1#include "SharedFuncsForRigidBody.h"
5 __global__ void SF_ApplyTransform(
6 DArrayList<Transform3f> instanceTransform,
7 const DArray<Vec3f> translate,
8 const DArray<Mat3f> rotation,
9 const DArray<Pair<uint, uint>> binding,
10 const DArray<int> bindingtag)
12 int tId = threadIdx.x + blockIdx.x * blockDim.x;
13 if (tId >= rotation.size())
15 if (bindingtag[tId] == 0)
18 Pair<uint, uint> pair = binding[tId];
20 Mat3f rot = rotation[tId];
22 Transform3f ti = Transform3f(translate[tId], rot);
24 instanceTransform[pair.first][pair.second] = ti;
28 DArrayList<Transform3f>& instanceTransform,
29 const DArray<Vec3f>& translate,
30 const DArray<Mat3f>& rotation,
31 const DArray<Pair<uint, uint>>& binding,
32 const DArray<int>& bindingtag)
34 cuExecute(rotation.size(),
45 * Update Velocity Function
47 * @param velocity velocity of rigids
48 * @param angular_velocity angular velocity of rigids
49 * @param impulse impulse exert on rigids
50 * @param linearDamping damping ratio of linear velocity
51 * @param angularDamping damping ratio of angular velocity
53 * This function update the velocity of rigids based on impulse
55 __global__ void SF_updateVelocity(
56 DArray<Attribute> attribute,
57 DArray<Vec3f> velocity,
58 DArray<Vec3f> angular_velocity,
59 DArray<Vec3f> impulse,
65 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
66 if (tId >= velocity.size())
69 if (attribute[tId].isDynamic())
71 velocity[tId] += impulse[2 * tId];
72 angular_velocity[tId] += impulse[2 * tId + 1];
74 /*velocity[tId] *= 1.0f / (1.0f + dt * linearDamping);
75 angular_velocity[tId] *= 1.0f / (1.0f + dt * angularDamping);*/
80 DArray<Attribute> attribute,
81 DArray<Vec3f> velocity,
82 DArray<Vec3f> angular_velocity,
83 DArray<Vec3f> impulse,
89 cuExecute(velocity.size(),
102 * Update Gesture Function
104 * @param pos position of rigids
105 * @param rotQuat quaterion of rigids
106 * @param rotMat rotation matrix of rigids
107 * @param inertia inertia matrix of rigids
108 * @param velocity velocity of rigids
109 * @param angular_velocity angular velocity of rigids
110 * @param inertia_init initial inertial matrix of rigids
111 * @param dt time step
112 * This function update the gesture of rigids based on velocity and timeStep
114 __global__ void SF_updateGesture(
115 DArray<Attribute> attribute,
117 DArray<Quat1f> rotQuat,
118 DArray<Mat3f> rotMat,
119 DArray<Mat3f> inertia,
120 DArray<Vec3f> velocity,
121 DArray<Vec3f> angular_velocity,
122 DArray<Mat3f> inertia_init,
126 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
127 if (tId >= pos.size())
130 if (!attribute[tId].isFixed())
132 pos[tId] += velocity[tId] * dt;
134 rotQuat[tId] = rotQuat[tId].normalize();
136 rotQuat[tId] += dt * 0.5f *
137 Quat1f(angular_velocity[tId][0], angular_velocity[tId][1], angular_velocity[tId][2], 0.0)
140 rotQuat[tId] = rotQuat[tId].normalize();
142 rotMat[tId] = rotQuat[tId].toMatrix3x3();
144 inertia[tId] = rotMat[tId] * inertia_init[tId] * rotMat[tId].inverse();
149 DArray<Attribute> attribute,
151 DArray<Quat1f> rotQuat,
152 DArray<Mat3f> rotMat,
153 DArray<Mat3f> inertia,
154 DArray<Vec3f> velocity,
155 DArray<Vec3f> angular_velocity,
156 DArray<Mat3f> inertia_init,
160 cuExecute(pos.size(),
174 * update the position and rotation of rigids
176 * @param pos position of rigids
177 * @param rotQuat quaterion of rigids
178 * @param rotMat rotation matrix of rigids
179 * @param inertia inertia matrix of rigids
180 * @param inertia_init initial inertia matrix of rigids
181 * @param impulse_constrain impulse to update position and rotation
182 * This function update the position of rigids use delta position
184 __global__ void SF_updatePositionAndRotation(
186 DArray<Quat1f> rotQuat,
187 DArray<Mat3f> rotMat,
188 DArray<Mat3f> inertia,
189 DArray<Mat3f> inertia_init,
190 DArray<Vec3f> impulse_constrain
193 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
194 if (tId >= pos.size())
196 Vec3f dx = impulse_constrain[2 * tId];
197 Vec3f dq = impulse_constrain[2 * tId + 1];
199 pos[tId] += impulse_constrain[2 * tId];
200 rotQuat[tId] += 0.5 * Quat1f(dq.x, dq.y, dq.z, 0.0f) * rotQuat[tId];
202 rotQuat[tId] = rotQuat[tId].normalize();
203 rotMat[tId] = rotQuat[tId].toMatrix3x3();
204 inertia[tId] = rotMat[tId] * inertia_init[tId] * rotMat[tId].inverse();
207 void updatePositionAndRotation(
209 DArray<Quat1f> rotQuat,
210 DArray<Mat3f> rotMat,
211 DArray<Mat3f> inertia,
212 DArray<Mat3f> inertia_init,
213 DArray<Vec3f> impulse_constrain
216 cuExecute(pos.size(),
217 SF_updatePositionAndRotation,
227 * calculate contact point num function
229 * @param contacts contacts
230 * @param contactCnt contact num of each rigids
231 * This function calculate the contact num of each rigids
233 template<typename ContactPair>
234 __global__ void SF_calculateContactPoints(
235 DArray<ContactPair> contacts,
236 DArray<int> contactCnt
239 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
240 if (tId >= contacts.size())
243 int idx1 = contacts[tId].bodyId1;
244 int idx2 = contacts[tId].bodyId2;
246 atomicAdd(&contactCnt[idx1], 1);
249 atomicAdd(&contactCnt[idx2], 1);
252 void calculateContactPoints(
253 DArray<TContactPair<float>> contacts,
254 DArray<int> contactCnt
257 cuExecute(contacts.size(),
258 SF_calculateContactPoints,
265 * calculate Jacobian Matrix function
267 * @param J Jacobian Matrix
268 * @param B M^-1J Matrix
269 * @param pos postion of rigids
270 * @param inertia inertia matrix of rigids
271 * @param mass mass of rigids
272 * @param rotMat rotation Matrix of rigids
273 * @param constraints constraints data
274 * This function calculate the Jacobian Matrix of constraints
276 template<typename Coord, typename Matrix, typename Constraint>
277 __global__ void SF_calculateJacobianMatrix(
281 DArray<Matrix> inertia,
283 DArray<Matrix> rotMat,
284 DArray<Constraint> constraints
287 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
288 if (tId >= constraints.size())
291 int idx1 = constraints[tId].bodyId1;
292 int idx2 = constraints[tId].bodyId2;
294 if (constraints[tId].type == ConstraintType::CN_NONPENETRATION || constraints[tId].type == ConstraintType::CN_FRICTION)
296 Coord n = constraints[tId].normal1;
297 Coord r1 = constraints[tId].pos1 - pos[idx1];
298 Coord rcn_1 = r1.cross(n);
301 J[4 * tId + 1] = -rcn_1;
302 B[4 * tId] = -n / mass[idx1];
303 B[4 * tId + 1] = -inertia[idx1].inverse() * rcn_1;
307 Coord r2 = constraints[tId].pos2 - pos[idx2];
308 Coord rcn_2 = r2.cross(n);
310 J[4 * tId + 3] = rcn_2;
311 B[4 * tId + 2] = n / mass[idx2];
312 B[4 * tId + 3] = inertia[idx2].inverse() * rcn_2;
316 if (constraints[tId].type == ConstraintType::CN_ANCHOR_EQUAL_1)
318 Coord r1 = constraints[tId].normal1;
319 Coord r2 = constraints[tId].normal2;
322 J[4 * tId] = Coord(-1, 0, 0);
323 J[4 * tId + 1] = Coord(0, -r1[2], r1[1]);
326 J[4 * tId + 2] = Coord(1, 0, 0);
327 J[4 * tId + 3] = Coord(0, r2[2], -r2[1]);
330 B[4 * tId] = Coord(-1, 0, 0) / mass[idx1];
331 B[4 * tId + 1] = inertia[idx1].inverse() * Coord(0, -r1[2], r1[1]);
334 B[4 * tId + 2] = Coord(1, 0, 0) / mass[idx2];
335 B[4 * tId + 3] = inertia[idx2].inverse() * Coord(0, r2[2], -r2[1]);
339 if (constraints[tId].type == ConstraintType::CN_ANCHOR_EQUAL_2)
341 Coord r1 = constraints[tId].normal1;
342 Coord r2 = constraints[tId].normal2;
344 J[4 * tId] = Coord(0, -1, 0);
345 J[4 * tId + 1] = Coord(r1[2], 0, -r1[0]);
348 J[4 * tId + 2] = Coord(0, 1, 0);
349 J[4 * tId + 3] = Coord(-r2[2], 0, r2[0]);
352 B[4 * tId] = Coord(0, -1, 0) / mass[idx1];
353 B[4 * tId + 1] = inertia[idx1].inverse() * Coord(r1[2], 0, -r1[0]);
356 B[4 * tId + 2] = Coord(0, 1, 0) / mass[idx2];
357 B[4 * tId + 3] = inertia[idx2].inverse() * Coord(-r2[2], 0, r2[0]);
361 if (constraints[tId].type == ConstraintType::CN_ANCHOR_EQUAL_3)
363 Coord r1 = constraints[tId].normal1;
364 Coord r2 = constraints[tId].normal2;
366 J[4 * tId] = Coord(0, 0, -1);
367 J[4 * tId + 1] = Coord(-r1[1], r1[0], 0);
370 J[4 * tId + 2] = Coord(0, 0, 1);
371 J[4 * tId + 3] = Coord(r2[1], -r2[0], 0);
374 B[4 * tId] = Coord(0, 0, -1) / mass[idx1];
375 B[4 * tId + 1] = inertia[idx1].inverse() * Coord(-r1[1], r1[0], 0);
378 B[4 * tId + 2] = Coord(0, 0, 1) / mass[idx2];
379 B[4 * tId + 3] = inertia[idx2].inverse() * Coord(r2[1], -r2[0], 0);
383 if (constraints[tId].type == ConstraintType::CN_ANCHOR_TRANS_1)
385 Coord r1 = constraints[tId].pos1;
386 Coord r2 = constraints[tId].pos2;
388 Coord n1 = constraints[tId].normal1;
391 J[4 * tId + 1] = -(pos[idx2] + r2 - pos[idx1]).cross(n1);
393 J[4 * tId + 3] = r2.cross(n1);
395 B[4 * tId] = -n1 / mass[idx1];
396 B[4 * tId + 1] = inertia[idx1].inverse() * J[4 * tId + 1];
397 B[4 * tId + 2] = n1 / mass[idx2];
398 B[4 * tId + 3] = inertia[idx2].inverse() * J[4 * tId + 3];
401 if (constraints[tId].type == ConstraintType::CN_ANCHOR_TRANS_2)
403 Coord r1 = constraints[tId].pos1;
404 Coord r2 = constraints[tId].pos2;
406 Coord n2 = constraints[tId].normal2;
409 J[4 * tId + 1] = -(pos[idx2] + r2 - pos[idx1]).cross(n2);
411 J[4 * tId + 3] = r2.cross(n2);
413 B[4 * tId] = -n2 / mass[idx1];
414 B[4 * tId + 1] = inertia[idx1].inverse() * J[4 * tId + 1];
415 B[4 * tId + 2] = n2 / mass[idx2];
416 B[4 * tId + 3] = inertia[idx2].inverse() * J[4 * tId + 3];
419 if (constraints[tId].type == ConstraintType::CN_BAN_ROT_1)
421 J[4 * tId] = Coord(0);
422 J[4 * tId + 1] = Coord(-1, 0, 0);
425 J[4 * tId + 2] = Coord(0);
426 J[4 * tId + 3] = Coord(1, 0, 0);
429 B[4 * tId] = Coord(0);
430 B[4 * tId + 1] = inertia[idx1].inverse() * Coord(-1, 0, 0);
433 B[4 * tId + 2] = Coord(0);
434 B[4 * tId + 3] = inertia[idx2].inverse() * Coord(1, 0, 0);
438 if (constraints[tId].type == ConstraintType::CN_BAN_ROT_2)
440 J[4 * tId] = Coord(0);
441 J[4 * tId + 1] = Coord(0, -1, 0);
444 J[4 * tId + 2] = Coord(0);
445 J[4 * tId + 3] = Coord(0, 1, 0);
448 B[4 * tId] = Coord(0);
449 B[4 * tId + 1] = inertia[idx1].inverse() * Coord(0, -1, 0);
452 B[4 * tId + 2] = Coord(0);
453 B[4 * tId + 3] = inertia[idx2].inverse() * Coord(0, 1, 0);
457 if (constraints[tId].type == ConstraintType::CN_BAN_ROT_3)
459 J[4 * tId] = Coord(0);
460 J[4 * tId + 1] = Coord(0, 0, -1);
463 J[4 * tId + 2] = Coord(0);
464 J[4 * tId + 3] = Coord(0, 0, 1);
467 B[4 * tId] = Coord(0);
468 B[4 * tId + 1] = inertia[idx1].inverse() * Coord(0, 0, -1);
471 B[4 * tId + 2] = Coord(0);
472 B[4 * tId + 3] = inertia[idx2].inverse() * Coord(0, 0, 1);
476 if (constraints[tId].type == ConstraintType::CN_JOINT_SLIDER_MOTER)
478 if (constraints[tId].isValid)
480 Coord n = constraints[tId].axis;
483 J[4 * tId + 1] = Coord(0);
485 J[4 * tId + 3] = Coord(0);
487 B[4 * tId] = n / mass[idx1];
488 B[4 * tId + 1] = Coord(0);
489 B[4 * tId + 2] = -n / mass[idx2];
490 B[4 * tId + 3] = Coord(0);
494 if (constraints[tId].type == ConstraintType::CN_JOINT_SLIDER_MIN)
496 if (constraints[tId].isValid)
498 Coord a = constraints[tId].axis;
499 Coord r1 = constraints[tId].pos1;
500 Coord r2 = constraints[tId].pos2;
503 J[4 * tId + 1] = -(pos[idx2] + r2 - pos[idx1]).cross(a);
505 J[4 * tId + 3] = r2.cross(a);
507 B[4 * tId] = -a / mass[idx1];
508 B[4 * tId + 1] = inertia[idx1].inverse() * J[4 * tId + 1];
509 B[4 * tId + 2] = a / mass[idx2];
510 B[4 * tId + 3] = inertia[idx2].inverse() * J[4 * tId + 3];
514 if (constraints[tId].type == ConstraintType::CN_JOINT_SLIDER_MAX)
516 if (constraints[tId].isValid)
518 Coord a = constraints[tId].axis;
519 Coord r1 = constraints[tId].pos1;
520 Coord r2 = constraints[tId].pos2;
523 J[4 * tId + 1] = (pos[idx2] + r2 - pos[idx1]).cross(a);
525 J[4 * tId + 3] = -r2.cross(a);
527 B[4 * tId] = a / mass[idx1];
528 B[4 * tId + 1] = inertia[idx1].inverse() * J[4 * tId + 1];
529 B[4 * tId + 2] = -a / mass[idx2];
530 B[4 * tId + 3] = inertia[idx2].inverse() * J[4 * tId + 3];
534 if (constraints[tId].type == ConstraintType::CN_ALLOW_ROT1D_1)
536 Coord b2 = constraints[tId].pos1;
537 Coord a1 = constraints[tId].axis;
539 J[4 * tId] = Coord(0);
540 J[4 * tId + 1] = -b2.cross(a1);
541 J[4 * tId + 2] = Coord(0);
542 J[4 * tId + 3] = b2.cross(a1);
544 B[4 * tId] = Coord(0);
545 B[4 * tId + 1] = inertia[idx1].inverse() * J[4 * tId + 1];
546 B[4 * tId + 2] = Coord(0);
547 B[4 * tId + 3] = inertia[idx2].inverse() * J[4 * tId + 3];
550 if (constraints[tId].type == ConstraintType::CN_ALLOW_ROT1D_2)
552 Coord c2 = constraints[tId].pos2;
553 Coord a1 = constraints[tId].axis;
555 J[4 * tId] = Coord(0);
556 J[4 * tId + 1] = -c2.cross(a1);
557 J[4 * tId + 2] = Coord(0);
558 J[4 * tId + 3] = c2.cross(a1);
560 B[4 * tId] = Coord(0);
561 B[4 * tId + 1] = inertia[idx1].inverse() * J[4 * tId + 1];
562 B[4 * tId + 2] = Coord(0);
563 B[4 * tId + 3] = inertia[idx2].inverse() * J[4 * tId + 3];
566 if (constraints[tId].type == ConstraintType::CN_JOINT_HINGE_MIN)
568 if (constraints[tId].isValid == 1)
570 Coord a = constraints[tId].axis;
571 J[4 * tId] = Coord(0);
573 J[4 * tId + 2] = Coord(0);
576 B[4 * tId] = Coord(0);
577 B[4 * tId + 1] = inertia[idx1].inverse() * (-a);
578 B[4 * tId + 2] = Coord(0);
579 B[4 * tId + 3] = inertia[idx2].inverse() * (a);
583 if (constraints[tId].type == ConstraintType::CN_JOINT_HINGE_MAX)
585 if (constraints[tId].isValid == 1)
587 Coord a = constraints[tId].axis;
588 J[4 * tId] = Coord(0);
590 J[4 * tId + 2] = Coord(0);
593 B[4 * tId] = Coord(0);
594 B[4 * tId + 1] = inertia[idx1].inverse() * (a);
595 B[4 * tId + 2] = Coord(0);
596 B[4 * tId + 3] = inertia[idx2].inverse() * (-a);
600 if (constraints[tId].type == ConstraintType::CN_JOINT_HINGE_MOTER)
602 if (constraints[tId].isValid)
604 Coord a = constraints[tId].axis;
605 J[4 * tId] = Coord(0);
607 J[4 * tId + 2] = Coord(0);
610 B[4 * tId] = Coord(0);
611 B[4 * tId + 1] = inertia[idx1].inverse() * (-a);
612 B[4 * tId + 2] = Coord(0);
613 B[4 * tId + 3] = inertia[idx2].inverse() * a;
617 if (constraints[tId].type == ConstraintType::CN_JOINT_NO_MOVE_1)
619 J[4 * tId] = Coord(1.0, 0, 0);
620 J[4 * tId + 1] = Coord(0);
621 J[4 * tId + 2] = Coord(0);
622 J[4 * tId + 3] = Coord(0);
624 B[4 * tId] = Coord(1 / mass[idx1], 0, 0);
625 B[4 * tId + 1] = Coord(0);
626 B[4 * tId + 2] = Coord(0);
627 B[4 * tId + 3] = Coord(0);
630 if (constraints[tId].type == ConstraintType::CN_JOINT_NO_MOVE_2)
632 J[4 * tId] = Coord(0, 1.0, 0);
633 J[4 * tId + 1] = Coord(0);
634 J[4 * tId + 2] = Coord(0);
635 J[4 * tId + 3] = Coord(0);
637 B[4 * tId] = Coord(0, 1.0 / mass[idx1], 0);
638 B[4 * tId + 1] = Coord(0);
639 B[4 * tId + 2] = Coord(0);
640 B[4 * tId + 3] = Coord(0);
643 if (constraints[tId].type == ConstraintType::CN_JOINT_NO_MOVE_3)
645 J[4 * tId] = Coord(0, 0, 1.0);
646 J[4 * tId + 1] = Coord(0);
647 J[4 * tId + 2] = Coord(0);
648 J[4 * tId + 3] = Coord(0);
650 B[4 * tId] = Coord(0, 0, 1.0 / mass[idx1]);
651 B[4 * tId + 1] = Coord(0);
652 B[4 * tId + 2] = Coord(0);
653 B[4 * tId + 3] = Coord(0);
657 template<typename Coord, typename Matrix, typename Constraint>
658 __global__ void SF_calculateJacobianMatrixForNJS(
662 DArray<Matrix> inertia,
664 DArray<Matrix> rotMat,
665 DArray<Constraint> constraints
668 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
669 if (tId >= constraints.size())
672 int idx1 = constraints[tId].bodyId1;
673 int idx2 = constraints[tId].bodyId2;
675 if (constraints[tId].type == ConstraintType::CN_NONPENETRATION)
677 Coord n = constraints[tId].normal1;
678 Coord r1 = constraints[tId].pos1 - pos[idx1];
679 Coord rcn_1 = r1.cross(n);
682 J[4 * tId + 1] = -rcn_1;
683 B[4 * tId] = -n / mass[idx1];
684 B[4 * tId + 1] = -inertia[idx1].inverse() * rcn_1;
688 Coord r2 = constraints[tId].pos2 - pos[idx2];
689 Coord rcn_2 = r2.cross(n);
691 J[4 * tId + 3] = rcn_2;
692 B[4 * tId + 2] = n / mass[idx2];
693 B[4 * tId + 3] = inertia[idx2].inverse() * rcn_2;
697 if (constraints[tId].type == ConstraintType::CN_ANCHOR_EQUAL_1)
699 Coord r1 = constraints[tId].normal1;
700 Coord r2 = constraints[tId].normal2;
703 J[4 * tId] = Coord(-1, 0, 0);
704 J[4 * tId + 1] = Coord(0, -r1[2], r1[1]);
707 J[4 * tId + 2] = Coord(1, 0, 0);
708 J[4 * tId + 3] = Coord(0, r2[2], -r2[1]);
711 B[4 * tId] = Coord(-1, 0, 0) / mass[idx1];
712 B[4 * tId + 1] = inertia[idx1].inverse() * Coord(0, -r1[2], r1[1]);
715 B[4 * tId + 2] = Coord(1, 0, 0) / mass[idx2];
716 B[4 * tId + 3] = inertia[idx2].inverse() * Coord(0, r2[2], -r2[1]);
720 if (constraints[tId].type == ConstraintType::CN_ANCHOR_EQUAL_2)
722 Coord r1 = constraints[tId].normal1;
723 Coord r2 = constraints[tId].normal2;
725 J[4 * tId] = Coord(0, -1, 0);
726 J[4 * tId + 1] = Coord(r1[2], 0, -r1[0]);
729 J[4 * tId + 2] = Coord(0, 1, 0);
730 J[4 * tId + 3] = Coord(-r2[2], 0, r2[0]);
733 B[4 * tId] = Coord(0, -1, 0) / mass[idx1];
734 B[4 * tId + 1] = inertia[idx1].inverse() * Coord(r1[2], 0, -r1[0]);
737 B[4 * tId + 2] = Coord(0, 1, 0) / mass[idx2];
738 B[4 * tId + 3] = inertia[idx2].inverse() * Coord(-r2[2], 0, r2[0]);
742 if (constraints[tId].type == ConstraintType::CN_ANCHOR_EQUAL_3)
744 Coord r1 = constraints[tId].normal1;
745 Coord r2 = constraints[tId].normal2;
747 J[4 * tId] = Coord(0, 0, -1);
748 J[4 * tId + 1] = Coord(-r1[1], r1[0], 0);
751 J[4 * tId + 2] = Coord(0, 0, 1);
752 J[4 * tId + 3] = Coord(r2[1], -r2[0], 0);
755 B[4 * tId] = Coord(0, 0, -1) / mass[idx1];
756 B[4 * tId + 1] = inertia[idx1].inverse() * Coord(-r1[1], r1[0], 0);
759 B[4 * tId + 2] = Coord(0, 0, 1) / mass[idx2];
760 B[4 * tId + 3] = inertia[idx2].inverse() * Coord(r2[1], -r2[0], 0);
764 if (constraints[tId].type == ConstraintType::CN_ANCHOR_TRANS_1)
766 Coord r1 = constraints[tId].pos1;
767 Coord r2 = constraints[tId].pos2;
769 Coord n1 = constraints[tId].normal1;
772 J[4 * tId + 1] = -(pos[idx2] + r2 - pos[idx1]).cross(n1);
774 J[4 * tId + 3] = r2.cross(n1);
776 B[4 * tId] = -n1 / mass[idx1];
777 B[4 * tId + 1] = inertia[idx1].inverse() * J[4 * tId + 1];
778 B[4 * tId + 2] = n1 / mass[idx2];
779 B[4 * tId + 3] = inertia[idx2].inverse() * J[4 * tId + 3];
782 if (constraints[tId].type == ConstraintType::CN_ANCHOR_TRANS_2)
784 Coord r1 = constraints[tId].pos1;
785 Coord r2 = constraints[tId].pos2;
787 Coord n2 = constraints[tId].normal2;
790 J[4 * tId + 1] = -(pos[idx2] + r2 - pos[idx1]).cross(n2);
792 J[4 * tId + 3] = r2.cross(n2);
794 B[4 * tId] = -n2 / mass[idx1];
795 B[4 * tId + 1] = inertia[idx1].inverse() * J[4 * tId + 1];
796 B[4 * tId + 2] = n2 / mass[idx2];
797 B[4 * tId + 3] = inertia[idx2].inverse() * J[4 * tId + 3];
800 if (constraints[tId].type == ConstraintType::CN_BAN_ROT_1)
802 J[4 * tId] = Coord(0);
803 J[4 * tId + 1] = Coord(-1, 0, 0);
806 J[4 * tId + 2] = Coord(0);
807 J[4 * tId + 3] = Coord(1, 0, 0);
810 B[4 * tId] = Coord(0);
811 B[4 * tId + 1] = inertia[idx1].inverse() * Coord(-1, 0, 0);
814 B[4 * tId + 2] = Coord(0);
815 B[4 * tId + 3] = inertia[idx2].inverse() * Coord(1, 0, 0);
819 if (constraints[tId].type == ConstraintType::CN_BAN_ROT_2)
821 J[4 * tId] = Coord(0);
822 J[4 * tId + 1] = Coord(0, -1, 0);
825 J[4 * tId + 2] = Coord(0);
826 J[4 * tId + 3] = Coord(0, 1, 0);
829 B[4 * tId] = Coord(0);
830 B[4 * tId + 1] = inertia[idx1].inverse() * Coord(0, -1, 0);
833 B[4 * tId + 2] = Coord(0);
834 B[4 * tId + 3] = inertia[idx2].inverse() * Coord(0, 1, 0);
838 if (constraints[tId].type == ConstraintType::CN_BAN_ROT_3)
840 J[4 * tId] = Coord(0);
841 J[4 * tId + 1] = Coord(0, 0, -1);
844 J[4 * tId + 2] = Coord(0);
845 J[4 * tId + 3] = Coord(0, 0, 1);
848 B[4 * tId] = Coord(0);
849 B[4 * tId + 1] = inertia[idx1].inverse() * Coord(0, 0, -1);
852 B[4 * tId + 2] = Coord(0);
853 B[4 * tId + 3] = inertia[idx2].inverse() * Coord(0, 0, 1);
858 if (constraints[tId].type == ConstraintType::CN_JOINT_SLIDER_MIN)
860 if (constraints[tId].isValid)
862 Coord a = constraints[tId].axis;
863 Coord r1 = constraints[tId].pos1;
864 Coord r2 = constraints[tId].pos2;
867 J[4 * tId + 1] = -(pos[idx2] + r2 - pos[idx1]).cross(a);
869 J[4 * tId + 3] = r2.cross(a);
871 B[4 * tId] = -a / mass[idx1];
872 B[4 * tId + 1] = inertia[idx1].inverse() * J[4 * tId + 1];
873 B[4 * tId + 2] = a / mass[idx2];
874 B[4 * tId + 3] = inertia[idx2].inverse() * J[4 * tId + 3];
878 if (constraints[tId].type == ConstraintType::CN_JOINT_SLIDER_MAX)
880 if (constraints[tId].isValid)
882 Coord a = constraints[tId].axis;
883 Coord r1 = constraints[tId].pos1;
884 Coord r2 = constraints[tId].pos2;
887 J[4 * tId + 1] = (pos[idx2] + r2 - pos[idx1]).cross(a);
889 J[4 * tId + 3] = -r2.cross(a);
891 B[4 * tId] = a / mass[idx1];
892 B[4 * tId + 1] = inertia[idx1].inverse() * J[4 * tId + 1];
893 B[4 * tId + 2] = -a / mass[idx2];
894 B[4 * tId + 3] = inertia[idx2].inverse() * J[4 * tId + 3];
898 if (constraints[tId].type == ConstraintType::CN_ALLOW_ROT1D_1)
900 Coord b2 = constraints[tId].pos1;
901 Coord a1 = constraints[tId].axis;
903 J[4 * tId] = Coord(0);
904 J[4 * tId + 1] = -b2.cross(a1);
905 J[4 * tId + 2] = Coord(0);
906 J[4 * tId + 3] = b2.cross(a1);
908 B[4 * tId] = Coord(0);
909 B[4 * tId + 1] = inertia[idx1].inverse() * J[4 * tId + 1];
910 B[4 * tId + 2] = Coord(0);
911 B[4 * tId + 3] = inertia[idx2].inverse() * J[4 * tId + 3];
914 if (constraints[tId].type == ConstraintType::CN_ALLOW_ROT1D_2)
916 Coord c2 = constraints[tId].pos2;
917 Coord a1 = constraints[tId].axis;
919 J[4 * tId] = Coord(0);
920 J[4 * tId + 1] = -c2.cross(a1);
921 J[4 * tId + 2] = Coord(0);
922 J[4 * tId + 3] = c2.cross(a1);
924 B[4 * tId] = Coord(0);
925 B[4 * tId + 1] = inertia[idx1].inverse() * J[4 * tId + 1];
926 B[4 * tId + 2] = Coord(0);
927 B[4 * tId + 3] = inertia[idx2].inverse() * J[4 * tId + 3];
930 if (constraints[tId].type == ConstraintType::CN_JOINT_HINGE_MIN)
932 if (constraints[tId].isValid == 1)
934 Coord a = constraints[tId].axis;
935 J[4 * tId] = Coord(0);
937 J[4 * tId + 2] = Coord(0);
940 B[4 * tId] = Coord(0);
941 B[4 * tId + 1] = inertia[idx1].inverse() * (-a);
942 B[4 * tId + 2] = Coord(0);
943 B[4 * tId + 3] = inertia[idx2].inverse() * (a);
947 if (constraints[tId].type == ConstraintType::CN_JOINT_HINGE_MAX)
949 if (constraints[tId].isValid == 1)
951 Coord a = constraints[tId].axis;
952 J[4 * tId] = Coord(0);
954 J[4 * tId + 2] = Coord(0);
957 B[4 * tId] = Coord(0);
958 B[4 * tId + 1] = inertia[idx1].inverse() * (a);
959 B[4 * tId + 2] = Coord(0);
960 B[4 * tId + 3] = inertia[idx2].inverse() * (-a);
964 if (constraints[tId].type == ConstraintType::CN_JOINT_NO_MOVE_1)
966 J[4 * tId] = Coord(1.0, 0, 0);
967 J[4 * tId + 1] = Coord(0);
968 J[4 * tId + 2] = Coord(0);
969 J[4 * tId + 3] = Coord(0);
971 B[4 * tId] = Coord(1 / mass[idx1], 0, 0);
972 B[4 * tId + 1] = Coord(0);
973 B[4 * tId + 2] = Coord(0);
974 B[4 * tId + 3] = Coord(0);
977 if (constraints[tId].type == ConstraintType::CN_JOINT_NO_MOVE_2)
979 J[4 * tId] = Coord(0, 1.0, 0);
980 J[4 * tId + 1] = Coord(0);
981 J[4 * tId + 2] = Coord(0);
982 J[4 * tId + 3] = Coord(0);
984 B[4 * tId] = Coord(0, 1.0 / mass[idx1], 0);
985 B[4 * tId + 1] = Coord(0);
986 B[4 * tId + 2] = Coord(0);
987 B[4 * tId + 3] = Coord(0);
990 if (constraints[tId].type == ConstraintType::CN_JOINT_NO_MOVE_3)
992 J[4 * tId] = Coord(0, 0, 1.0);
993 J[4 * tId + 1] = Coord(0);
994 J[4 * tId + 2] = Coord(0);
995 J[4 * tId + 3] = Coord(0);
997 B[4 * tId] = Coord(0, 0, 1.0 / mass[idx1]);
998 B[4 * tId + 1] = Coord(0);
999 B[4 * tId + 2] = Coord(0);
1000 B[4 * tId + 3] = Coord(0);
1004 void calculateJacobianMatrix(
1008 DArray<Mat3f> inertia,
1010 DArray<Mat3f> rotMat,
1011 DArray<TConstraintPair<float>> constraints
1014 cuExecute(constraints.size(),
1015 SF_calculateJacobianMatrix,
1025 void calculateJacobianMatrixForNJS(
1029 DArray<Mat3f> inertia,
1031 DArray<Mat3f> rotMat,
1032 DArray<TConstraintPair<float>> constraints
1035 cuExecute(constraints.size(),
1036 SF_calculateJacobianMatrixForNJS,
1048 * calculate eta vector for PJS
1050 * @param eta eta vector
1051 * @param J Jacobian Matrix
1052 * @param velocity linear velocity of rigids
1053 * @param angular_velocity angular velocity of rigids
1054 * @param constraints constraints data
1055 * This function calculate the diagonal Matrix of JB
1057 template<typename Coord, typename Constraint, typename Real>
1058 __global__ void SF_calculateEtaVectorForPJS(
1061 DArray<Coord> velocity,
1062 DArray<Coord> angular_velocity,
1063 DArray<Constraint> constraints
1066 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
1067 if (tId >= constraints.size())
1070 int idx1 = constraints[tId].bodyId1;
1071 int idx2 = constraints[tId].bodyId2;
1073 Real eta_i = Real(0);
1075 eta_i -= J[4 * tId].dot(velocity[idx1]);
1076 eta_i -= J[4 * tId + 1].dot(angular_velocity[idx1]);
1078 if (idx2 != INVALID)
1080 eta_i -= J[4 * tId + 2].dot(velocity[idx2]);
1081 eta_i -= J[4 * tId + 3].dot(angular_velocity[idx2]);
1086 if (constraints[tId].type == ConstraintType::CN_JOINT_SLIDER_MOTER || constraints[tId].type == ConstraintType::CN_JOINT_HINGE_MOTER)
1088 Real v_moter = constraints[tId].interpenetration;
1089 eta[tId] -= v_moter;
1093 void calculateEtaVectorForPJS(
1096 DArray<Vec3f> velocity,
1097 DArray<Vec3f> angular_velocity,
1098 DArray<TConstraintPair<float>> constraints
1101 cuExecute(constraints.size(),
1102 SF_calculateEtaVectorForPJS,
1111 * calculate eta vector for PJS Baumgarte stabilization
1113 * @param eta eta vector
1114 * @param J Jacobian Matrix
1115 * @param velocity linear velocity of rigids
1116 * @param angular_velocity angular velocity of rigids
1117 * @param pos position of rigids
1118 * @param rotation_q quarterion of rigids
1119 * @param constraints constraints data
1120 * @param slop interpenetration slop
1121 * @param beta Baumgarte bias
1122 * @param dt time step
1123 * This function calculate the diagonal Matrix of JB
1125 template<typename Coord, typename Constraint, typename Real, typename Quat>
1126 __global__ void SF_calculateEtaVectorForPJSBaumgarte(
1129 DArray<Coord> velocity,
1130 DArray<Coord> angular_velocity,
1132 DArray<Quat> rotation_q,
1133 DArray<Constraint> constraints,
1134 DArray<Real> errors,
1141 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
1142 if (tId >= constraints.size())
1145 int idx1 = constraints[tId].bodyId1;
1146 int idx2 = constraints[tId].bodyId2;
1148 Real eta_i = Real(0);
1150 eta_i -= J[4 * tId].dot(velocity[idx1]);
1151 eta_i -= J[4 * tId + 1].dot(angular_velocity[idx1]);
1153 if (idx2 != INVALID)
1155 eta_i -= J[4 * tId + 2].dot(velocity[idx2]);
1156 eta_i -= J[4 * tId + 3].dot(angular_velocity[idx2]);
1161 Real invDt = Real(1) / dt;
1164 if (constraints[tId].type == ConstraintType::CN_JOINT_SLIDER_MOTER || constraints[tId].type == ConstraintType::CN_JOINT_HINGE_MOTER)
1166 Real v_moter = constraints[tId].interpenetration;
1167 eta[tId] -= v_moter;
1170 if (constraints[tId].type == ConstraintType::CN_NONPENETRATION)
1172 error = minimum(constraints[tId].interpenetration + slop, 0.0f) / substepping;
1175 if (constraints[tId].type == ConstraintType::CN_ANCHOR_EQUAL_1)
1177 Coord r1 = constraints[tId].normal1;
1178 Coord r2 = constraints[tId].normal2;
1179 Coord pos1 = constraints[tId].pos1;
1182 errorVec = pos[idx2] + r2 - pos[idx1] - r1;
1184 errorVec = pos1 - pos[idx1] - r1;
1185 error = errorVec[0];
1188 if (constraints[tId].type == ConstraintType::CN_ANCHOR_EQUAL_2)
1190 Coord r1 = constraints[tId].normal1;
1191 Coord r2 = constraints[tId].normal2;
1192 Coord pos1 = constraints[tId].pos1;
1194 if (idx2 != INVALID)
1195 errorVec = pos[idx2] + r2 - pos[idx1] - r1;
1197 errorVec = pos1 - pos[idx1] - r1;
1198 error = errorVec[1];
1201 if (constraints[tId].type == ConstraintType::CN_ANCHOR_EQUAL_3)
1203 Coord r1 = constraints[tId].normal1;
1204 Coord r2 = constraints[tId].normal2;
1205 Coord pos1 = constraints[tId].pos1;
1207 if (idx2 != INVALID)
1208 errorVec = pos[idx2] + r2 - pos[idx1] - r1;
1210 errorVec = pos1 - pos[idx1] - r1;
1211 error = errorVec[2];
1214 if (constraints[tId].type == ConstraintType::CN_ANCHOR_TRANS_1)
1216 Coord r1 = constraints[tId].pos1;
1217 Coord r2 = constraints[tId].pos2;
1218 Coord n1 = constraints[tId].normal1;
1220 error = (pos[idx2] + r2 - pos[idx1] - r1).dot(n1);
1223 if (constraints[tId].type == ConstraintType::CN_ANCHOR_TRANS_2)
1225 Coord r1 = constraints[tId].pos1;
1226 Coord r2 = constraints[tId].pos2;
1227 Coord n2 = constraints[tId].normal2;
1229 error = (pos[idx2] + r2 - pos[idx1] - r1).dot(n2);
1232 if (constraints[tId].type == ConstraintType::CN_BAN_ROT_1)
1234 Quat q1 = rotation_q[idx1];
1235 if (idx2 != INVALID)
1237 Quat q2 = rotation_q[idx2];
1238 Quat q_init = constraints[tId].rotQuat;
1239 Quat q_error = q2 * q_init * q1.inverse();
1241 error = q_error.x * 2;
1245 Quat diff = rotation_q[idx1] * constraints[tId].rotQuat.inverse();
1246 error = -diff.x * 2;
1250 if (constraints[tId].type == ConstraintType::CN_BAN_ROT_2)
1252 Quat q1 = rotation_q[idx1];
1253 if (idx2 != INVALID)
1255 Quat q2 = rotation_q[idx2];
1256 Quat q_init = constraints[tId].rotQuat;
1257 Quat q_error = q2 * q_init * q1.inverse();
1259 error = q_error.y * 2;
1263 Quat diff = rotation_q[idx1] * constraints[tId].rotQuat.inverse();
1264 error = -diff.y * 2;
1268 if (constraints[tId].type == ConstraintType::CN_BAN_ROT_3)
1270 Quat q1 = rotation_q[idx1];
1271 if (idx2 != INVALID)
1273 Quat q2 = rotation_q[idx2];
1274 Quat q_init = constraints[tId].rotQuat;
1275 Quat q_error = q2 * q_init * q1.inverse();
1277 error = q_error.z * 2;
1281 Quat diff = rotation_q[idx1] * constraints[tId].rotQuat.inverse();
1282 error = -diff.z * 2;
1286 if (constraints[tId].type == ConstraintType::CN_JOINT_HINGE_MIN || constraints[tId].type == ConstraintType::CN_JOINT_SLIDER_MIN)
1288 error = constraints[tId].d_min;
1291 if (constraints[tId].type == ConstraintType::CN_JOINT_HINGE_MAX || constraints[tId].type == ConstraintType::CN_JOINT_SLIDER_MAX)
1293 error = constraints[tId].d_max;
1296 if (constraints[tId].type == ConstraintType::CN_ALLOW_ROT1D_1)
1298 Coord a1 = constraints[tId].axis;
1299 Coord b2 = constraints[tId].pos1;
1303 if (constraints[tId].type == ConstraintType::CN_ALLOW_ROT1D_2)
1305 Coord a1 = constraints[tId].axis;
1306 Coord c2 = constraints[tId].pos2;
1310 if (constraints[tId].type == ConstraintType::CN_JOINT_NO_MOVE_1)
1312 Coord errorVec = constraints[tId].normal1;
1313 error = errorVec[0];
1316 if (constraints[tId].type == ConstraintType::CN_JOINT_NO_MOVE_2)
1318 Coord errorVec = constraints[tId].normal1;
1319 error = errorVec[1];
1322 if (constraints[tId].type == ConstraintType::CN_JOINT_NO_MOVE_3)
1324 Coord errorVec = constraints[tId].normal1;
1325 error = errorVec[2];
1328 eta[tId] -= beta * invDt * error;
1329 errors[tId] = error;
1332 template<typename Coord, typename Constraint, typename Real, typename Quat>
1333 __global__ void SF_calculateEtaVectorWithERP(
1336 DArray<Coord> velocity,
1337 DArray<Coord> angular_velocity,
1339 DArray<Quat> rotation_q,
1340 DArray<Constraint> constraints,
1346 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
1347 if (tId >= constraints.size())
1350 if (!constraints[tId].isValid)
1353 Real invDt = Real(1) / dt;
1354 int idx1 = constraints[tId].bodyId1;
1355 int idx2 = constraints[tId].bodyId2;
1357 Real eta_i = Real(0);
1359 eta_i -= J[4 * tId].dot(velocity[idx1]);
1360 eta_i -= J[4 * tId + 1].dot(angular_velocity[idx1]);
1362 if (idx2 != INVALID)
1364 eta_i -= J[4 * tId + 2].dot(velocity[idx2]);
1365 eta_i -= J[4 * tId + 3].dot(angular_velocity[idx2]);
1372 if (constraints[tId].type == ConstraintType::CN_JOINT_SLIDER_MOTER || constraints[tId].type == ConstraintType::CN_JOINT_HINGE_MOTER)
1374 Real v_moter = constraints[tId].interpenetration;
1375 eta[tId] -= v_moter;
1378 if (constraints[tId].type == ConstraintType::CN_NONPENETRATION)
1380 error = minimum(constraints[tId].interpenetration + slop, 0.0f);
1383 if (constraints[tId].type == ConstraintType::CN_ANCHOR_EQUAL_1)
1385 Coord r1 = constraints[tId].normal1;
1386 Coord r2 = constraints[tId].normal2;
1387 Coord pos1 = constraints[tId].pos1;
1389 if (idx2 != INVALID)
1390 errorVec = pos[idx2] + r2 - pos[idx1] - r1;
1392 errorVec = pos1 - pos[idx1] - r1;
1393 error = errorVec[0];
1396 if (constraints[tId].type == ConstraintType::CN_ANCHOR_EQUAL_2)
1398 Coord r1 = constraints[tId].normal1;
1399 Coord r2 = constraints[tId].normal2;
1400 Coord pos1 = constraints[tId].pos1;
1402 if (idx2 != INVALID)
1403 errorVec = pos[idx2] + r2 - pos[idx1] - r1;
1405 errorVec = pos1 - pos[idx1] - r1;
1406 error = errorVec[1];
1409 if (constraints[tId].type == ConstraintType::CN_ANCHOR_EQUAL_3)
1411 Coord r1 = constraints[tId].normal1;
1412 Coord r2 = constraints[tId].normal2;
1413 Coord pos1 = constraints[tId].pos1;
1415 if (idx2 != INVALID)
1416 errorVec = pos[idx2] + r2 - pos[idx1] - r1;
1418 errorVec = pos1 - pos[idx1] - r1;
1419 error = errorVec[2];
1422 if (constraints[tId].type == ConstraintType::CN_ANCHOR_TRANS_1)
1424 Coord r1 = constraints[tId].pos1;
1425 Coord r2 = constraints[tId].pos2;
1426 Coord n1 = constraints[tId].normal1;
1428 error = (pos[idx2] + r2 - pos[idx1] - r1).dot(n1);
1431 if (constraints[tId].type == ConstraintType::CN_ANCHOR_TRANS_2)
1433 Coord r1 = constraints[tId].pos1;
1434 Coord r2 = constraints[tId].pos2;
1435 Coord n2 = constraints[tId].normal2;
1437 error = (pos[idx2] + r2 - pos[idx1] - r1).dot(n2);
1440 if (constraints[tId].type == ConstraintType::CN_BAN_ROT_1)
1442 Quat q1 = rotation_q[idx1];
1443 q1 = q1.normalize();
1444 if (idx2 != INVALID)
1446 Quat q2 = rotation_q[idx2];
1447 q2 = q2.normalize();
1449 Quat q_error = q2 * q1.inverse();
1450 q_error = q_error.normalize();
1452 Real theta = 2.0 * acos(q_error.w);
1455 Vec3f v = (1 / sin(theta / 2.0)) * Vec3f(q_error.x, q_error.y, q_error.z);
1456 error = theta * v.x;
1465 Real theta = 2.0 * acos(q1.w);
1468 Vec3f v = (1 / sin(theta / 2.0)) * Vec3f(q1.x, q1.y, q1.z);
1469 error = theta * v.x;
1478 if (constraints[tId].type == ConstraintType::CN_BAN_ROT_2)
1480 Quat q1 = rotation_q[idx1];
1481 q1 = q1.normalize();
1482 if (idx2 != INVALID)
1484 Quat q2 = rotation_q[idx2];
1485 q2 = q2.normalize();
1486 Quat q_error = q2 * q1.inverse();
1487 q_error = q_error.normalize();
1488 Real theta = 2.0 * acos(q_error.w);
1491 Vec3f v = (1 / sin(theta / 2.0)) * Vec3f(q_error.x, q_error.y, q_error.z);
1492 error = theta * v.y;
1501 Real theta = 2.0 * acos(q1.w);
1504 Vec3f v = (1 / sin(theta / 2.0)) * Vec3f(q1.x, q1.y, q1.z);
1505 error = theta * v.y;
1514 if (constraints[tId].type == ConstraintType::CN_BAN_ROT_3)
1516 Quat q1 = rotation_q[idx1];
1517 q1 = q1.normalize();
1518 if (idx2 != INVALID)
1520 Quat q2 = rotation_q[idx2];
1521 q2 = q2.normalize();
1522 Quat q_error = q2 * q1.inverse();
1523 q_error = q_error.normalize();
1524 Real theta = 2.0 * acos(q_error.w);
1527 Vec3f v = (1 / sin(theta / 2.0)) * Vec3f(q_error.x, q_error.y, q_error.z);
1528 error = theta * v.z;
1537 Real theta = 2.0 * acos(q1.w);
1540 Vec3f v = (1 / sin(theta / 2.0)) * Vec3f(q1.x, q1.y, q1.z);
1541 error = theta * v.z;
1550 if (constraints[tId].type == ConstraintType::CN_JOINT_HINGE_MIN || constraints[tId].type == ConstraintType::CN_JOINT_SLIDER_MIN)
1552 error = constraints[tId].d_min;
1555 if (constraints[tId].type == ConstraintType::CN_JOINT_HINGE_MAX || constraints[tId].type == ConstraintType::CN_JOINT_SLIDER_MAX)
1557 error = constraints[tId].d_max;
1560 if (constraints[tId].type == ConstraintType::CN_ALLOW_ROT1D_1)
1562 Coord a1 = constraints[tId].axis;
1563 Coord b2 = constraints[tId].pos1;
1567 if (constraints[tId].type == ConstraintType::CN_ALLOW_ROT1D_2)
1569 Coord a1 = constraints[tId].axis;
1570 Coord c2 = constraints[tId].pos2;
1574 if (constraints[tId].type == ConstraintType::CN_JOINT_NO_MOVE_1)
1576 Coord errorVec = constraints[tId].normal1;
1577 error = errorVec[0];
1580 if (constraints[tId].type == ConstraintType::CN_JOINT_NO_MOVE_2)
1582 Coord errorVec = constraints[tId].normal1;
1583 error = errorVec[1];
1586 if (constraints[tId].type == ConstraintType::CN_JOINT_NO_MOVE_3)
1588 Coord errorVec = constraints[tId].normal1;
1589 error = errorVec[2];
1592 eta[tId] -= ERP[tId] * invDt * error;
1595 void calculateEtaVectorForPJSBaumgarte(
1598 DArray<Vec3f> velocity,
1599 DArray<Vec3f> angular_velocity,
1601 DArray<Quat1f> rotation_q,
1602 DArray<TConstraintPair<float>> constraints,
1603 DArray<float> errors,
1610 cuExecute(constraints.size(),
1611 SF_calculateEtaVectorForPJSBaumgarte,
1626 void calculateEtaVectorWithERP(
1629 DArray<Vec3f> velocity,
1630 DArray<Vec3f> angular_velocity,
1632 DArray<Quat1f> rotation_q,
1633 DArray<TConstraintPair<float>> constraints,
1639 cuExecute(constraints.size(),
1640 SF_calculateEtaVectorWithERP,
1654 template<typename Coord, typename Constraint, typename Real>
1655 __global__ void SF_calculateEtaVectorForRelaxation(
1658 DArray<Coord> velocity,
1659 DArray<Coord> angular_velocity,
1660 DArray<Constraint> constraints
1663 int tId = threadIdx.x + blockIdx.x * blockDim.x;
1664 if (tId >= constraints.size())
1667 int idx1 = constraints[tId].bodyId1;
1668 int idx2 = constraints[tId].bodyId2;
1670 Real eta_i = Real(0);
1672 eta_i -= J[4 * tId].dot(velocity[idx1]);
1673 eta_i -= J[4 * tId + 1].dot(angular_velocity[idx1]);
1675 if (idx2 != INVALID)
1677 eta_i -= J[4 * tId + 2].dot(velocity[idx2]);
1678 eta_i -= J[4 * tId + 3].dot(angular_velocity[idx2]);
1685 void calculateEtaVectorForRelaxation(
1688 DArray<Vec3f> velocity,
1689 DArray<Vec3f> angular_velocity,
1690 DArray <TConstraintPair<float>> constraints
1693 cuExecute(constraints.size(),
1694 SF_calculateEtaVectorForRelaxation,
1702 template<typename Coord, typename Constraint, typename Real, typename Quat>
1703 __global__ void SF_calculateEtaVectorForPJSoft(
1706 DArray<Coord> velocity,
1707 DArray<Coord> angular_velocity,
1709 DArray<Quat> rotation_q,
1710 DArray<Constraint> constraints,
1718 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
1719 if (tId >= constraints.size())
1722 int idx1 = constraints[tId].bodyId1;
1723 int idx2 = constraints[tId].bodyId2;
1725 Real eta_i = Real(0);
1727 eta_i -= J[4 * tId].dot(velocity[idx1]);
1728 eta_i -= J[4 * tId + 1].dot(angular_velocity[idx1]);
1730 if (idx2 != INVALID)
1732 eta_i -= J[4 * tId + 2].dot(velocity[idx2]);
1733 eta_i -= J[4 * tId + 3].dot(angular_velocity[idx2]);
1738 Real invDt = Real(1) / dt;
1741 if (constraints[tId].type == ConstraintType::CN_JOINT_SLIDER_MOTER || constraints[tId].type == ConstraintType::CN_JOINT_HINGE_MOTER)
1743 Real v_moter = constraints[tId].interpenetration;
1744 eta[tId] -= v_moter;
1747 if (constraints[tId].type == ConstraintType::CN_NONPENETRATION)
1749 error = minimum(constraints[tId].interpenetration + slop, 0.0f) / substepping;
1752 if (constraints[tId].type == ConstraintType::CN_ANCHOR_EQUAL_1)
1754 Coord r1 = constraints[tId].normal1;
1755 Coord r2 = constraints[tId].normal2;
1756 Coord pos1 = constraints[tId].pos1;
1758 if (idx2 != INVALID)
1759 errorVec = pos[idx2] + r2 - pos[idx1] - r1;
1761 errorVec = pos1 - pos[idx1] - r1;
1762 error = errorVec[0];
1765 if (constraints[tId].type == ConstraintType::CN_ANCHOR_EQUAL_2)
1767 Coord r1 = constraints[tId].normal1;
1768 Coord r2 = constraints[tId].normal2;
1769 Coord pos1 = constraints[tId].pos1;
1771 if (idx2 != INVALID)
1772 errorVec = pos[idx2] + r2 - pos[idx1] - r1;
1774 errorVec = pos1 - pos[idx1] - r1;
1775 error = errorVec[1];
1778 if (constraints[tId].type == ConstraintType::CN_ANCHOR_EQUAL_3)
1780 Coord r1 = constraints[tId].normal1;
1781 Coord r2 = constraints[tId].normal2;
1782 Coord pos1 = constraints[tId].pos1;
1784 if (idx2 != INVALID)
1785 errorVec = pos[idx2] + r2 - pos[idx1] - r1;
1787 errorVec = pos1 - pos[idx1] - r1;
1788 error = errorVec[2];
1791 if (constraints[tId].type == ConstraintType::CN_ANCHOR_TRANS_1)
1793 Coord r1 = constraints[tId].pos1;
1794 Coord r2 = constraints[tId].pos2;
1795 Coord n1 = constraints[tId].normal1;
1797 error = (pos[idx2] + r2 - pos[idx1] - r1).dot(n1);
1800 if (constraints[tId].type == ConstraintType::CN_ANCHOR_TRANS_2)
1802 Coord r1 = constraints[tId].pos1;
1803 Coord r2 = constraints[tId].pos2;
1804 Coord n2 = constraints[tId].normal2;
1806 error = (pos[idx2] + r2 - pos[idx1] - r1).dot(n2);
1809 if (constraints[tId].type == ConstraintType::CN_BAN_ROT_1)
1811 Quat q1 = rotation_q[idx1];
1812 if (idx2 != INVALID)
1814 Quat q2 = rotation_q[idx2];
1815 Quat q_init = constraints[tId].rotQuat;
1816 Quat q_error = q2 * q_init * q1.inverse();
1818 error = q_error.x * 2;
1822 Quat diff = rotation_q[idx1] * constraints[tId].rotQuat.inverse();
1823 error = -diff.x * 2;
1827 if (constraints[tId].type == ConstraintType::CN_BAN_ROT_2)
1829 Quat q1 = rotation_q[idx1];
1830 if (idx2 != INVALID)
1832 Quat q2 = rotation_q[idx2];
1833 Quat q_init = constraints[tId].rotQuat;
1834 Quat q_error = q2 * q_init * q1.inverse();
1836 error = q_error.y * 2;
1840 Quat diff = rotation_q[idx1] * constraints[tId].rotQuat.inverse();
1841 error = -diff.y * 2;
1845 if (constraints[tId].type == ConstraintType::CN_BAN_ROT_3)
1847 Quat q1 = rotation_q[idx1];
1848 if (idx2 != INVALID)
1850 Quat q2 = rotation_q[idx2];
1851 Quat q_init = constraints[tId].rotQuat;
1852 Quat q_error = q2 * q_init * q1.inverse();
1854 error = q_error.z * 2;
1858 Quat diff = rotation_q[idx1] * constraints[tId].rotQuat.inverse();
1859 error = -diff.z * 2;
1863 if (constraints[tId].type == ConstraintType::CN_JOINT_HINGE_MIN || constraints[tId].type == ConstraintType::CN_JOINT_SLIDER_MIN)
1865 error = constraints[tId].d_min;
1868 if (constraints[tId].type == ConstraintType::CN_JOINT_HINGE_MAX || constraints[tId].type == ConstraintType::CN_JOINT_SLIDER_MAX)
1870 error = constraints[tId].d_max;
1873 if (constraints[tId].type == ConstraintType::CN_ALLOW_ROT1D_1)
1875 Coord a1 = constraints[tId].axis;
1876 Coord b2 = constraints[tId].pos1;
1880 if (constraints[tId].type == ConstraintType::CN_ALLOW_ROT1D_2)
1882 Coord a1 = constraints[tId].axis;
1883 Coord c2 = constraints[tId].pos2;
1887 if (constraints[tId].type == ConstraintType::CN_JOINT_NO_MOVE_1)
1889 Coord errorVec = constraints[tId].normal1;
1890 error = errorVec[0];
1893 if (constraints[tId].type == ConstraintType::CN_JOINT_NO_MOVE_2)
1895 Coord errorVec = constraints[tId].normal1;
1896 error = errorVec[1];
1899 if (constraints[tId].type == ConstraintType::CN_JOINT_NO_MOVE_3)
1901 Coord errorVec = constraints[tId].normal1;
1902 error = errorVec[2];
1905 Real omega = 2.0 * M_PI * hertz;
1906 Real a1 = 2.0 * zeta + omega * dt;
1907 Real biasRate = omega / a1;
1908 eta[tId] -= biasRate * error;
1911 void calculateEtaVectorForPJSoft(
1914 DArray<Vec3f> velocity,
1915 DArray<Vec3f> angular_velocity,
1917 DArray<Quat1f> rotation_q,
1918 DArray <TConstraintPair<float>> constraints,
1926 cuExecute(constraints.size(),
1927 SF_calculateEtaVectorForPJSoft,
1944 * calculate eta vector for NJS
1946 * @param eta eta vector
1947 * @param J Jacobian Matrix
1948 * @param pos position of rigids
1949 * @param rotation_q quaterion of rigids
1950 * @param constraints constraints data
1951 * @param linear slop linear slop
1952 * @param angular slop angular slop
1953 * @param beta bias ratio
1954 * This function calculate the diagonal Matrix of JB
1956 template<typename Coord, typename Constraint, typename Real, typename Quat>
1957 __global__ void SF_calculateEtaVectorForNJS(
1961 DArray<Quat> rotation_q,
1962 DArray<Constraint> constraints,
1967 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
1968 if (tId >= constraints.size())
1971 int idx1 = constraints[tId].bodyId1;
1972 int idx2 = constraints[tId].bodyId2;
1974 Real eta_i = Real(0);
1978 if (constraints[tId].type == ConstraintType::CN_NONPENETRATION)
1980 error = minimum(constraints[tId].interpenetration + slop, 0.0f);
1983 if (constraints[tId].type == ConstraintType::CN_ANCHOR_EQUAL_1)
1985 Coord r1 = constraints[tId].normal1;
1986 Coord r2 = constraints[tId].normal2;
1987 Coord pos1 = constraints[tId].pos1;
1989 if (idx2 != INVALID)
1990 errorVec = pos[idx2] + r2 - pos[idx1] - r1;
1992 errorVec = pos1 - pos[idx1] - r1;
1993 error = errorVec[0];
1996 if (constraints[tId].type == ConstraintType::CN_ANCHOR_EQUAL_2)
1998 Coord r1 = constraints[tId].normal1;
1999 Coord r2 = constraints[tId].normal2;
2000 Coord pos1 = constraints[tId].pos1;
2002 if (idx2 != INVALID)
2003 errorVec = pos[idx2] + r2 - pos[idx1] - r1;
2005 errorVec = pos1 - pos[idx1] - r1;
2006 error = errorVec[1];
2009 if (constraints[tId].type == ConstraintType::CN_ANCHOR_EQUAL_3)
2011 Coord r1 = constraints[tId].normal1;
2012 Coord r2 = constraints[tId].normal2;
2013 Coord pos1 = constraints[tId].pos1;
2015 if (idx2 != INVALID)
2016 errorVec = pos[idx2] + r2 - pos[idx1] - r1;
2018 errorVec = pos1 - pos[idx1] - r1;
2019 error = errorVec[2];
2022 if (constraints[tId].type == ConstraintType::CN_ANCHOR_TRANS_1)
2024 Coord r1 = constraints[tId].pos1;
2025 Coord r2 = constraints[tId].pos2;
2026 Coord n1 = constraints[tId].normal1;
2028 error = (pos[idx2] + r2 - pos[idx1] - r1).dot(n1);
2031 if (constraints[tId].type == ConstraintType::CN_ANCHOR_TRANS_2)
2033 Coord r1 = constraints[tId].pos1;
2034 Coord r2 = constraints[tId].pos2;
2035 Coord n2 = constraints[tId].normal2;
2037 error = (pos[idx2] + r2 - pos[idx1] - r1).dot(n2);
2040 if (constraints[tId].type == ConstraintType::CN_BAN_ROT_1)
2042 Quat q1 = rotation_q[idx1];
2043 q1 = q1.normalize();
2044 if (idx2 != INVALID)
2046 Quat q2 = rotation_q[idx2];
2047 q2 = q2.normalize();
2049 Quat q_error = q2 * q1.inverse();
2050 q_error = q_error.normalize();
2052 Real theta = 2.0 * acos(q_error.w);
2055 Vec3f v = (1 / sin(theta / 2.0)) * Vec3f(q_error.x, q_error.y, q_error.z);
2056 error = theta * v.x;
2065 Real theta = 2.0 * acos(q1.w);
2068 Vec3f v = (1 / sin(theta / 2.0)) * Vec3f(q1.x, q1.y, q1.z);
2069 error = theta * v.x;
2078 if (constraints[tId].type == ConstraintType::CN_BAN_ROT_2)
2080 Quat q1 = rotation_q[idx1];
2081 q1 = q1.normalize();
2082 if (idx2 != INVALID)
2084 Quat q2 = rotation_q[idx2];
2085 q2 = q2.normalize();
2086 Quat q_error = q2 * q1.inverse();
2087 q_error = q_error.normalize();
2088 Real theta = 2.0 * acos(q_error.w);
2091 Vec3f v = (1 / sin(theta / 2.0)) * Vec3f(q_error.x, q_error.y, q_error.z);
2092 error = theta * v.y;
2101 Real theta = 2.0 * acos(q1.w);
2104 Vec3f v = (1 / sin(theta / 2.0)) * Vec3f(q1.x, q1.y, q1.z);
2105 error = theta * v.y;
2114 if (constraints[tId].type == ConstraintType::CN_BAN_ROT_3)
2116 Quat q1 = rotation_q[idx1];
2117 q1 = q1.normalize();
2118 if (idx2 != INVALID)
2120 Quat q2 = rotation_q[idx2];
2121 q2 = q2.normalize();
2122 Quat q_error = q2 * q1.inverse();
2123 q_error = q_error.normalize();
2124 Real theta = 2.0 * acos(q_error.w);
2127 Vec3f v = (1 / sin(theta / 2.0)) * Vec3f(q_error.x, q_error.y, q_error.z);
2128 error = theta * v.z;
2137 Real theta = 2.0 * acos(q1.w);
2140 Vec3f v = (1 / sin(theta / 2.0)) * Vec3f(q1.x, q1.y, q1.z);
2141 error = theta * v.z;
2150 if (constraints[tId].type == ConstraintType::CN_JOINT_HINGE_MIN || constraints[tId].type == ConstraintType::CN_JOINT_SLIDER_MIN)
2152 error = constraints[tId].d_min;
2155 if (constraints[tId].type == ConstraintType::CN_JOINT_HINGE_MAX || constraints[tId].type == ConstraintType::CN_JOINT_SLIDER_MAX)
2157 error = constraints[tId].d_max;
2160 if (constraints[tId].type == ConstraintType::CN_ALLOW_ROT1D_1)
2162 Coord a1 = constraints[tId].axis;
2163 Coord b2 = constraints[tId].pos1;
2167 if (constraints[tId].type == ConstraintType::CN_ALLOW_ROT1D_2)
2169 Coord a1 = constraints[tId].axis;
2170 Coord c2 = constraints[tId].pos2;
2174 if (constraints[tId].type == ConstraintType::CN_JOINT_NO_MOVE_1)
2176 Coord errorVec = constraints[tId].normal1;
2177 error = errorVec[0];
2180 if (constraints[tId].type == ConstraintType::CN_JOINT_NO_MOVE_2)
2182 Coord errorVec = constraints[tId].normal1;
2183 error = errorVec[1];
2186 if (constraints[tId].type == ConstraintType::CN_JOINT_NO_MOVE_3)
2188 Coord errorVec = constraints[tId].normal1;
2189 error = errorVec[2];
2192 eta[tId] = eta_i - beta * error;
2195 void calculateEtaVectorForNJS(
2199 DArray<Quat1f> rotation_q,
2200 DArray <TConstraintPair<float>> constraints,
2205 cuExecute(constraints.size(),
2206 SF_calculateEtaVectorForNJS,
2217 * Store the contacts in local coordinates.
2219 * @param contactsInLocalFrame contacts in local coordinates
2220 * @param contactsInGlobalFrame contacts in global coordinates
2221 * @param pos position of rigids
2222 * @param rotMat rotation matrix of rigids
2223 * This function store the contacts in local coordinates.
2225 template<typename Contact, typename Coord, typename Matrix>
2226 __global__ void SF_setUpContactsInLocalFrame(
2227 DArray<Contact> contactsInLocalFrame,
2228 DArray<Contact> contactsInGlobalFrame,
2230 DArray<Matrix> rotMat
2233 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
2234 if (tId >= contactsInGlobalFrame.size())
2237 Contact globalC = contactsInGlobalFrame[tId];
2238 int idx1 = globalC.bodyId1;
2239 int idx2 = globalC.bodyId2;
2242 localC.bodyId1 = idx1;
2243 localC.bodyId2 = idx2;
2245 localC.interpenetration = -globalC.interpenetration;
2246 localC.contactType = globalC.contactType;
2248 Coord c1 = pos[idx1];
2249 Matrix rot1 = rotMat[idx1];
2251 if (idx2 != INVALID)
2253 Coord c2 = pos[idx2];
2254 Matrix rot2 = rotMat[idx2];
2255 localC.pos1 = rot1.transpose() * (globalC.pos1 - c1);
2256 localC.normal1 = -globalC.normal1;
2257 localC.pos2 = rot2.transpose() * (globalC.pos1 - c2);
2258 localC.normal2 = globalC.normal1;
2262 localC.pos1 = rot1.transpose() * (globalC.pos1 - c1);
2263 localC.normal1 = - globalC.normal1;
2264 localC.pos2 = globalC.pos1;
2265 localC.normal2 = globalC.normal1;
2267 contactsInLocalFrame[tId] = localC;
2270 void setUpContactsInLocalFrame(
2271 DArray<TContactPair<float>> contactsInLocalFrame,
2272 DArray<TContactPair<float>> contactsInGlobalFrame,
2274 DArray<Mat3f> rotMat
2277 cuExecute(contactsInGlobalFrame.size(),
2278 SF_setUpContactsInLocalFrame,
2279 contactsInLocalFrame,
2280 contactsInGlobalFrame,
2286 * Set up the contact and friction constraints
2288 * @param constraints constraints data
2289 * @param contactsInLocalFrame contacts in local coordinates
2290 * @param pos position of rigids
2291 * @param rotMat rotation matrix of rigids
2292 * @param hasFriction friction choice
2293 * This function set up the contact and friction constraints
2295 template<typename Coord, typename Matrix, typename Contact, typename Constraint>
2296 __global__ void SF_setUpContactAndFrictionConstraints(
2297 DArray<Constraint> constraints,
2298 DArray<Contact> contactsInLocalFrame,
2300 DArray<Matrix> rotMat,
2304 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
2305 if (tId >= contactsInLocalFrame.size())
2308 int contact_size = contactsInLocalFrame.size();
2310 int idx1 = contactsInLocalFrame[tId].bodyId1;
2311 int idx2 = contactsInLocalFrame[tId].bodyId2;
2313 Coord c1 = pos[idx1];
2314 Matrix rot1 = rotMat[idx1];
2316 constraints[tId].bodyId1 = idx1;
2317 constraints[tId].bodyId2 = idx2;
2318 constraints[tId].pos1 = rot1 * contactsInLocalFrame[tId].pos1 + c1;
2319 constraints[tId].normal1 = contactsInLocalFrame[tId].normal1;
2321 if (idx2 != INVALID)
2323 Coord c2 = pos[idx2];
2324 Matrix rot2 = rotMat[idx2];
2325 constraints[tId].pos2 = rot2 * contactsInLocalFrame[tId].pos2 + c2;
2326 constraints[tId].normal2 = contactsInLocalFrame[tId].normal2;
2330 constraints[tId].pos2 = contactsInLocalFrame[tId].pos2;
2331 constraints[tId].normal2 = contactsInLocalFrame[tId].normal2;
2334 constraints[tId].interpenetration = minimum(contactsInLocalFrame[tId].interpenetration + (constraints[tId].pos2 - constraints[tId].pos1).dot(contactsInLocalFrame[tId].normal1), 0.0f);
2335 constraints[tId].type = ConstraintType::CN_NONPENETRATION;
2336 constraints[tId].isValid = true;
2340 Coord n = constraints[tId].normal1;
2345 if (abs(n[1]) > EPSILON || abs(n[2]) > EPSILON)
2347 u1 = Vector<Real, 3>(0, n[2], -n[1]);
2348 u1 = u1.normalize();
2350 else if (abs(n[0]) > EPSILON)
2352 u1 = Vector<Real, 3>(n[2], 0, -n[0]);
2353 u1 = u1.normalize();
2357 u2 = u2.normalize();
2359 constraints[tId * 2 + contact_size].bodyId1 = idx1;
2360 constraints[tId * 2 + contact_size].bodyId2 = idx2;
2361 constraints[tId * 2 + contact_size].pos1 = constraints[tId].pos1;
2362 constraints[tId * 2 + contact_size].pos2 = constraints[tId].pos2;
2363 constraints[tId * 2 + contact_size].normal1 = u1;
2364 constraints[tId * 2 + contact_size].normal2 = -u1;
2365 constraints[tId * 2 + contact_size].type = ConstraintType::CN_FRICTION;
2366 constraints[tId * 2 + contact_size].isValid = true;
2368 constraints[tId * 2 + 1 + contact_size].bodyId1 = idx1;
2369 constraints[tId * 2 + 1 + contact_size].bodyId2 = idx2;
2370 constraints[tId * 2 + 1 + contact_size].pos1 = constraints[tId].pos1;
2371 constraints[tId * 2 + 1 + contact_size].pos2 = constraints[tId].pos2;
2372 constraints[tId * 2 + 1 + contact_size].normal1 = u2;
2373 constraints[tId * 2 + 1 + contact_size].normal2 = -u2;
2374 constraints[tId * 2 + 1 + contact_size].type = ConstraintType::CN_FRICTION;
2375 constraints[tId * 2 + 1 + contact_size].isValid = true;
2379 void setUpContactAndFrictionConstraints(
2380 DArray<TConstraintPair<float>> constraints,
2381 DArray<TContactPair<float>> contactsInLocalFrame,
2383 DArray<Mat3f> rotMat,
2387 cuExecute(constraints.size(),
2388 SF_setUpContactAndFrictionConstraints,
2390 contactsInLocalFrame,
2397 * Set up the contact constraints
2399 * @param constraints constraints data
2400 * @param contactsInLocalFrame contacts in local coordinates
2401 * @param pos position of rigids
2402 * @param rotMat rotation matrix of rigids
2403 * This function set up the contact constraints
2405 template<typename Coord, typename Matrix, typename Contact, typename Constraint>
2406 __global__ void SF_setUpContactConstraints(
2407 DArray<Constraint> constraints,
2408 DArray<Contact> contactsInLocalFrame,
2410 DArray<Matrix> rotMat
2413 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
2414 if (tId >= contactsInLocalFrame.size())
2417 int contact_size = contactsInLocalFrame.size();
2419 int idx1 = contactsInLocalFrame[tId].bodyId1;
2420 int idx2 = contactsInLocalFrame[tId].bodyId2;
2422 Coord c1 = pos[idx1];
2423 Matrix rot1 = rotMat[idx1];
2425 constraints[tId].bodyId1 = idx1;
2426 constraints[tId].bodyId2 = idx2;
2427 constraints[tId].pos1 = rot1 * contactsInLocalFrame[tId].pos1 + c1;
2428 constraints[tId].normal1 = contactsInLocalFrame[tId].normal1;
2430 if (idx2 != INVALID)
2432 Coord c2 = pos[idx2];
2433 Matrix rot2 = rotMat[idx2];
2435 constraints[tId].pos2 = rot2 * contactsInLocalFrame[tId].pos2 + c2;
2436 constraints[tId].normal2 = contactsInLocalFrame[tId].normal2;
2437 constraints[tId].interpenetration = (constraints[tId].pos2 - constraints[tId].pos1).dot(constraints[tId].normal1) + contactsInLocalFrame[tId].interpenetration;
2441 Real dist = (contactsInLocalFrame[tId].pos2 - constraints[tId].pos1).dot(constraints[tId].normal1) + contactsInLocalFrame[tId].interpenetration;
2442 constraints[tId].interpenetration = dist;
2445 constraints[tId].type = ConstraintType::CN_NONPENETRATION;
2448 void setUpContactConstraints(
2449 DArray<TConstraintPair<float>> constraints,
2450 DArray<TContactPair<float>> contactsInLocalFrame,
2452 DArray<Mat3f> rotMat
2455 cuExecute(constraints.size(),
2456 SF_setUpContactConstraints,
2458 contactsInLocalFrame,
2464 * Set up the ball and socket constraints
2466 * @param constraints constraints data
2467 * @param joints joints data
2468 * @param pos position of rigids
2469 * @param rotMat rotation matrix of rigids
2470 * @param begin_index begin index of ball and socket joints constraints in array
2471 * This function set up the ball and socket joint constraints
2473 template<typename Joint, typename Constraint, typename Coord, typename Matrix>
2474 __global__ void SF_setUpBallAndSocketJointConstraints(
2475 DArray<Constraint> constraints,
2476 DArray<Joint> joints,
2478 DArray<Matrix> rotMat,
2482 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
2484 if (tId >= joints.size())
2487 int idx1 = joints[tId].bodyId1;
2488 int idx2 = joints[tId].bodyId2;
2490 Coord r1 = rotMat[idx1] * joints[tId].r1;
2491 Coord r2 = rotMat[idx2] * joints[tId].r2;
2493 int baseIndex = 3 * tId + begin_index;
2495 constraints[baseIndex].bodyId1 = idx1;
2496 constraints[baseIndex].bodyId2 = idx2;
2497 constraints[baseIndex].normal1 = r1;
2498 constraints[baseIndex].normal2 = r2;
2499 constraints[baseIndex].type = ConstraintType::CN_ANCHOR_EQUAL_1;
2500 constraints[baseIndex].isValid = true;
2502 constraints[baseIndex + 1].bodyId1 = idx1;
2503 constraints[baseIndex + 1].bodyId2 = idx2;
2504 constraints[baseIndex + 1].normal1 = r1;
2505 constraints[baseIndex + 1].normal2 = r2;
2506 constraints[baseIndex + 1].type = ConstraintType::CN_ANCHOR_EQUAL_2;
2507 constraints[baseIndex + 1].isValid = true;
2509 constraints[baseIndex + 2].bodyId1 = idx1;
2510 constraints[baseIndex + 2].bodyId2 = idx2;
2511 constraints[baseIndex + 2].normal1 = r1;
2512 constraints[baseIndex + 2].normal2 = r2;
2513 constraints[baseIndex + 2].type = ConstraintType::CN_ANCHOR_EQUAL_3;
2514 constraints[baseIndex + 2].isValid = true;
2517 void setUpBallAndSocketJointConstraints(
2518 DArray<TConstraintPair<float>> constraints,
2519 DArray<BallAndSocketJoint<float>> joints,
2521 DArray<Mat3f> rotMat,
2525 cuExecute(constraints.size(),
2526 SF_setUpBallAndSocketJointConstraints,
2535 * Set up the slider constraints
2537 * @param constraints constraints data
2538 * @param joints joints data
2539 * @param pos position of rigids
2540 * @param rotMat rotation matrix of rigids
2541 * @param begin_index begin index of slider constraints in array
2542 * This function set up the slider joint constraints
2544 template<typename Joint, typename Constraint, typename Coord, typename Matrix, typename Quat>
2545 __global__ void SF_setUpSliderJointConstraints(
2546 DArray<Constraint> constraints,
2547 DArray<Joint> joints,
2549 DArray<Matrix> rotMat,
2550 DArray<Quat> rotQuat,
2554 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
2556 if (tId >= joints.size())
2559 int constraint_size = 8;
2561 int idx1 = joints[tId].bodyId1;
2562 int idx2 = joints[tId].bodyId2;
2564 Coord r1 = rotMat[idx1] * joints[tId].r1;
2565 Coord r2 = rotMat[idx2] * joints[tId].r2;
2567 Coord n = rotMat[idx1] * joints[tId].sliderAxis;
2570 if (abs(n[1]) > EPSILON || abs(n[2]) > EPSILON)
2572 n1 = Coord(0, n[2], -n[1]);
2573 n1 = n1.normalize();
2575 else if (abs(n[0]) > EPSILON)
2577 n1 = Coord(n[2], 0, -n[0]);
2578 n1 = n1.normalize();
2581 n2 = n2.normalize();
2583 int baseIndex = constraint_size * tId + begin_index;
2585 for (int i = 0; i < 5; i++)
2587 constraints[baseIndex + i].isValid = true;
2591 bool useRange = joints[tId].useRange;
2594 if (joints[tId].useRange)
2596 Coord u = pos[idx2] + r2 - pos[idx1] - r1;
2597 C_min = u.dot(n) - joints[tId].d_min;
2598 C_max = joints[tId].d_max - u.dot(n);
2600 constraints[baseIndex + 5].isValid = true;
2602 constraints[baseIndex + 5].isValid = false;
2604 constraints[baseIndex + 6].isValid = true;
2606 constraints[baseIndex + 6].isValid = false;
2610 constraints[baseIndex + 5].isValid = false;
2611 constraints[baseIndex + 6].isValid = false;
2615 bool useMoter = joints[tId].useMoter;
2618 v_moter = joints[tId].v_moter;
2619 constraints[baseIndex + 7].isValid = true;
2623 constraints[baseIndex + 7].isValid = false;
2626 for (int i = 0; i < constraint_size; i++)
2628 auto& constraint = constraints[baseIndex + i];
2629 constraint.bodyId1 = idx1;
2630 constraint.bodyId2 = idx2;
2631 constraint.pos1 = r1;
2632 constraint.pos2 = r2;
2633 constraint.normal1 = n1;
2634 constraint.normal2 = n2;
2635 constraint.axis = n;
2636 constraint.interpenetration = v_moter;
2637 constraint.d_min = C_min;
2638 constraint.d_max = C_max;
2639 constraint.rotQuat = joints[tId].q_init;
2642 constraints[baseIndex].type = ConstraintType::CN_ANCHOR_TRANS_1;
2643 constraints[baseIndex + 1].type = ConstraintType::CN_ANCHOR_TRANS_2;
2644 constraints[baseIndex + 2].type = ConstraintType::CN_BAN_ROT_1;
2645 constraints[baseIndex + 3].type = ConstraintType::CN_BAN_ROT_2;
2646 constraints[baseIndex + 4].type = ConstraintType::CN_BAN_ROT_3;
2647 constraints[baseIndex + 5].type = ConstraintType::CN_JOINT_SLIDER_MIN;
2648 constraints[baseIndex + 6].type = ConstraintType::CN_JOINT_SLIDER_MAX;
2649 constraints[baseIndex + 7].type = ConstraintType::CN_JOINT_SLIDER_MOTER;
2652 void setUpSliderJointConstraints(
2653 DArray<TConstraintPair<float>> constraints,
2654 DArray<SliderJoint<float>> joints,
2656 DArray<Mat3f> rotMat,
2657 DArray<Quat1f> rotQuat,
2661 cuExecute(constraints.size(),
2662 SF_setUpSliderJointConstraints,
2672 * Set up the hinge constraints
2674 * @param constraints constraints data
2675 * @param joints joints data
2676 * @param pos position of rigids
2677 * @param rotMat rotation matrix of rigids
2678 * @oaran rotation_q quaterion of rigids
2679 * @param begin_index begin index of hinge constraints in array
2680 * This function set up the hinge joint constraints
2682 template<typename Joint, typename Constraint, typename Coord, typename Matrix, typename Quat>
2683 __global__ void SF_setUpHingeJointConstraints(
2684 DArray<Constraint> constraints,
2685 DArray<Joint> joints,
2687 DArray<Matrix> rotMat,
2688 DArray<Quat> rotation_q,
2692 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
2693 if (tId >= joints.size())
2696 int constraint_size = 8;
2698 int idx1 = joints[tId].bodyId1;
2699 int idx2 = joints[tId].bodyId2;
2701 Matrix rotMat1 = rotMat[idx1];
2702 Matrix rotMat2 = rotMat[idx2];
2705 Coord r1 = rotMat1 * joints[tId].r1;
2706 Coord r2 = rotMat2 * joints[tId].r2;
2708 Coord a1 = rotMat1 * joints[tId].hingeAxisBody1;
2709 Coord a2 = rotMat2 * joints[tId].hingeAxisBody2;
2714 // two vector orthogonal to the a2
2716 if (abs(a2[1]) > EPSILON || abs(a2[2]) > EPSILON)
2718 b2 = Coord(0, a2[2], -a2[1]);
2719 b2 = b2.normalize();
2721 else if (abs(a2[0]) > EPSILON)
2723 b2 = Coord(a2[2], 0, -a2[0]);
2724 b2 = b2.normalize();
2727 c2 = c2.normalize();
2731 int baseIndex = tId * constraint_size + begin_index;
2733 if (joints[tId].useRange)
2735 Real theta = rotation_q[idx2].angle(rotation_q[idx1]);
2737 Quat q_rot = rotation_q[idx2] * rotation_q[idx1].inverse();
2739 if (a1.dot(Coord(q_rot.x, q_rot.y, q_rot.z)) < 0)
2745 C_min = theta - joints[tId].d_min;
2746 C_max = joints[tId].d_max - theta;
2750 constraints[baseIndex + 5].isValid = true;
2753 constraints[baseIndex + 5].isValid = false;
2757 constraints[baseIndex + 6].isValid = true;
2760 constraints[baseIndex + 6].isValid = false;
2765 constraints[baseIndex + 5].isValid = false;
2766 constraints[baseIndex + 6].isValid = false;
2770 if (joints[tId].useMoter)
2772 v_moter = joints[tId].v_moter;
2773 constraints[baseIndex + 7].isValid = true;
2776 constraints[baseIndex + 7].isValid = false;
2778 for (int i = 0; i < constraint_size; i++)
2780 constraints[baseIndex + i].bodyId1 = idx1;
2781 constraints[baseIndex + i].bodyId2 = idx2;
2782 constraints[baseIndex + i].axis = a1;
2783 constraints[baseIndex + i].normal1 = r1;
2784 constraints[baseIndex + i].normal2 = r2;
2785 constraints[baseIndex + i].pos1 = b2;
2786 constraints[baseIndex + i].pos2 = c2;
2787 constraints[baseIndex + i].d_min = C_min > 0 ? 0 : C_min;
2788 constraints[baseIndex + i].d_max = C_max > 0 ? 0 : C_max;
2789 constraints[baseIndex + i].interpenetration = v_moter;
2792 for (int i = 0; i < 5; i++)
2794 constraints[baseIndex + i].isValid = true;
2797 constraints[baseIndex].type = ConstraintType::CN_ANCHOR_EQUAL_1;
2798 constraints[baseIndex + 1].type = ConstraintType::CN_ANCHOR_EQUAL_2;
2799 constraints[baseIndex + 2].type = ConstraintType::CN_ANCHOR_EQUAL_3;
2800 constraints[baseIndex + 3].type = ConstraintType::CN_ALLOW_ROT1D_1;
2801 constraints[baseIndex + 4].type = ConstraintType::CN_ALLOW_ROT1D_2;
2802 constraints[baseIndex + 5].type = ConstraintType::CN_JOINT_HINGE_MIN;
2803 constraints[baseIndex + 6].type = ConstraintType::CN_JOINT_HINGE_MAX;
2804 constraints[baseIndex + 7].type = ConstraintType::CN_JOINT_HINGE_MOTER;
2807 void setUpHingeJointConstraints(
2808 DArray<TConstraintPair<float>> constraints,
2809 DArray<HingeJoint<float>> joints,
2811 DArray<Mat3f> rotMat,
2812 DArray<Quat1f> rotation_q,
2816 cuExecute(constraints.size(),
2817 SF_setUpHingeJointConstraints,
2827 * Set up the fixed joint constraints
2829 * @param constraints constraints data
2830 * @param joints joints data
2831 * @param rotMat rotation matrix of rigids
2832 * @param begin_index begin index of fixed constraints in array
2833 * This function set up the fixed joint constraints
2835 template<typename Joint, typename Constraint, typename Matrix, typename Quat>
2836 __global__ void SF_setUpFixedJointConstraints(
2837 DArray<Constraint> constraints,
2838 DArray<Joint> joints,
2839 DArray<Matrix> rotMat,
2840 DArray<Quat> rotQuat,
2844 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
2846 if (tId >= joints.size())
2849 int idx1 = joints[tId].bodyId1;
2850 int idx2 = joints[tId].bodyId2;
2851 Vector<Real, 3> r1 = rotMat[idx1] * joints[tId].r1;
2853 if (idx2 != INVALID)
2855 r2 = rotMat[idx2] * joints[tId].r2;
2858 int baseIndex = 6 * tId + begin_index;
2859 for (int i = 0; i < 6; i++)
2861 constraints[baseIndex + i].bodyId1 = idx1;
2862 constraints[baseIndex + i].bodyId2 = idx2;
2863 constraints[baseIndex + i].normal1 = r1;
2864 constraints[baseIndex + i].normal2 = r2;
2865 constraints[baseIndex + i].pos1 = joints[tId].w;
2866 constraints[baseIndex + i].rotQuat = joints[tId].q_init;
2867 constraints[baseIndex + i].isValid = true;
2870 constraints[baseIndex].type = ConstraintType::CN_ANCHOR_EQUAL_1;
2871 constraints[baseIndex + 1].type = ConstraintType::CN_ANCHOR_EQUAL_2;
2872 constraints[baseIndex + 2].type = ConstraintType::CN_ANCHOR_EQUAL_3;
2873 constraints[baseIndex + 3].type = ConstraintType::CN_BAN_ROT_1;
2874 constraints[baseIndex + 4].type = ConstraintType::CN_BAN_ROT_2;
2875 constraints[baseIndex + 5].type = ConstraintType::CN_BAN_ROT_3;
2878 void setUpFixedJointConstraints(
2879 DArray<TConstraintPair<float>> &constraints,
2880 DArray<FixedJoint<float>> &joints,
2881 DArray<Mat3f> &rotMat,
2882 DArray<Quat1f> &rotQuat,
2886 cuExecute(constraints.size(),
2887 SF_setUpFixedJointConstraints,
2896 * Set up the point joint constraints
2898 * @param constraints constraints data
2899 * @param joints joints data
2900 * @param begin_index begin index of fixed constraints in array
2901 * This function set up the point joint constraints
2903 template<typename Joint, typename Constraint, typename Coord>
2904 __global__ void SF_setUpPointJointConstraints(
2905 DArray<Constraint> constraints,
2906 DArray<Joint> joints,
2911 int tId = threadIdx.x + blockDim.x * blockIdx.x;
2912 if (tId >= joints.size())
2915 int idx1 = joints[tId].bodyId1;
2916 int idx2 = joints[tId].bodyId2;
2918 int baseIndex = 3 * tId + begin_index;
2920 for (int i = 0; i < 3; i++)
2922 constraints[baseIndex + i].bodyId1 = idx1;
2923 constraints[baseIndex + i].bodyId2 = idx2;
2924 constraints[baseIndex + i].normal1 = pos[idx1] - joints[tId].anchorPoint;
2925 constraints[baseIndex + i].isValid = true;
2928 constraints[baseIndex].type = ConstraintType::CN_JOINT_NO_MOVE_1;
2929 constraints[baseIndex + 1].type = ConstraintType::CN_JOINT_NO_MOVE_2;
2930 constraints[baseIndex + 2].type = ConstraintType::CN_JOINT_NO_MOVE_3;
2933 void setUpPointJointConstraints(
2934 DArray<TConstraintPair<float>> constraints,
2935 DArray<PointJoint<float>> joints,
2940 cuExecute(constraints.size(),
2941 SF_setUpPointJointConstraints,
2949 template<typename Coord, typename Constraint, typename Matrix>
2950 __global__ void SF_calculateK(
2951 DArray<Constraint> constraints,
2955 DArray<Matrix> inertia,
2962 int tId = threadIdx.x + blockIdx.x * blockDim.x;
2963 if (tId >= constraints.size())
2966 int idx1 = constraints[tId].bodyId1;
2967 int idx2 = constraints[tId].bodyId2;
2969 if (constraints[tId].type == ConstraintType::CN_ANCHOR_EQUAL_1)
2971 Matrix E(1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f);
2972 Coord r1 = constraints[tId].normal1;
2973 Matrix r1x(0.0f, -r1[2], r1[1], r1[2], 0, -r1[0], -r1[1], r1[0], 0);
2974 if (idx2 != INVALID)
2976 Coord r2 = constraints[tId].normal2;
2977 Matrix r2x(0.0f, -r2[2], r2[1], r2[2], 0, -r2[0], -r2[1], r2[0], 0);
2978 Matrix K = (1 / mass[idx1]) * E + (r1x * inertia[idx1].inverse()) * r1x.transpose() + (1 / mass[idx2]) * E + (r2x * inertia[idx2].inverse()) * r2x.transpose();
2979 K_3[tId] = K.inverse();
2983 Matrix K = (1 / mass[idx1]) * E + (r1x * inertia[idx1].inverse()) * r1x.transpose();
2984 K_3[tId] = K.inverse();
2989 else if (constraints[tId].type == ConstraintType::CN_ALLOW_ROT1D_1)
2991 Coord a1 = constraints[tId].axis;
2992 Coord b2 = constraints[tId].pos1;
2993 Coord c2 = constraints[tId].pos2;
2994 Coord b2_c_a1 = b2.cross(a1);
2995 Coord c2_c_a1 = c2.cross(a1);
2996 Real a = b2_c_a1.dot(inertia[idx1].inverse() * b2_c_a1) + b2_c_a1.dot(inertia[idx2].inverse() * b2_c_a1);
2997 Real b = b2_c_a1.dot(inertia[idx1].inverse() * c2_c_a1) + b2_c_a1.dot(inertia[idx2].inverse() * c2_c_a1);
2998 Real c = c2_c_a1.dot(inertia[idx1].inverse() * b2_c_a1) + c2_c_a1.dot(inertia[idx2].inverse() * b2_c_a1);
2999 Real d = c2_c_a1.dot(inertia[idx1].inverse() * c2_c_a1) + c2_c_a1.dot(inertia[idx2].inverse() * c2_c_a1);
3000 Mat2f K(a, b, c, d);
3001 K_2[tId] = K.inverse();
3004 else if (constraints[tId].type == ConstraintType::CN_JOINT_NO_MOVE_1)
3006 Matrix K = (1 / mass[idx1]) * Matrix(1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f);
3007 K_3[tId] = K.inverse();
3010 else if (constraints[tId].type == ConstraintType::CN_ANCHOR_TRANS_1)
3012 Coord r1 = constraints[tId].pos1;
3013 Coord r2 = constraints[tId].pos2;
3014 Coord n1 = constraints[tId].normal1;
3015 Coord n2 = constraints[tId].normal2;
3016 Coord u = pos[idx2] + r2 - pos[idx1] - r1;
3017 Coord r1u_c_n1 = (r1 + u).cross(n1);
3018 Coord r1u_c_n2 = (r1 + u).cross(n2);
3019 Coord r2_c_n1 = r2.cross(n1);
3020 Coord r2_c_n2 = r2.cross(n2);
3021 Real a = 1 / mass[idx1] + 1 / mass[idx2] + r1u_c_n1.dot(inertia[idx1].inverse() * r1u_c_n1) + r2_c_n1.dot(inertia[idx2].inverse() * r2_c_n1);
3022 Real b = r1u_c_n1.dot(inertia[idx1].inverse() * r1u_c_n2) + r2_c_n1.dot(inertia[idx2].inverse() * r2_c_n2);
3023 Real c = r1u_c_n2.dot(inertia[idx1].inverse() * r1u_c_n1) + r2_c_n2.dot(inertia[idx2].inverse() * r2_c_n1);
3024 Real d = 1 / mass[idx1] + 1 / mass[idx2] + r1u_c_n2.dot(inertia[idx1].inverse() * r1u_c_n2) + r2_c_n2.dot(inertia[idx2].inverse() * r2_c_n2);
3025 Mat2f K(a, b, c, d);
3026 K_2[tId] = K.inverse();
3030 else if (constraints[tId].type == ConstraintType::CN_BAN_ROT_1)
3032 if (idx2 != INVALID)
3034 Matrix K = inertia[idx1].inverse() + inertia[idx2].inverse();
3035 K_3[tId] = K.inverse();
3039 Matrix K = inertia[idx1].inverse();
3040 K_3[tId] = K.inverse();
3046 if (constraints[tId].isValid)
3048 Real K = J[4 * tId].dot(B[4 * tId]) + J[4 * tId + 1].dot(B[4 * tId + 1]) + J[4 * tId + 2].dot(B[4 * tId + 2]) + J[4 * tId + 3].dot(B[4 * tId + 3]);
3054 template<typename Coord, typename Constraint, typename Matrix>
3055 __global__ void SF_calculateKWithCFM(
3056 DArray<Constraint> constraints,
3060 DArray<Matrix> inertia,
3068 int tId = threadIdx.x + blockIdx.x * blockDim.x;
3069 if (tId >= constraints.size())
3072 int idx1 = constraints[tId].bodyId1;
3073 int idx2 = constraints[tId].bodyId2;
3075 if (constraints[tId].type == ConstraintType::CN_ANCHOR_EQUAL_1)
3077 Matrix E(1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f);
3078 Coord r1 = constraints[tId].normal1;
3079 Matrix r1x(0.0f, -r1[2], r1[1], r1[2], 0, -r1[0], -r1[1], r1[0], 0);
3080 Matrix CFM_3(CFM[tId], 0, 0, 0, CFM[tId], 0, 0, 0, CFM[tId]);
3082 if (idx2 != INVALID)
3084 Coord r2 = constraints[tId].normal2;
3085 Matrix r2x(0.0f, -r2[2], r2[1], r2[2], 0, -r2[0], -r2[1], r2[0], 0);
3086 Matrix K = (1 / mass[idx1]) * E + (r1x * inertia[idx1].inverse()) * r1x.transpose() + (1 / mass[idx2]) * E + (r2x * inertia[idx2].inverse()) * r2x.transpose();
3087 K_3[tId] = (K + CFM_3).inverse();
3091 Matrix K = (1 / mass[idx1]) * E + (r1x * inertia[idx1].inverse()) * r1x.transpose();
3092 K_3[tId] = (K + CFM_3).inverse();
3097 else if (constraints[tId].type == ConstraintType::CN_ALLOW_ROT1D_1)
3099 Coord a1 = constraints[tId].axis;
3100 Coord b2 = constraints[tId].pos1;
3101 Coord c2 = constraints[tId].pos2;
3102 Coord b2_c_a1 = b2.cross(a1);
3103 Coord c2_c_a1 = c2.cross(a1);
3104 Real a = b2_c_a1.dot(inertia[idx1].inverse() * b2_c_a1) + b2_c_a1.dot(inertia[idx2].inverse() * b2_c_a1);
3105 Real b = b2_c_a1.dot(inertia[idx1].inverse() * c2_c_a1) + b2_c_a1.dot(inertia[idx2].inverse() * c2_c_a1);
3106 Real c = c2_c_a1.dot(inertia[idx1].inverse() * b2_c_a1) + c2_c_a1.dot(inertia[idx2].inverse() * b2_c_a1);
3107 Real d = c2_c_a1.dot(inertia[idx1].inverse() * c2_c_a1) + c2_c_a1.dot(inertia[idx2].inverse() * c2_c_a1);
3108 Mat2f K(a, b, c, d);
3109 Mat2f CFM_2(CFM[tId], 0, 0, CFM[tId]);
3110 K_2[tId] = (K + CFM_2).inverse();
3113 else if (constraints[tId].type == ConstraintType::CN_JOINT_NO_MOVE_1)
3115 Matrix K = (1 / mass[idx1]) * Matrix(1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f);
3116 Matrix CFM_3(CFM[tId], 0, 0, 0, CFM[tId], 0, 0, 0, CFM[tId]);
3117 K_3[tId] = (K + CFM_3).inverse();
3120 else if (constraints[tId].type == ConstraintType::CN_ANCHOR_TRANS_1)
3122 Coord r1 = constraints[tId].pos1;
3123 Coord r2 = constraints[tId].pos2;
3124 Coord n1 = constraints[tId].normal1;
3125 Coord n2 = constraints[tId].normal2;
3126 Coord u = pos[idx2] + r2 - pos[idx1] - r1;
3127 Coord r1u_c_n1 = (r1 + u).cross(n1);
3128 Coord r1u_c_n2 = (r1 + u).cross(n2);
3129 Coord r2_c_n1 = r2.cross(n1);
3130 Coord r2_c_n2 = r2.cross(n2);
3131 Real a = 1 / mass[idx1] + 1 / mass[idx2] + r1u_c_n1.dot(inertia[idx1].inverse() * r1u_c_n1) + r2_c_n1.dot(inertia[idx2].inverse() * r2_c_n1);
3132 Real b = r1u_c_n1.dot(inertia[idx1].inverse() * r1u_c_n2) + r2_c_n1.dot(inertia[idx2].inverse() * r2_c_n2);
3133 Real c = r1u_c_n2.dot(inertia[idx1].inverse() * r1u_c_n1) + r2_c_n2.dot(inertia[idx2].inverse() * r2_c_n1);
3134 Real d = 1 / mass[idx1] + 1 / mass[idx2] + r1u_c_n2.dot(inertia[idx1].inverse() * r1u_c_n2) + r2_c_n2.dot(inertia[idx2].inverse() * r2_c_n2);
3135 Mat2f K(a, b, c, d);
3136 Mat2f CFM_2(CFM[tId], 0, 0, CFM[tId]);
3137 K_2[tId] = (K + CFM_2).inverse();
3140 else if (constraints[tId].type == ConstraintType::CN_BAN_ROT_1)
3142 Matrix CFM_3(CFM[tId], 0, 0, 0, CFM[tId], 0, 0, 0, CFM[tId]);
3143 if (idx2 != INVALID)
3145 Matrix K = inertia[idx1].inverse() + inertia[idx2].inverse();
3146 K_3[tId] = (K + CFM_3).inverse();
3150 Matrix K = inertia[idx1].inverse();
3151 K_3[tId] = (K + CFM_3).inverse();
3157 if (constraints[tId].isValid)
3159 Real K = J[4 * tId].dot(B[4 * tId]) + J[4 * tId + 1].dot(B[4 * tId + 1]) + J[4 * tId + 2].dot(B[4 * tId + 2]) + J[4 * tId + 3].dot(B[4 * tId + 3]);
3160 K_1[tId] = 1 / (K + CFM[tId]);
3167 DArray<TConstraintPair<float>> constraints,
3171 DArray<Mat3f> inertia,
3178 cuExecute(constraints.size(),
3191 void calculateKWithCFM(
3192 DArray<TConstraintPair<float>> constraints,
3196 DArray<Mat3f> inertia,
3204 cuExecute(constraints.size(),
3205 SF_calculateKWithCFM,
3219 * take one Jacobi Iteration
3225 * @param constraints
3234 * This function take one Jacobi Iteration to calculate constrain impulse
3236 template<typename Real, typename Coord, typename Constraint, typename Matrix3, typename Matrix2>
3237 __global__ void SF_JacobiIteration(
3238 DArray<Real> lambda,
3239 DArray<Coord> impulse,
3243 DArray<Constraint> constraints,
3246 DArray<Matrix2> K_2,
3247 DArray<Matrix3> K_3,
3249 DArray<Real> fricCoeffs,
3255 int tId = threadIdx.x + blockIdx.x * blockDim.x;
3256 if (tId >= constraints.size())
3260 int idx1 = constraints[tId].bodyId1;
3261 int idx2 = constraints[tId].bodyId2;
3263 int stepInverse = 0;
3264 if (constraints[tId].type == ConstraintType::CN_FRICTION || constraints[tId].type == ConstraintType::CN_NONPENETRATION)
3266 if (idx2 != INVALID)
3268 stepInverse = nbq[idx1] + nbq[idx2];
3272 stepInverse = nbq[idx1];
3280 Real omega = Real(1) / stepInverse;
3282 if (constraints[tId].type == ConstraintType::CN_FRICTION || constraints[tId].type == ConstraintType::CN_NONPENETRATION)
3284 Real tmp = eta[tId];
3285 tmp -= J[4 * tId].dot(impulse[idx1 * 2]);
3286 tmp -= J[4 * tId + 1].dot(impulse[idx1 * 2 + 1]);
3287 if (idx2 != INVALID)
3289 tmp -= J[4 * tId + 2].dot(impulse[idx2 * 2]);
3290 tmp -= J[4 * tId + 3].dot(impulse[idx2 * 2 + 1]);
3292 Real delta_lambda = 0;
3293 if (constraints[tId].type == ConstraintType::CN_NONPENETRATION)
3295 Real lambda_new = maximum(0.0f, lambda[tId] + (tmp * K_1[tId] * omega));
3296 delta_lambda = lambda_new - lambda[tId];
3298 if (constraints[tId].type == ConstraintType::CN_FRICTION)
3300 Real mass_avl = mass[idx1];
3301 Real mu_i = fricCoeffs[idx1];
3302 if (idx2 != INVALID)
3304 mass_avl = (mass_avl + mass[idx2]) / 2;
3305 mu_i = (mu_i + fricCoeffs[idx2]) / 2;
3307 Real lambda_new = minimum(maximum(lambda[tId] + (tmp * K_1[tId] * omega), -mu_i * mass_avl * g * dt), mu_i * mass_avl * g * dt);
3308 delta_lambda = lambda_new - lambda[tId];
3311 lambda[tId] += delta_lambda;
3313 atomicAdd(&impulse[idx1 * 2][0], B[4 * tId][0] * delta_lambda);
3314 atomicAdd(&impulse[idx1 * 2][1], B[4 * tId][1] * delta_lambda);
3315 atomicAdd(&impulse[idx1 * 2][2], B[4 * tId][2] * delta_lambda);
3317 atomicAdd(&impulse[idx1 * 2 + 1][0], B[4 * tId + 1][0] * delta_lambda);
3318 atomicAdd(&impulse[idx1 * 2 + 1][1], B[4 * tId + 1][1] * delta_lambda);
3319 atomicAdd(&impulse[idx1 * 2 + 1][2], B[4 * tId + 1][2] * delta_lambda);
3321 if (idx2 != INVALID)
3323 atomicAdd(&impulse[idx2 * 2][0], B[4 * tId + 2][0] * delta_lambda);
3324 atomicAdd(&impulse[idx2 * 2][1], B[4 * tId + 2][1] * delta_lambda);
3325 atomicAdd(&impulse[idx2 * 2][2], B[4 * tId + 2][2] * delta_lambda);
3327 atomicAdd(&impulse[idx2 * 2 + 1][0], B[4 * tId + 3][0] * delta_lambda);
3328 atomicAdd(&impulse[idx2 * 2 + 1][1], B[4 * tId + 3][1] * delta_lambda);
3329 atomicAdd(&impulse[idx2 * 2 + 1][2], B[4 * tId + 3][2] * delta_lambda);
3333 if (constraints[tId].type == ConstraintType::CN_ANCHOR_EQUAL_1 || constraints[tId].type == ConstraintType::CN_BAN_ROT_1)
3335 Coord tmp(eta[tId], eta[tId + 1], eta[tId + 2]);
3336 if (idx2 != INVALID)
3338 for (int i = 0; i < 3; i++)
3340 tmp[i] -= J[4 * (tId + i)].dot(impulse[idx1 * 2]) + J[4 * (tId + i) + 2].dot(impulse[idx2 * 2]);
3341 tmp[i] -= J[4 * (tId + i) + 1].dot(impulse[idx1 * 2 + 1]) + J[4 * (tId + i) + 3].dot(impulse[idx2 * 2 + 1]);
3346 for (int i = 0; i < 3; i++)
3348 tmp[i] -= J[4 * (tId + i)].dot(impulse[idx1 * 2]);
3349 tmp[i] -= J[4 * (tId + i) + 1].dot(impulse[idx1 * 2 + 1]);
3353 Coord delta_lambda = omega * (K_3[tId] * tmp);
3355 for (int i = 0; i < 3; i++)
3357 atomicAdd(&impulse[idx1 * 2][0], B[4 * (tId + i)][0] * delta_lambda[i]);
3358 atomicAdd(&impulse[idx1 * 2][1], B[4 * (tId + i)][1] * delta_lambda[i]);
3359 atomicAdd(&impulse[idx1 * 2][2], B[4 * (tId + i)][2] * delta_lambda[i]);
3361 atomicAdd(&impulse[idx1 * 2 + 1][0], B[4 * (tId + i) + 1][0] * delta_lambda[i]);
3362 atomicAdd(&impulse[idx1 * 2 + 1][1], B[4 * (tId + i) + 1][1] * delta_lambda[i]);
3363 atomicAdd(&impulse[idx1 * 2 + 1][2], B[4 * (tId + i) + 1][2] * delta_lambda[i]);
3365 if (idx2 != INVALID)
3367 atomicAdd(&impulse[idx2 * 2][0], B[4 * (tId + i) + 2][0] * delta_lambda[i]);
3368 atomicAdd(&impulse[idx2 * 2][1], B[4 * (tId + i) + 2][1] * delta_lambda[i]);
3369 atomicAdd(&impulse[idx2 * 2][2], B[4 * (tId + i) + 2][2] * delta_lambda[i]);
3371 atomicAdd(&impulse[idx2 * 2 + 1][0], B[4 * (tId + i) + 3][0] * delta_lambda[i]);
3372 atomicAdd(&impulse[idx2 * 2 + 1][1], B[4 * (tId + i) + 3][1] * delta_lambda[i]);
3373 atomicAdd(&impulse[idx2 * 2 + 1][2], B[4 * (tId + i) + 3][2] * delta_lambda[i]);
3378 if (constraints[tId].type == ConstraintType::CN_ALLOW_ROT1D_1 || constraints[tId].type == ConstraintType::CN_ANCHOR_TRANS_1)
3380 Vec2f tmp(eta[tId], eta[tId + 1]);
3382 for (int i = 0; i < 2; i++)
3384 tmp[i] -= J[4 * (tId + i)].dot(impulse[idx1 * 2]) + J[4 * (tId + i) + 2].dot(impulse[idx2 * 2]);
3385 tmp[i] -= J[4 * (tId + i) + 1].dot(impulse[idx1 * 2 + 1]) + J[4 * (tId + i) + 3].dot(impulse[idx2 * 2 + 1]);
3388 Vec2f delta_lambda = omega * (K_2[tId] * tmp);
3390 for (int i = 0; i < 2; i++)
3392 atomicAdd(&impulse[idx1 * 2][0], B[4 * (tId + i)][0] * delta_lambda[i]);
3393 atomicAdd(&impulse[idx1 * 2][1], B[4 * (tId + i)][1] * delta_lambda[i]);
3394 atomicAdd(&impulse[idx1 * 2][2], B[4 * (tId + i)][2] * delta_lambda[i]);
3396 atomicAdd(&impulse[idx1 * 2 + 1][0], B[4 * (tId + i) + 1][0] * delta_lambda[i]);
3397 atomicAdd(&impulse[idx1 * 2 + 1][1], B[4 * (tId + i) + 1][1] * delta_lambda[i]);
3398 atomicAdd(&impulse[idx1 * 2 + 1][2], B[4 * (tId + i) + 1][2] * delta_lambda[i]);
3400 atomicAdd(&impulse[idx2 * 2][0], B[4 * (tId + i) + 2][0] * delta_lambda[i]);
3401 atomicAdd(&impulse[idx2 * 2][1], B[4 * (tId + i) + 2][1] * delta_lambda[i]);
3402 atomicAdd(&impulse[idx2 * 2][2], B[4 * (tId + i) + 2][2] * delta_lambda[i]);
3404 atomicAdd(&impulse[idx2 * 2 + 1][0], B[4 * (tId + i) + 3][0] * delta_lambda[i]);
3405 atomicAdd(&impulse[idx2 * 2 + 1][1], B[4 * (tId + i) + 3][1] * delta_lambda[i]);
3406 atomicAdd(&impulse[idx2 * 2 + 1][2], B[4 * (tId + i) + 3][2] * delta_lambda[i]);
3410 if (constraints[tId].type == ConstraintType::CN_JOINT_HINGE_MIN || constraints[tId].type == ConstraintType::CN_JOINT_HINGE_MAX || constraints[tId].type == ConstraintType::CN_JOINT_HINGE_MOTER || constraints[tId].type == ConstraintType::CN_JOINT_SLIDER_MIN || constraints[tId].type == ConstraintType::CN_JOINT_SLIDER_MAX || constraints[tId].type == ConstraintType::CN_JOINT_SLIDER_MOTER)
3412 Real tmp = eta[tId];
3413 tmp -= J[4 * tId].dot(impulse[idx1 * 2]) + J[4 * tId + 2].dot(impulse[idx2 * 2]);
3414 tmp -= J[4 * tId + 1].dot(impulse[idx1 * 2 + 1]) + J[4 * tId + 3].dot(impulse[idx2 * 2 + 1]);
3417 Real delta_lambda = tmp * K_1[tId] * omega;
3418 lambda[tId] += delta_lambda;
3419 atomicAdd(&impulse[idx1 * 2][0], B[4 * tId][0] * delta_lambda);
3420 atomicAdd(&impulse[idx1 * 2][1], B[4 * tId][1] * delta_lambda);
3421 atomicAdd(&impulse[idx1 * 2][2], B[4 * tId][2] * delta_lambda);
3423 atomicAdd(&impulse[idx1 * 2 + 1][0], B[4 * tId + 1][0] * delta_lambda);
3424 atomicAdd(&impulse[idx1 * 2 + 1][1], B[4 * tId + 1][1] * delta_lambda);
3425 atomicAdd(&impulse[idx1 * 2 + 1][2], B[4 * tId + 1][2] * delta_lambda);
3427 atomicAdd(&impulse[idx2 * 2][0], B[4 * tId + 2][0] * delta_lambda);
3428 atomicAdd(&impulse[idx2 * 2][1], B[4 * tId + 2][1] * delta_lambda);
3429 atomicAdd(&impulse[idx2 * 2][2], B[4 * tId + 2][2] * delta_lambda);
3431 atomicAdd(&impulse[idx2 * 2 + 1][0], B[4 * tId + 3][0] * delta_lambda);
3432 atomicAdd(&impulse[idx2 * 2 + 1][1], B[4 * tId + 3][1] * delta_lambda);
3433 atomicAdd(&impulse[idx2 * 2 + 1][2], B[4 * tId + 3][2] * delta_lambda);
3437 if (constraints[tId].type == ConstraintType::CN_JOINT_NO_MOVE_1)
3439 Coord tmp(eta[tId], eta[tId + 1], eta[tId + 2]);
3440 for (int i = 0; i < 3; i++)
3442 tmp[i] -= J[4 * (tId + i)].dot(impulse[idx1 * 2]);
3445 Coord delta_lambda = omega * (K_3[tId] * tmp);
3446 for (int i = 0; i < 3; i++)
3448 atomicAdd(&impulse[idx1 * 2][0], B[4 * (tId + i)][0] * delta_lambda[i]);
3449 atomicAdd(&impulse[idx1 * 2][1], B[4 * (tId + i)][1] * delta_lambda[i]);
3450 atomicAdd(&impulse[idx1 * 2][2], B[4 * (tId + i)][2] * delta_lambda[i]);
3452 atomicAdd(&impulse[idx1 * 2 + 1][0], B[4 * (tId + i) + 1][0] * delta_lambda[i]);
3453 atomicAdd(&impulse[idx1 * 2 + 1][1], B[4 * (tId + i) + 1][1] * delta_lambda[i]);
3454 atomicAdd(&impulse[idx1 * 2 + 1][2], B[4 * (tId + i) + 1][2] * delta_lambda[i]);
3459 template<typename Real, typename Coord, typename Constraint, typename Matrix3, typename Matrix2>
3460 __global__ void SF_JacobiIterationForCFM(
3461 DArray<Real> lambda,
3462 DArray<Coord> impulse,
3466 DArray<Constraint> constraints,
3469 DArray<Matrix2> K_2,
3470 DArray<Matrix3> K_3,
3478 int tId = threadIdx.x + blockIdx.x * blockDim.x;
3479 if (tId >= constraints.size())
3483 int idx1 = constraints[tId].bodyId1;
3484 int idx2 = constraints[tId].bodyId2;
3489 int stepInverse = 0;
3490 if (constraints[tId].type == ConstraintType::CN_FRICTION || constraints[tId].type == ConstraintType::CN_NONPENETRATION)
3492 if (idx2 != INVALID)
3494 stepInverse = nbq[idx1] + nbq[idx2];
3498 stepInverse = nbq[idx1];
3506 Real omega = Real(1) / stepInverse;
3508 if (constraints[tId].type == ConstraintType::CN_FRICTION || constraints[tId].type == ConstraintType::CN_NONPENETRATION)
3510 Real tmp = eta[tId];
3511 tmp -= J[4 * tId].dot(impulse[idx1 * 2]);
3512 tmp -= J[4 * tId + 1].dot(impulse[idx1 * 2 + 1]);
3513 if (idx2 != INVALID)
3515 tmp -= J[4 * tId + 2].dot(impulse[idx2 * 2]);
3516 tmp -= J[4 * tId + 3].dot(impulse[idx2 * 2 + 1]);
3519 tmp -= lambda[tId] * CFM[tId];
3521 Real delta_lambda = 0;
3522 if (constraints[tId].type == ConstraintType::CN_NONPENETRATION)
3524 Real lambda_new = maximum(0.0f, lambda[tId] + (tmp * K_1[tId] * omega));
3525 delta_lambda = lambda_new - lambda[tId];
3529 lambda[tId] += delta_lambda;
3531 atomicAdd(&impulse[idx1 * 2][0], B[4 * tId][0] * delta_lambda);
3532 atomicAdd(&impulse[idx1 * 2][1], B[4 * tId][1] * delta_lambda);
3533 atomicAdd(&impulse[idx1 * 2][2], B[4 * tId][2] * delta_lambda);
3535 atomicAdd(&impulse[idx1 * 2 + 1][0], B[4 * tId + 1][0] * delta_lambda);
3536 atomicAdd(&impulse[idx1 * 2 + 1][1], B[4 * tId + 1][1] * delta_lambda);
3537 atomicAdd(&impulse[idx1 * 2 + 1][2], B[4 * tId + 1][2] * delta_lambda);
3539 if (idx2 != INVALID)
3541 atomicAdd(&impulse[idx2 * 2][0], B[4 * tId + 2][0] * delta_lambda);
3542 atomicAdd(&impulse[idx2 * 2][1], B[4 * tId + 2][1] * delta_lambda);
3543 atomicAdd(&impulse[idx2 * 2][2], B[4 * tId + 2][2] * delta_lambda);
3545 atomicAdd(&impulse[idx2 * 2 + 1][0], B[4 * tId + 3][0] * delta_lambda);
3546 atomicAdd(&impulse[idx2 * 2 + 1][1], B[4 * tId + 3][1] * delta_lambda);
3547 atomicAdd(&impulse[idx2 * 2 + 1][2], B[4 * tId + 3][2] * delta_lambda);
3551 if (constraints[tId].type == ConstraintType::CN_ANCHOR_EQUAL_1 || constraints[tId].type == ConstraintType::CN_BAN_ROT_1)
3553 Coord tmp(eta[tId], eta[tId + 1], eta[tId + 2]);
3554 if (idx2 != INVALID)
3556 for (int i = 0; i < 3; i++)
3558 tmp[i] -= J[4 * (tId + i)].dot(impulse[idx1 * 2]) + J[4 * (tId + i) + 2].dot(impulse[idx2 * 2]);
3559 tmp[i] -= J[4 * (tId + i) + 1].dot(impulse[idx1 * 2 + 1]) + J[4 * (tId + i) + 3].dot(impulse[idx2 * 2 + 1]);
3560 tmp[i] -= lambda[tId + i] * CFM[tId + i];
3565 for (int i = 0; i < 3; i++)
3567 tmp[i] -= J[4 * (tId + i)].dot(impulse[idx1 * 2]);
3568 tmp[i] -= J[4 * (tId + i) + 1].dot(impulse[idx1 * 2 + 1]);
3569 tmp[i] -= lambda[tId + i] * CFM[tId + i];
3573 Coord delta_lambda = omega * (K_3[tId] * tmp);
3575 for (int i = 0; i < 3; i++)
3577 lambda[tId + i] += delta_lambda[i];
3578 atomicAdd(&impulse[idx1 * 2][0], B[4 * (tId + i)][0] * delta_lambda[i]);
3579 atomicAdd(&impulse[idx1 * 2][1], B[4 * (tId + i)][1] * delta_lambda[i]);
3580 atomicAdd(&impulse[idx1 * 2][2], B[4 * (tId + i)][2] * delta_lambda[i]);
3582 atomicAdd(&impulse[idx1 * 2 + 1][0], B[4 * (tId + i) + 1][0] * delta_lambda[i]);
3583 atomicAdd(&impulse[idx1 * 2 + 1][1], B[4 * (tId + i) + 1][1] * delta_lambda[i]);
3584 atomicAdd(&impulse[idx1 * 2 + 1][2], B[4 * (tId + i) + 1][2] * delta_lambda[i]);
3586 if (idx2 != INVALID)
3588 atomicAdd(&impulse[idx2 * 2][0], B[4 * (tId + i) + 2][0] * delta_lambda[i]);
3589 atomicAdd(&impulse[idx2 * 2][1], B[4 * (tId + i) + 2][1] * delta_lambda[i]);
3590 atomicAdd(&impulse[idx2 * 2][2], B[4 * (tId + i) + 2][2] * delta_lambda[i]);
3592 atomicAdd(&impulse[idx2 * 2 + 1][0], B[4 * (tId + i) + 3][0] * delta_lambda[i]);
3593 atomicAdd(&impulse[idx2 * 2 + 1][1], B[4 * (tId + i) + 3][1] * delta_lambda[i]);
3594 atomicAdd(&impulse[idx2 * 2 + 1][2], B[4 * (tId + i) + 3][2] * delta_lambda[i]);
3599 if (constraints[tId].type == ConstraintType::CN_ALLOW_ROT1D_1 || constraints[tId].type == ConstraintType::CN_ANCHOR_TRANS_1)
3601 Vec2f tmp(eta[tId], eta[tId + 1]);
3603 for (int i = 0; i < 2; i++)
3605 tmp[i] -= J[4 * (tId + i)].dot(impulse[idx1 * 2]) + J[4 * (tId + i) + 2].dot(impulse[idx2 * 2]);
3606 tmp[i] -= J[4 * (tId + i) + 1].dot(impulse[idx1 * 2 + 1]) + J[4 * (tId + i) + 3].dot(impulse[idx2 * 2 + 1]);
3607 tmp[i] -= lambda[tId + i] * CFM[tId + i];
3610 Vec2f delta_lambda = omega * (K_2[tId] * tmp);
3612 for (int i = 0; i < 2; i++)
3614 lambda[tId + i] += delta_lambda[i];
3615 atomicAdd(&impulse[idx1 * 2][0], B[4 * (tId + i)][0] * delta_lambda[i]);
3616 atomicAdd(&impulse[idx1 * 2][1], B[4 * (tId + i)][1] * delta_lambda[i]);
3617 atomicAdd(&impulse[idx1 * 2][2], B[4 * (tId + i)][2] * delta_lambda[i]);
3619 atomicAdd(&impulse[idx1 * 2 + 1][0], B[4 * (tId + i) + 1][0] * delta_lambda[i]);
3620 atomicAdd(&impulse[idx1 * 2 + 1][1], B[4 * (tId + i) + 1][1] * delta_lambda[i]);
3621 atomicAdd(&impulse[idx1 * 2 + 1][2], B[4 * (tId + i) + 1][2] * delta_lambda[i]);
3623 atomicAdd(&impulse[idx2 * 2][0], B[4 * (tId + i) + 2][0] * delta_lambda[i]);
3624 atomicAdd(&impulse[idx2 * 2][1], B[4 * (tId + i) + 2][1] * delta_lambda[i]);
3625 atomicAdd(&impulse[idx2 * 2][2], B[4 * (tId + i) + 2][2] * delta_lambda[i]);
3627 atomicAdd(&impulse[idx2 * 2 + 1][0], B[4 * (tId + i) + 3][0] * delta_lambda[i]);
3628 atomicAdd(&impulse[idx2 * 2 + 1][1], B[4 * (tId + i) + 3][1] * delta_lambda[i]);
3629 atomicAdd(&impulse[idx2 * 2 + 1][2], B[4 * (tId + i) + 3][2] * delta_lambda[i]);
3633 if (constraints[tId].type == ConstraintType::CN_JOINT_HINGE_MIN || constraints[tId].type == ConstraintType::CN_JOINT_HINGE_MAX || constraints[tId].type == ConstraintType::CN_JOINT_HINGE_MOTER || constraints[tId].type == ConstraintType::CN_JOINT_SLIDER_MIN || constraints[tId].type == ConstraintType::CN_JOINT_SLIDER_MAX || constraints[tId].type == ConstraintType::CN_JOINT_SLIDER_MOTER)
3635 Real tmp = eta[tId];
3636 tmp -= J[4 * tId].dot(impulse[idx1 * 2]) + J[4 * tId + 2].dot(impulse[idx2 * 2]);
3637 tmp -= J[4 * tId + 1].dot(impulse[idx1 * 2 + 1]) + J[4 * tId + 3].dot(impulse[idx2 * 2 + 1]);
3638 tmp -= lambda[tId] * CFM[tId];
3641 Real delta_lambda = tmp * (K_1[tId] * omega);
3642 lambda[tId] += delta_lambda;
3643 atomicAdd(&impulse[idx1 * 2][0], B[4 * tId][0] * delta_lambda);
3644 atomicAdd(&impulse[idx1 * 2][1], B[4 * tId][1] * delta_lambda);
3645 atomicAdd(&impulse[idx1 * 2][2], B[4 * tId][2] * delta_lambda);
3647 atomicAdd(&impulse[idx1 * 2 + 1][0], B[4 * tId + 1][0] * delta_lambda);
3648 atomicAdd(&impulse[idx1 * 2 + 1][1], B[4 * tId + 1][1] * delta_lambda);
3649 atomicAdd(&impulse[idx1 * 2 + 1][2], B[4 * tId + 1][2] * delta_lambda);
3651 atomicAdd(&impulse[idx2 * 2][0], B[4 * tId + 2][0] * delta_lambda);
3652 atomicAdd(&impulse[idx2 * 2][1], B[4 * tId + 2][1] * delta_lambda);
3653 atomicAdd(&impulse[idx2 * 2][2], B[4 * tId + 2][2] * delta_lambda);
3655 atomicAdd(&impulse[idx2 * 2 + 1][0], B[4 * tId + 3][0] * delta_lambda);
3656 atomicAdd(&impulse[idx2 * 2 + 1][1], B[4 * tId + 3][1] * delta_lambda);
3657 atomicAdd(&impulse[idx2 * 2 + 1][2], B[4 * tId + 3][2] * delta_lambda);
3661 if (constraints[tId].type == ConstraintType::CN_JOINT_NO_MOVE_1)
3663 Coord tmp(eta[tId], eta[tId + 1], eta[tId + 2]);
3664 for (int i = 0; i < 3; i++)
3666 tmp[i] -= J[4 * (tId + i)].dot(impulse[idx1 * 2]);
3667 tmp[i] -= lambda[tId + i] * CFM[tId + i];
3670 Coord delta_lambda = omega * (K_3[tId] * tmp);
3671 for (int i = 0; i < 3; i++)
3673 lambda[tId + i] += delta_lambda[i];
3674 atomicAdd(&impulse[idx1 * 2][0], B[4 * (tId + i)][0] * delta_lambda[i]);
3675 atomicAdd(&impulse[idx1 * 2][1], B[4 * (tId + i)][1] * delta_lambda[i]);
3676 atomicAdd(&impulse[idx1 * 2][2], B[4 * (tId + i)][2] * delta_lambda[i]);
3678 atomicAdd(&impulse[idx1 * 2 + 1][0], B[4 * (tId + i) + 1][0] * delta_lambda[i]);
3679 atomicAdd(&impulse[idx1 * 2 + 1][1], B[4 * (tId + i) + 1][1] * delta_lambda[i]);
3680 atomicAdd(&impulse[idx1 * 2 + 1][2], B[4 * (tId + i) + 1][2] * delta_lambda[i]);
3686 template<typename Real, typename Coord, typename Constraint, typename Matrix3, typename Matrix2>
3687 __global__ void SF_JacobiIterationForNJS(
3688 DArray<Real> lambda,
3689 DArray<Coord> impulse,
3693 DArray<Constraint> constraints,
3696 DArray<Matrix2> K_2,
3700 int tId = threadIdx.x + blockIdx.x * blockDim.x;
3701 if (tId >= constraints.size())
3705 int idx1 = constraints[tId].bodyId1;
3706 int idx2 = constraints[tId].bodyId2;
3708 int stepInverse = 0;
3709 if (constraints[tId].type == ConstraintType::CN_NONPENETRATION)
3711 if (idx2 != INVALID)
3713 stepInverse = nbq[idx1] > nbq[idx2] ? nbq[idx1] : nbq[idx2];
3717 stepInverse = nbq[idx1];
3725 Real omega = Real(1) / stepInverse;
3727 if (constraints[tId].type == ConstraintType::CN_NONPENETRATION)
3729 Real tmp = eta[tId];
3730 tmp -= J[4 * tId].dot(impulse[idx1 * 2]);
3731 tmp -= J[4 * tId + 1].dot(impulse[idx1 * 2 + 1]);
3732 if (idx2 != INVALID)
3734 tmp -= J[4 * tId + 2].dot(impulse[idx2 * 2]);
3735 tmp -= J[4 * tId + 3].dot(impulse[idx2 * 2 + 1]);
3737 Real delta_lambda = 0;
3738 Real lambda_new = maximum(0.0f, lambda[tId] + (tmp / (K_1[tId] * stepInverse)));
3739 delta_lambda = lambda_new - lambda[tId];
3742 lambda[tId] += delta_lambda;
3744 atomicAdd(&impulse[idx1 * 2][0], B[4 * tId][0] * delta_lambda);
3745 atomicAdd(&impulse[idx1 * 2][1], B[4 * tId][1] * delta_lambda);
3746 atomicAdd(&impulse[idx1 * 2][2], B[4 * tId][2] * delta_lambda);
3748 atomicAdd(&impulse[idx1 * 2 + 1][0], B[4 * tId + 1][0] * delta_lambda);
3749 atomicAdd(&impulse[idx1 * 2 + 1][1], B[4 * tId + 1][1] * delta_lambda);
3750 atomicAdd(&impulse[idx1 * 2 + 1][2], B[4 * tId + 1][2] * delta_lambda);
3752 if (idx2 != INVALID)
3754 atomicAdd(&impulse[idx2 * 2][0], B[4 * tId + 2][0] * delta_lambda);
3755 atomicAdd(&impulse[idx2 * 2][1], B[4 * tId + 2][1] * delta_lambda);
3756 atomicAdd(&impulse[idx2 * 2][2], B[4 * tId + 2][2] * delta_lambda);
3758 atomicAdd(&impulse[idx2 * 2 + 1][0], B[4 * tId + 3][0] * delta_lambda);
3759 atomicAdd(&impulse[idx2 * 2 + 1][1], B[4 * tId + 3][1] * delta_lambda);
3760 atomicAdd(&impulse[idx2 * 2 + 1][2], B[4 * tId + 3][2] * delta_lambda);
3764 if (constraints[tId].type == ConstraintType::CN_ANCHOR_EQUAL_1 || constraints[tId].type == ConstraintType::CN_BAN_ROT_1)
3766 Coord tmp(eta[tId], eta[tId + 1], eta[tId + 2]);
3767 if (idx2 != INVALID)
3769 for (int i = 0; i < 3; i++)
3771 tmp[i] -= J[4 * (tId + i)].dot(impulse[idx1 * 2]) + J[4 * (tId + i) + 2].dot(impulse[idx2 * 2]);
3772 tmp[i] -= J[4 * (tId + i) + 1].dot(impulse[idx1 * 2 + 1]) + J[4 * (tId + i) + 3].dot(impulse[idx2 * 2 + 1]);
3777 for (int i = 0; i < 3; i++)
3779 tmp[i] -= J[4 * (tId + i)].dot(impulse[idx1 * 2]);
3780 tmp[i] -= J[4 * (tId + i) + 1].dot(impulse[idx1 * 2 + 1]);
3784 Coord delta_lambda = omega * (K_3[tId].inverse() * tmp);
3786 for (int i = 0; i < 3; i++)
3788 atomicAdd(&impulse[idx1 * 2][0], B[4 * (tId + i)][0] * delta_lambda[i]);
3789 atomicAdd(&impulse[idx1 * 2][1], B[4 * (tId + i)][1] * delta_lambda[i]);
3790 atomicAdd(&impulse[idx1 * 2][2], B[4 * (tId + i)][2] * delta_lambda[i]);
3792 atomicAdd(&impulse[idx1 * 2 + 1][0], B[4 * (tId + i) + 1][0] * delta_lambda[i]);
3793 atomicAdd(&impulse[idx1 * 2 + 1][1], B[4 * (tId + i) + 1][1] * delta_lambda[i]);
3794 atomicAdd(&impulse[idx1 * 2 + 1][2], B[4 * (tId + i) + 1][2] * delta_lambda[i]);
3796 if (idx2 != INVALID)
3798 atomicAdd(&impulse[idx2 * 2][0], B[4 * (tId + i) + 2][0] * delta_lambda[i]);
3799 atomicAdd(&impulse[idx2 * 2][1], B[4 * (tId + i) + 2][1] * delta_lambda[i]);
3800 atomicAdd(&impulse[idx2 * 2][2], B[4 * (tId + i) + 2][2] * delta_lambda[i]);
3802 atomicAdd(&impulse[idx2 * 2 + 1][0], B[4 * (tId + i) + 3][0] * delta_lambda[i]);
3803 atomicAdd(&impulse[idx2 * 2 + 1][1], B[4 * (tId + i) + 3][1] * delta_lambda[i]);
3804 atomicAdd(&impulse[idx2 * 2 + 1][2], B[4 * (tId + i) + 3][2] * delta_lambda[i]);
3809 if (constraints[tId].type == ConstraintType::CN_ALLOW_ROT1D_1 || constraints[tId].type == ConstraintType::CN_ANCHOR_TRANS_1)
3811 Vec2f tmp(eta[tId], eta[tId + 1]);
3813 for (int i = 0; i < 2; i++)
3815 tmp[i] -= J[4 * (tId + i)].dot(impulse[idx1 * 2]) + J[4 * (tId + i) + 2].dot(impulse[idx2 * 2]);
3816 tmp[i] -= J[4 * (tId + i) + 1].dot(impulse[idx1 * 2 + 1]) + J[4 * (tId + i) + 3].dot(impulse[idx2 * 2 + 1]);
3819 Vec2f delta_lambda = omega * (K_2[tId].inverse() * tmp);
3821 for (int i = 0; i < 2; i++)
3823 atomicAdd(&impulse[idx1 * 2][0], B[4 * (tId + i)][0] * delta_lambda[i]);
3824 atomicAdd(&impulse[idx1 * 2][1], B[4 * (tId + i)][1] * delta_lambda[i]);
3825 atomicAdd(&impulse[idx1 * 2][2], B[4 * (tId + i)][2] * delta_lambda[i]);
3827 atomicAdd(&impulse[idx1 * 2 + 1][0], B[4 * (tId + i) + 1][0] * delta_lambda[i]);
3828 atomicAdd(&impulse[idx1 * 2 + 1][1], B[4 * (tId + i) + 1][1] * delta_lambda[i]);
3829 atomicAdd(&impulse[idx1 * 2 + 1][2], B[4 * (tId + i) + 1][2] * delta_lambda[i]);
3831 atomicAdd(&impulse[idx2 * 2][0], B[4 * (tId + i) + 2][0] * delta_lambda[i]);
3832 atomicAdd(&impulse[idx2 * 2][1], B[4 * (tId + i) + 2][1] * delta_lambda[i]);
3833 atomicAdd(&impulse[idx2 * 2][2], B[4 * (tId + i) + 2][2] * delta_lambda[i]);
3835 atomicAdd(&impulse[idx2 * 2 + 1][0], B[4 * (tId + i) + 3][0] * delta_lambda[i]);
3836 atomicAdd(&impulse[idx2 * 2 + 1][1], B[4 * (tId + i) + 3][1] * delta_lambda[i]);
3837 atomicAdd(&impulse[idx2 * 2 + 1][2], B[4 * (tId + i) + 3][2] * delta_lambda[i]);
3841 if (constraints[tId].type == ConstraintType::CN_JOINT_HINGE_MIN || constraints[tId].type == ConstraintType::CN_JOINT_HINGE_MAX || constraints[tId].type == ConstraintType::CN_JOINT_SLIDER_MIN || constraints[tId].type == ConstraintType::CN_JOINT_SLIDER_MAX)
3843 Real tmp = eta[tId];
3844 tmp -= J[4 * tId].dot(impulse[idx1 * 2]) + J[4 * tId + 2].dot(impulse[idx2 * 2]);
3845 tmp -= J[4 * tId + 1].dot(impulse[idx1 * 2 + 1]) + J[4 * tId + 3].dot(impulse[idx2 * 2 + 1]);
3848 Real delta_lambda = tmp / (K_1[tId] * stepInverse);
3849 lambda[tId] += delta_lambda;
3850 atomicAdd(&impulse[idx1 * 2][0], B[4 * tId][0] * delta_lambda);
3851 atomicAdd(&impulse[idx1 * 2][1], B[4 * tId][1] * delta_lambda);
3852 atomicAdd(&impulse[idx1 * 2][2], B[4 * tId][2] * delta_lambda);
3854 atomicAdd(&impulse[idx1 * 2 + 1][0], B[4 * tId + 1][0] * delta_lambda);
3855 atomicAdd(&impulse[idx1 * 2 + 1][1], B[4 * tId + 1][1] * delta_lambda);
3856 atomicAdd(&impulse[idx1 * 2 + 1][2], B[4 * tId + 1][2] * delta_lambda);
3858 atomicAdd(&impulse[idx2 * 2][0], B[4 * tId + 2][0] * delta_lambda);
3859 atomicAdd(&impulse[idx2 * 2][1], B[4 * tId + 2][1] * delta_lambda);
3860 atomicAdd(&impulse[idx2 * 2][2], B[4 * tId + 2][2] * delta_lambda);
3862 atomicAdd(&impulse[idx2 * 2 + 1][0], B[4 * tId + 3][0] * delta_lambda);
3863 atomicAdd(&impulse[idx2 * 2 + 1][1], B[4 * tId + 3][1] * delta_lambda);
3864 atomicAdd(&impulse[idx2 * 2 + 1][2], B[4 * tId + 3][2] * delta_lambda);
3868 if (constraints[tId].type == ConstraintType::CN_JOINT_NO_MOVE_1)
3870 Coord tmp(eta[tId], eta[tId + 1], eta[tId + 2]);
3871 for (int i = 0; i < 3; i++)
3873 tmp[i] -= J[4 * (tId + i)].dot(impulse[idx1 * 2]);
3876 Coord delta_lambda = omega * (K_3[tId].inverse() * tmp);
3877 for (int i = 0; i < 3; i++)
3879 atomicAdd(&impulse[idx1 * 2][0], B[4 * (tId + i)][0] * delta_lambda[i]);
3880 atomicAdd(&impulse[idx1 * 2][1], B[4 * (tId + i)][1] * delta_lambda[i]);
3881 atomicAdd(&impulse[idx1 * 2][2], B[4 * (tId + i)][2] * delta_lambda[i]);
3883 atomicAdd(&impulse[idx1 * 2 + 1][0], B[4 * (tId + i) + 1][0] * delta_lambda[i]);
3884 atomicAdd(&impulse[idx1 * 2 + 1][1], B[4 * (tId + i) + 1][1] * delta_lambda[i]);
3885 atomicAdd(&impulse[idx1 * 2 + 1][2], B[4 * (tId + i) + 1][2] * delta_lambda[i]);
3890 template<typename Real, typename Coord, typename Constraint, typename Matrix3, typename Matrix2>
3891 __global__ void SF_JacobiIterationForSoft(
3892 DArray<Real> lambda,
3893 DArray<Coord> impulse,
3897 DArray<Constraint> constraints,
3900 DArray<Matrix2> K_2,
3901 DArray<Matrix3> K_3,
3910 int tId = threadIdx.x + blockIdx.x * blockDim.x;
3911 if (tId >= constraints.size())
3915 int idx1 = constraints[tId].bodyId1;
3916 int idx2 = constraints[tId].bodyId2;
3918 Real ome = 2.0f * M_PI * hertz;
3919 Real a1 = 2.0 * zeta + ome * dt;
3920 Real a2 = dt * ome * a1;
3921 Real a3 = 1.0f / (1.0f + a2);
3922 Real massCoeff = a2 * a3;
3923 Real impulseCoeff = a3;
3925 int stepInverse = 0;
3926 if (constraints[tId].type == ConstraintType::CN_FRICTION || constraints[tId].type == ConstraintType::CN_NONPENETRATION)
3928 if (idx2 != INVALID)
3930 stepInverse = nbq[idx1] > nbq[idx2] ? nbq[idx1] : nbq[idx2];
3934 stepInverse = nbq[idx1];
3942 Real omega = Real(1) / stepInverse;
3944 if (constraints[tId].type == ConstraintType::CN_FRICTION || constraints[tId].type == ConstraintType::CN_NONPENETRATION)
3946 Real tmp = eta[tId];
3947 tmp -= J[4 * tId].dot(impulse[idx1 * 2]);
3948 tmp -= J[4 * tId + 1].dot(impulse[idx1 * 2 + 1]);
3949 if (idx2 != INVALID)
3951 tmp -= J[4 * tId + 2].dot(impulse[idx2 * 2]);
3952 tmp -= J[4 * tId + 3].dot(impulse[idx2 * 2 + 1]);
3954 Real delta_lambda = 0;
3955 if (constraints[tId].type == ConstraintType::CN_NONPENETRATION)
3957 Real lambda_new = maximum(0.0f, lambda[tId] + omega * (massCoeff * tmp * K_1[tId] - impulseCoeff * lambda[tId]));
3958 delta_lambda = lambda_new - lambda[tId];
3960 if (constraints[tId].type == ConstraintType::CN_FRICTION)
3962 Real mass_avl = mass[idx1];
3963 Real mu_i = mu[idx1];
3964 if (idx2 != INVALID)
3966 mass_avl = (mass_avl + mass[idx2]) / 2;
3967 mu_i = (mu_i + mu[idx2]) / 2;
3969 Real lambda_new = minimum(maximum(lambda[tId] + omega * (massCoeff * tmp * K_1[tId] - impulseCoeff * lambda[tId]), -mu_i * mass_avl * g * dt), mu_i * mass_avl * g * dt);
3970 delta_lambda = lambda_new - lambda[tId];
3974 lambda[tId] += delta_lambda;
3976 atomicAdd(&impulse[idx1 * 2][0], B[4 * tId][0] * delta_lambda);
3977 atomicAdd(&impulse[idx1 * 2][1], B[4 * tId][1] * delta_lambda);
3978 atomicAdd(&impulse[idx1 * 2][2], B[4 * tId][2] * delta_lambda);
3980 atomicAdd(&impulse[idx1 * 2 + 1][0], B[4 * tId + 1][0] * delta_lambda);
3981 atomicAdd(&impulse[idx1 * 2 + 1][1], B[4 * tId + 1][1] * delta_lambda);
3982 atomicAdd(&impulse[idx1 * 2 + 1][2], B[4 * tId + 1][2] * delta_lambda);
3984 if (idx2 != INVALID)
3986 atomicAdd(&impulse[idx2 * 2][0], B[4 * tId + 2][0] * delta_lambda);
3987 atomicAdd(&impulse[idx2 * 2][1], B[4 * tId + 2][1] * delta_lambda);
3988 atomicAdd(&impulse[idx2 * 2][2], B[4 * tId + 2][2] * delta_lambda);
3990 atomicAdd(&impulse[idx2 * 2 + 1][0], B[4 * tId + 3][0] * delta_lambda);
3991 atomicAdd(&impulse[idx2 * 2 + 1][1], B[4 * tId + 3][1] * delta_lambda);
3992 atomicAdd(&impulse[idx2 * 2 + 1][2], B[4 * tId + 3][2] * delta_lambda);
3995 if (constraints[tId].type == ConstraintType::CN_ANCHOR_EQUAL_1 || constraints[tId].type == ConstraintType::CN_BAN_ROT_1)
3997 Coord tmp(eta[tId], eta[tId + 1], eta[tId + 2]);
3998 if (idx2 != INVALID)
4000 for (int i = 0; i < 3; i++)
4002 tmp[i] -= J[4 * (tId + i)].dot(impulse[idx1 * 2]) + J[4 * (tId + i) + 2].dot(impulse[idx2 * 2]);
4003 tmp[i] -= J[4 * (tId + i) + 1].dot(impulse[idx1 * 2 + 1]) + J[4 * (tId + i) + 3].dot(impulse[idx2 * 2 + 1]);
4008 for (int i = 0; i < 3; i++)
4010 tmp[i] -= J[4 * (tId + i)].dot(impulse[idx1 * 2]);
4011 tmp[i] -= J[4 * (tId + i) + 1].dot(impulse[idx1 * 2 + 1]);
4014 Coord tmp_lambda(lambda[tId], lambda[tId + 1], lambda[tId + 2]);
4015 Coord delta_lambda = omega * (massCoeff * K_3[tId] * tmp - impulseCoeff * tmp_lambda);
4017 for (int i = 0; i < 3; i++)
4019 atomicAdd(&impulse[idx1 * 2][0], B[4 * (tId + i)][0] * delta_lambda[i]);
4020 atomicAdd(&impulse[idx1 * 2][1], B[4 * (tId + i)][1] * delta_lambda[i]);
4021 atomicAdd(&impulse[idx1 * 2][2], B[4 * (tId + i)][2] * delta_lambda[i]);
4023 atomicAdd(&impulse[idx1 * 2 + 1][0], B[4 * (tId + i) + 1][0] * delta_lambda[i]);
4024 atomicAdd(&impulse[idx1 * 2 + 1][1], B[4 * (tId + i) + 1][1] * delta_lambda[i]);
4025 atomicAdd(&impulse[idx1 * 2 + 1][2], B[4 * (tId + i) + 1][2] * delta_lambda[i]);
4027 if (idx2 != INVALID)
4029 atomicAdd(&impulse[idx2 * 2][0], B[4 * (tId + i) + 2][0] * delta_lambda[i]);
4030 atomicAdd(&impulse[idx2 * 2][1], B[4 * (tId + i) + 2][1] * delta_lambda[i]);
4031 atomicAdd(&impulse[idx2 * 2][2], B[4 * (tId + i) + 2][2] * delta_lambda[i]);
4033 atomicAdd(&impulse[idx2 * 2 + 1][0], B[4 * (tId + i) + 3][0] * delta_lambda[i]);
4034 atomicAdd(&impulse[idx2 * 2 + 1][1], B[4 * (tId + i) + 3][1] * delta_lambda[i]);
4035 atomicAdd(&impulse[idx2 * 2 + 1][2], B[4 * (tId + i) + 3][2] * delta_lambda[i]);
4040 if (constraints[tId].type == ConstraintType::CN_ALLOW_ROT1D_1 || constraints[tId].type == ConstraintType::CN_ANCHOR_TRANS_1)
4042 Vec2f tmp(eta[tId], eta[tId + 1]);
4044 for (int i = 0; i < 2; i++)
4046 tmp[i] -= J[4 * (tId + i)].dot(impulse[idx1 * 2]) + J[4 * (tId + i) + 2].dot(impulse[idx2 * 2]);
4047 tmp[i] -= J[4 * (tId + i) + 1].dot(impulse[idx1 * 2 + 1]) + J[4 * (tId + i) + 3].dot(impulse[idx2 * 2 + 1]);
4049 Vec2f oldLambda(lambda[tId], lambda[tId + 1]);
4050 Vec2f delta_lambda = omega * (massCoeff * K_2[tId] * tmp - impulseCoeff * oldLambda);
4053 for (int i = 0; i < 2; i++)
4055 lambda[tId + i] += delta_lambda[i];
4056 atomicAdd(&impulse[idx1 * 2][0], B[4 * (tId + i)][0] * delta_lambda[i]);
4057 atomicAdd(&impulse[idx1 * 2][1], B[4 * (tId + i)][1] * delta_lambda[i]);
4058 atomicAdd(&impulse[idx1 * 2][2], B[4 * (tId + i)][2] * delta_lambda[i]);
4060 atomicAdd(&impulse[idx1 * 2 + 1][0], B[4 * (tId + i) + 1][0] * delta_lambda[i]);
4061 atomicAdd(&impulse[idx1 * 2 + 1][1], B[4 * (tId + i) + 1][1] * delta_lambda[i]);
4062 atomicAdd(&impulse[idx1 * 2 + 1][2], B[4 * (tId + i) + 1][2] * delta_lambda[i]);
4064 atomicAdd(&impulse[idx2 * 2][0], B[4 * (tId + i) + 2][0] * delta_lambda[i]);
4065 atomicAdd(&impulse[idx2 * 2][1], B[4 * (tId + i) + 2][1] * delta_lambda[i]);
4066 atomicAdd(&impulse[idx2 * 2][2], B[4 * (tId + i) + 2][2] * delta_lambda[i]);
4068 atomicAdd(&impulse[idx2 * 2 + 1][0], B[4 * (tId + i) + 3][0] * delta_lambda[i]);
4069 atomicAdd(&impulse[idx2 * 2 + 1][1], B[4 * (tId + i) + 3][1] * delta_lambda[i]);
4070 atomicAdd(&impulse[idx2 * 2 + 1][2], B[4 * (tId + i) + 3][2] * delta_lambda[i]);
4074 if (constraints[tId].type == ConstraintType::CN_JOINT_HINGE_MIN || constraints[tId].type == ConstraintType::CN_JOINT_HINGE_MAX || constraints[tId].type == ConstraintType::CN_JOINT_HINGE_MOTER || constraints[tId].type == ConstraintType::CN_JOINT_SLIDER_MIN || constraints[tId].type == ConstraintType::CN_JOINT_SLIDER_MAX || constraints[tId].type == ConstraintType::CN_JOINT_SLIDER_MOTER)
4076 Real tmp = eta[tId];
4077 tmp -= J[4 * tId].dot(impulse[idx1 * 2]) + J[4 * tId + 2].dot(impulse[idx2 * 2]);
4078 tmp -= J[4 * tId + 1].dot(impulse[idx1 * 2 + 1]) + J[4 * tId + 3].dot(impulse[idx2 * 2 + 1]);
4081 Real delta_lambda = omega * (massCoeff * K_1[tId] * tmp - impulseCoeff * lambda[tId]);
4082 lambda[tId] += delta_lambda;
4083 atomicAdd(&impulse[idx1 * 2][0], B[4 * tId][0] * delta_lambda);
4084 atomicAdd(&impulse[idx1 * 2][1], B[4 * tId][1] * delta_lambda);
4085 atomicAdd(&impulse[idx1 * 2][2], B[4 * tId][2] * delta_lambda);
4087 atomicAdd(&impulse[idx1 * 2 + 1][0], B[4 * tId + 1][0] * delta_lambda);
4088 atomicAdd(&impulse[idx1 * 2 + 1][1], B[4 * tId + 1][1] * delta_lambda);
4089 atomicAdd(&impulse[idx1 * 2 + 1][2], B[4 * tId + 1][2] * delta_lambda);
4091 atomicAdd(&impulse[idx2 * 2][0], B[4 * tId + 2][0] * delta_lambda);
4092 atomicAdd(&impulse[idx2 * 2][1], B[4 * tId + 2][1] * delta_lambda);
4093 atomicAdd(&impulse[idx2 * 2][2], B[4 * tId + 2][2] * delta_lambda);
4095 atomicAdd(&impulse[idx2 * 2 + 1][0], B[4 * tId + 3][0] * delta_lambda);
4096 atomicAdd(&impulse[idx2 * 2 + 1][1], B[4 * tId + 3][1] * delta_lambda);
4097 atomicAdd(&impulse[idx2 * 2 + 1][2], B[4 * tId + 3][2] * delta_lambda);
4101 if (constraints[tId].type == ConstraintType::CN_JOINT_NO_MOVE_1)
4103 Coord tmp(eta[tId], eta[tId + 1], eta[tId + 2]);
4104 for (int i = 0; i < 3; i++)
4106 tmp[i] -= J[4 * (tId + i)].dot(impulse[idx1 * 2]);
4108 Coord oldLambda(lambda[tId], lambda[tId + 1], lambda[tId + 2]);
4109 Coord delta_lambda = omega * (massCoeff * K_3[tId] * tmp - impulseCoeff * oldLambda);
4110 for (int i = 0; i < 3; i++)
4112 lambda[tId + i] += delta_lambda[i];
4113 atomicAdd(&impulse[idx1 * 2][0], B[4 * (tId + i)][0] * delta_lambda[i]);
4114 atomicAdd(&impulse[idx1 * 2][1], B[4 * (tId + i)][1] * delta_lambda[i]);
4115 atomicAdd(&impulse[idx1 * 2][2], B[4 * (tId + i)][2] * delta_lambda[i]);
4117 atomicAdd(&impulse[idx1 * 2 + 1][0], B[4 * (tId + i) + 1][0] * delta_lambda[i]);
4118 atomicAdd(&impulse[idx1 * 2 + 1][1], B[4 * (tId + i) + 1][1] * delta_lambda[i]);
4119 atomicAdd(&impulse[idx1 * 2 + 1][2], B[4 * (tId + i) + 1][2] * delta_lambda[i]);
4124 template<typename Real, typename Coord, typename Constraint>
4125 __global__ void SF_JacobiIterationStrict(
4126 DArray<Real> lambda,
4127 DArray<Coord> impulse,
4131 DArray<Constraint> constraints,
4140 int tId = threadIdx.x + blockIdx.x * blockDim.x;
4141 if (tId >= constraints.size())
4144 int idx1 = constraints[tId].bodyId1;
4145 int idx2 = constraints[tId].bodyId2;
4147 Real tmp = eta[tId];
4149 tmp -= J[4 * tId].dot(impulse[idx1 * 2]);
4150 tmp -= J[4 * tId + 1].dot(impulse[idx1 * 2 + 1]);
4152 if (idx2 != INVALID)
4154 tmp -= J[4 * tId + 2].dot(impulse[idx2 * 2]);
4155 tmp -= J[4 * tId + 3].dot(impulse[idx2 * 2 + 1]);
4158 int stepInverse = 0;
4159 if (constraints[tId].type == ConstraintType::CN_FRICTION || constraints[tId].type == ConstraintType::CN_NONPENETRATION)
4161 if (idx2 != INVALID)
4163 stepInverse = nbq[idx1] + nbq[idx2];
4167 stepInverse = nbq[idx1];
4175 Real omega = Real(1) / stepInverse;
4177 if (d[tId] > EPSILON)
4179 Real delta_lambda = (tmp / d[tId]) * omega;
4180 if (constraints[tId].type == ConstraintType::CN_NONPENETRATION)
4182 Real lambda_new = maximum(0.0f, lambda[tId] + (tmp / (d[tId] * stepInverse)));
4183 delta_lambda = lambda_new - lambda[tId];
4185 if (constraints[tId].type == ConstraintType::CN_FRICTION)
4187 Real mass_avl = mass[idx1];
4188 Real lambda_new = minimum(maximum(lambda[tId] + (tmp / (d[tId] * stepInverse)), -mu * mass_avl * g * dt), mu * mass_avl * g * dt);
4189 delta_lambda = lambda_new - lambda[tId];
4192 lambda[tId] += delta_lambda;
4194 atomicAdd(&impulse[idx1 * 2][0], B[4 * tId][0] * delta_lambda);
4195 atomicAdd(&impulse[idx1 * 2][1], B[4 * tId][1] * delta_lambda);
4196 atomicAdd(&impulse[idx1 * 2][2], B[4 * tId][2] * delta_lambda);
4198 atomicAdd(&impulse[idx1 * 2 + 1][0], B[4 * tId + 1][0] * delta_lambda);
4199 atomicAdd(&impulse[idx1 * 2 + 1][1], B[4 * tId + 1][1] * delta_lambda);
4200 atomicAdd(&impulse[idx1 * 2 + 1][2], B[4 * tId + 1][2] * delta_lambda);
4202 if (idx2 != INVALID)
4204 atomicAdd(&impulse[idx2 * 2][0], B[4 * tId + 2][0] * delta_lambda);
4205 atomicAdd(&impulse[idx2 * 2][1], B[4 * tId + 2][1] * delta_lambda);
4206 atomicAdd(&impulse[idx2 * 2][2], B[4 * tId + 2][2] * delta_lambda);
4208 atomicAdd(&impulse[idx2 * 2 + 1][0], B[4 * tId + 3][0] * delta_lambda);
4209 atomicAdd(&impulse[idx2 * 2 + 1][1], B[4 * tId + 3][1] * delta_lambda);
4210 atomicAdd(&impulse[idx2 * 2 + 1][2], B[4 * tId + 3][2] * delta_lambda);
4216 void JacobiIteration(
4217 DArray<float> lambda,
4218 DArray<Vec3f> impulse,
4222 DArray<TConstraintPair<float>> constraints,
4228 DArray<float> fricCoeffs,
4234 cuExecute(constraints.size(),
4253 void JacobiIterationForCFM(
4254 DArray<float> lambda,
4255 DArray<Vec3f> impulse,
4259 DArray<TConstraintPair<float>> constraints,
4271 cuExecute(constraints.size(),
4272 SF_JacobiIterationForCFM,
4290 void JacobiIterationStrict(
4291 DArray<float> lambda,
4292 DArray<Vec3f> impulse,
4296 DArray<TConstraintPair<float>> constraints,
4305 cuExecute(constraints.size(),
4306 SF_JacobiIterationStrict,
4322 void JacobiIterationForSoft(
4323 DArray<float> lambda,
4324 DArray<Vec3f> impulse,
4328 DArray<TConstraintPair<float>> constraints,
4341 cuExecute(constraints.size(),
4342 SF_JacobiIterationForSoft,
4361 void JacobiIterationForNJS(
4362 DArray<float> lambda,
4363 DArray<Vec3f> impulse,
4367 DArray<TConstraintPair<float>> constraints,
4374 cuExecute(constraints.size(),
4375 SF_JacobiIterationForNJS,
4390 * @param impulse_ext
4393 * This function set up gravity
4395 template<typename Coord>
4396 __global__ void SF_setUpGravity(
4397 DArray<Coord> impulse_ext,
4402 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
4403 if (tId >= impulse_ext.size() / 2)
4406 impulse_ext[2 * tId] = Coord(0, -g, 0) * dt;
4407 impulse_ext[2 * tId + 1] = Coord(0);
4411 DArray<Vec3f> impulse_ext,
4416 cuExecute(impulse_ext.size() / 2,
4423 template<typename Coord, typename Real>
4424 __global__ void SF_calculateDiagnals(
4430 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
4431 if (tId >= D.size())
4434 Real d = J[4 * tId].dot(B[4 * tId]) + J[4 * tId + 1].dot(B[4 * tId + 1]) + J[4 * tId + 2].dot(B[4 * tId + 2]) + J[4 * tId + 3].dot(B[4 * tId + 3]);
4439 void calculateDiagnals(
4446 SF_calculateDiagnals,
4452 template<typename Coord, typename Real>
4453 __global__ void SF_preConditionJ(
4459 int tId = threadIdx.x + blockIdx.x * blockDim.x;
4460 if (tId >= d.size())
4463 if (d[tId] > EPSILON)
4465 Real d_inv = 1 / d[tId];
4466 J[4 * tId] = d_inv * J[4 * tId];
4467 J[4 * tId + 1] = d_inv * J[4 * tId + 1];
4468 J[4 * tId + 2] = d_inv * J[4 * tId + 2];
4469 J[4 * tId + 3] = d_inv * J[4 * tId + 3];
4471 eta[tId] = d_inv * eta[tId];
4488 template<typename Coord, typename Real, typename Constraint>
4489 __global__ void SF_checkOutError(
4491 DArray<Coord> mImpulse,
4492 DArray<Constraint> constraints,
4497 int tId = threadIdx.x + blockIdx.x * blockDim.x;
4498 if (tId >= constraints.size())
4501 int idx1 = constraints[tId].bodyId1;
4502 int idx2 = constraints[tId].bodyId2;
4505 tmp += J[4 * tId].dot(mImpulse[idx1 * 2]) + J[4 * tId + 1].dot(mImpulse[idx1 * 2 + 1]);
4506 if (idx2 != INVALID)
4507 tmp += J[4 * tId + 2].dot(mImpulse[idx2 * 2]) + J[4 * tId + 3].dot(mImpulse[idx2 * 2 + 1]);
4509 Real e = tmp - eta[tId];
4517 DArray<Vec3f> mImpulse,
4518 DArray<TConstraintPair<float>> constraints,
4522 DArray<float> error;
4523 error.resize(eta.size());
4526 cuExecute(eta.size(),
4534 CArray<float> errorHost;
4535 errorHost.assign(error);
4538 int num = errorHost.size();
4539 for (int i = 0; i < num; i++)
4541 tmp += errorHost[i];
4548 bool saveVectorToFile(
4549 const std::vector<float>& vec,
4550 const std::string& filename
4553 std::ofstream file(filename);
4554 if (!file.is_open()) {
4555 std::cerr << "Failed to open file." << std::endl;
4569 bool saveMatrixToFile(
4570 DArray<float> &Matrix,
4572 const std::string& filename
4575 CArray<float> matrix;
4576 matrix.assign(Matrix);
4577 std::ofstream file(filename);
4578 if (!file.is_open()) {
4579 std::cerr << "Failed to open file." << std::endl;
4583 for (int i = 0; i < n; i++)
4585 for (int j = 0; j < n; j++)
4587 file << matrix[i * n + j] << " ";
4596 bool saveVectorToFile(
4598 const std::string& filename
4603 std::ofstream file(filename);
4604 if (!file.is_open()) {
4605 std::cerr << "Failed to open file." << std::endl;
4608 printf("%d\n", v.size());
4609 for (int i = 0; i < v.size(); i++)
4611 file << v[i] << " ";
4619 double checkOutErrors(
4620 DArray<float> errors
4623 CArray<float> merrors;
4624 merrors.assign(errors);
4626 for (int i = 0; i < merrors.size(); i++)
4628 tmp += merrors[i] * merrors[i];
4634 template<typename Coord, typename Real, typename Constraint>
4635 __global__ void SF_calculateMatrixA(
4639 DArray<Constraint> constraints,
4643 int n = constraints.size();
4644 int tId = threadIdx.x + blockDim.x * blockIdx.x;
4649 if (i >= constraints.size() || j >= constraints.size())
4656 int row_idx1 = constraints[i].bodyId1;
4657 int row_idx2 = constraints[i].bodyId2;
4659 int col_idx1 = constraints[j].bodyId1;
4660 int col_idx2 = constraints[j].bodyId2;
4666 if (row_idx1 == col_idx1)
4667 tmp += J[4 * i].dot(B[4 * j]) + J[4 * i + 1].dot(B[4 * j + 1]);
4669 if (row_idx1 == col_idx2)
4670 tmp += J[4 * i].dot(B[4 * j + 2]) + J[4 * i + 1].dot(B[4 * j + 3]);
4672 if (row_idx2 == col_idx1)
4673 tmp += J[4 * i + 2].dot(B[4 * j]) + J[4 * i + 3].dot(B[4 * j + 1]);
4675 if (row_idx2 == col_idx2)
4676 tmp += J[4 * i + 2].dot(B[4 * j + 2]) + J[4 * i + 3].dot(B[4 * j + 3]);
4678 if (i == j && constraints[tId].isValid == true)
4687 void calculateMatrixA(
4691 DArray<TConstraintPair<float>> &constraints,
4695 int n = constraints.size();
4698 SF_calculateMatrixA,
4706 template<typename Real, typename Constraint>
4707 __global__ void SF_vectorSub(
4709 DArray<Real> subtranhend,
4710 DArray<Real> minuend,
4711 DArray<Constraint> constraints
4714 int tId = threadIdx.x + blockIdx.x * blockDim.x;
4715 if (!constraints[tId].isValid)
4717 if (tId >= ans.size())
4719 ans[tId] = minuend[tId] - subtranhend[tId];
4726 DArray<float> &subtranhend,
4727 DArray<float> &minuend,
4728 DArray<TConstraintPair<float>> &constraints
4731 cuExecute(ans.size(),
4740 template<typename Real, typename Constraint>
4741 __global__ void SF_vectorAdd(
4745 DArray<Constraint> constraints
4748 int tId = threadIdx.x + blockIdx.x * blockDim.x;
4749 if (!constraints[tId].isValid)
4751 if (tId >= ans.size())
4753 ans[tId] = v1[tId] + v2[tId];
4760 DArray<TConstraintPair<float>> &constraints
4763 cuExecute(ans.size(),
4771 template<typename Real, typename Coord, typename Constraint>
4772 __global__ void SF_matrixMultiplyVecBuildImpulse(
4774 DArray<Real> lambda,
4775 DArray<Coord> impulse,
4776 DArray<Constraint> constraints
4779 int tId = threadIdx.x + blockIdx.x * blockDim.x;
4780 if (tId >= lambda.size())
4782 if (!constraints[tId].isValid)
4785 int idx1 = constraints[tId].bodyId1;
4786 int idx2 = constraints[tId].bodyId2;
4788 Real lambda_i = lambda[tId];
4790 atomicAdd(&impulse[2 * idx1][0], B[4 * tId][0] * lambda_i);
4791 atomicAdd(&impulse[2 * idx1][1], B[4 * tId][1] * lambda_i);
4792 atomicAdd(&impulse[2 * idx1][2], B[4 * tId][2] * lambda_i);
4793 atomicAdd(&impulse[2 * idx1 + 1][0], B[4 * tId + 1][0] * lambda_i);
4794 atomicAdd(&impulse[2 * idx1 + 1][1], B[4 * tId + 1][1] * lambda_i);
4795 atomicAdd(&impulse[2 * idx1 + 1][2], B[4 * tId + 1][2] * lambda_i);
4797 if (idx2 != INVALID)
4799 atomicAdd(&impulse[2 * idx2][0], B[4 * tId + 2][0] * lambda_i);
4800 atomicAdd(&impulse[2 * idx2][1], B[4 * tId + 2][1] * lambda_i);
4801 atomicAdd(&impulse[2 * idx2][2], B[4 * tId + 2][2] * lambda_i);
4802 atomicAdd(&impulse[2 * idx2 + 1][0], B[4 * tId + 3][0] * lambda_i);
4803 atomicAdd(&impulse[2 * idx2 + 1][1], B[4 * tId + 3][1] * lambda_i);
4804 atomicAdd(&impulse[2 * idx2 + 1][2], B[4 * tId + 3][2] * lambda_i);
4808 template<typename Real, typename Coord, typename Constraint>
4809 __global__ void SF_matrixMultiplyVecUseImpulse(
4811 DArray<Coord> impulse,
4812 DArray<Constraint> constraints,
4816 int tId = threadIdx.x + blockIdx.x * blockDim.x;
4817 if (tId >= ans.size())
4819 if (!constraints[tId].isValid)
4824 int idx1 = constraints[tId].bodyId1;
4825 int idx2 = constraints[tId].bodyId2;
4827 tmp += J[4 * tId].dot(impulse[idx1 * 2]) + J[4 * tId + 1].dot(impulse[idx1 * 2 + 1]);
4829 if (idx2 != INVALID)
4831 tmp += J[4 * tId + 2].dot(impulse[idx2 * 2]) + J[4 * tId + 3].dot(impulse[idx2 * 2 + 1]);
4839 void matrixMultiplyVec(
4842 DArray<float> &lambda,
4844 DArray<TConstraintPair<float>> &constraints,
4848 DArray<Vec3f> impulse;
4849 impulse.resize(2 * bodyNum);
4852 cuExecute(constraints.size(),
4853 SF_matrixMultiplyVecBuildImpulse,
4859 cuExecute(constraints.size(),
4860 SF_matrixMultiplyVecUseImpulse,
4869 template<typename Real>
4870 __global__ void SF_vectorInnerProduct(
4876 int index = threadIdx.x + blockIdx.x * blockDim.x;
4883 result[index] = v1[index] * v2[index];
4899 SF_vectorInnerProduct,
4904 Reduction<float> reduction;
4905 return reduction.accumulate(c.begin(), c.size());
4908 template<typename Real, typename Constraint>
4909 __global__ void SF_vectorMultiplyScale(
4911 DArray<Real> initialVec,
4912 DArray<Constraint> constraints,
4916 int tId = threadIdx.x + blockIdx.x * blockDim.x;
4917 if (!constraints[tId].isValid)
4919 if (tId >= ans.size())
4921 ans[tId] = initialVec[tId] * scale;
4924 void vectorMultiplyScale(
4926 DArray<float> &initialVec,
4928 DArray<TConstraintPair<float>>& constraints
4931 cuExecute(ans.size(),
4932 SF_vectorMultiplyScale,
4939 template<typename Real, typename Constraint>
4940 __global__ void SF_vectorClampSupport(
4942 DArray<Constraint> constraints
4945 int tId = threadIdx.x + blockDim.x * blockIdx.x;
4946 if (tId >= v.size())
4949 if (constraints[tId].type == ConstraintType::CN_NONPENETRATION)
4956 void vectorClampSupport(
4958 DArray<TConstraintPair<float>> constraints
4962 SF_vectorClampSupport,
4966 template<typename Real, typename Constraint>
4967 __global__ void SF_vectorClampFriction(
4969 DArray<Constraint> constraints,
4974 int tId = threadIdx.x + blockDim.x * blockIdx.x;
4975 if (tId >= v.size())
4977 if (constraints[tId].type == ConstraintType::CN_FRICTION)
4979 Real support = abs(v[tId % contact_size]);
4980 v[tId] = minimum(maximum(v[tId], -mu * support), mu * support);
4985 void vectorClampFriction(
4987 DArray<TConstraintPair<float>> constraints,
4993 SF_vectorClampFriction,
5001 void calculateImpulseByLambda(
5002 DArray<float> lambda,
5003 DArray<TConstraintPair<float>> constraints,
5004 DArray<Vec3f> impulse,
5008 cuExecute(lambda.size(),
5009 SF_matrixMultiplyVecBuildImpulse,
5016 template<typename Real, typename Constraint>
5017 __global__ void SF_vectorMultiplyVector(
5021 DArray<Constraint> constraints
5024 int tId = threadIdx.x + blockIdx.x * blockDim.x;
5025 if (!constraints[tId].isValid)
5028 if (tId >= v1.size())
5031 ans[tId] = v1[tId] * v2[tId];
5034 void vectorMultiplyVector(
5038 DArray<TConstraintPair<float>>& constraints
5041 cuExecute(v1.size(),
5042 SF_vectorMultiplyVector,
5049 template<typename Real, typename Matrix2x2, typename Matrix3x3, typename Constraint>
5050 __global__ void SF_preconditionedResidual(
5051 DArray<Real> residual,
5054 DArray<Matrix2x2> k_2,
5055 DArray<Matrix3x3> k_3,
5056 DArray<Constraint> constraints
5059 int tId = threadIdx.x + blockIdx.x * blockDim.x;
5060 if (tId >= residual.size())
5063 if (!constraints[tId].isValid)
5068 if (constraints[tId].type == ConstraintType::CN_ANCHOR_EQUAL_1 || constraints[tId].type == ConstraintType::CN_BAN_ROT_1 || constraints[tId].type == ConstraintType::CN_JOINT_NO_MOVE_1)
5070 Vec3f tmp(residual[tId], residual[tId + 1], residual[tId + 2]);
5071 Vec3f delta = k_3[tId] * tmp;
5072 for (int i = 0; i < 3; i++)
5074 ans[tId + i] = delta[i];
5078 if (constraints[tId].type == ConstraintType::CN_ALLOW_ROT1D_1 || constraints[tId].type == ConstraintType::CN_ANCHOR_TRANS_1)
5080 Vec2f tmp(residual[tId], residual[tId + 1]);
5081 Vec2f delta = k_2[tId] * tmp;
5082 for (int i = 0; i < 2; i++)
5084 ans[tId + i] = delta[i];
5088 if (constraints[tId].type == ConstraintType::CN_NONPENETRATION || constraints[tId].type == ConstraintType::CN_FRICTION)
5090 ans[tId] = residual[tId] * k_1[tId];
5093 if (constraints[tId].type == ConstraintType::CN_JOINT_HINGE_MIN || constraints[tId].type == ConstraintType::CN_JOINT_HINGE_MAX || constraints[tId].type == ConstraintType::CN_JOINT_HINGE_MOTER || constraints[tId].type == ConstraintType::CN_JOINT_SLIDER_MIN || constraints[tId].type == ConstraintType::CN_JOINT_SLIDER_MAX || constraints[tId].type == ConstraintType::CN_JOINT_SLIDER_MOTER)
5095 if (constraints[tId].isValid)
5097 ans[tId] = residual[tId] * k_1[tId];
5102 void preconditionedResidual(
5103 DArray<float> &residual,
5108 DArray<TConstraintPair<float>> &constraints
5111 cuExecute(residual.size(),
5112 SF_preconditionedResidual,
5121 template<typename Coord, typename Constraint, typename Real>
5122 __global__ void SF_buildCFMAndERP(
5125 DArray<Constraint> constraints,
5133 int tId = threadIdx.x + blockIdx.x * blockDim.x;
5135 if (tId >= constraints.size())
5138 if (!constraints[tId].isValid)
5143 int idx2 = constraints[tId].bodyId2;
5144 if (idx2 != INVALID)
5146 d += J[4 * tId].dot(B[4 * tId]) + J[4 * tId + 1].dot(B[4 * tId + 1]) + J[4 * tId + 2].dot(B[4 * tId + 2]) + J[4 * tId + 3].dot(B[4 * tId + 3]);
5150 d += J[4 * tId].dot(B[4 * tId]) + J[4 * tId + 1].dot(B[4 * tId + 1]);
5154 Real omega = 2 * M_PI * hertz;
5155 Real k = m_eff * omega * omega;
5156 Real c = 2 * m_eff * zeta * omega;
5158 CFM[tId] = 1 / (c * dt + dt * dt * k);
5159 ERP[tId] = dt * k / (c + dt * k);
5161 //printf("%d : CFM(%lf), ERP(%lf)\n", tId, CFM[tId], ERP[tId]);
5167 void buildCFMAndERP(
5170 DArray<TConstraintPair<float>> constraints,
5178 cuExecute(constraints.size(),
5190 template<typename Real, typename Coord, typename Constraint>
5191 __global__ void SF_calculateLinearSystemLHSImpulse(
5193 DArray<Coord> impulse,
5194 DArray<Real> lambda,
5195 DArray<Constraint> constraints
5198 int tId = threadIdx.x + blockIdx.x * blockDim.x;
5200 if (tId >= constraints.size())
5203 if (!constraints[tId].isValid)
5207 int idx1 = constraints[tId].bodyId1;
5208 int idx2 = constraints[tId].bodyId2;
5210 Real lambda_i = lambda[tId];
5212 atomicAdd(&impulse[2 * idx1][0], B[4 * tId][0] * lambda_i);
5213 atomicAdd(&impulse[2 * idx1][1], B[4 * tId][1] * lambda_i);
5214 atomicAdd(&impulse[2 * idx1][2], B[4 * tId][2] * lambda_i);
5215 atomicAdd(&impulse[2 * idx1 + 1][0], B[4 * tId + 1][0] * lambda_i);
5216 atomicAdd(&impulse[2 * idx1 + 1][1], B[4 * tId + 1][1] * lambda_i);
5217 atomicAdd(&impulse[2 * idx1 + 1][2], B[4 * tId + 1][2] * lambda_i);
5219 if (idx2 != INVALID)
5221 atomicAdd(&impulse[2 * idx2][0], B[4 * tId + 2][0] * lambda_i);
5222 atomicAdd(&impulse[2 * idx2][1], B[4 * tId + 2][1] * lambda_i);
5223 atomicAdd(&impulse[2 * idx2][2], B[4 * tId + 2][2] * lambda_i);
5224 atomicAdd(&impulse[2 * idx2 + 1][0], B[4 * tId + 3][0] * lambda_i);
5225 atomicAdd(&impulse[2 * idx2 + 1][1], B[4 * tId + 3][1] * lambda_i);
5226 atomicAdd(&impulse[2 * idx2 + 1][2], B[4 * tId + 3][2] * lambda_i);
5230 template<typename Real, typename Coord, typename Constraint>
5231 __global__ void SF_calculateLinearSystemLHSResult(
5232 DArray<Coord> impulse,
5236 DArray<Real> lambda,
5237 DArray<Constraint> constraints
5240 int tId = threadIdx.x + blockIdx.x * blockDim.x;
5242 if (tId >= constraints.size())
5245 if (!constraints[tId].isValid)
5248 int idx1 = constraints[tId].bodyId1;
5249 int idx2 = constraints[tId].bodyId2;
5253 tmp += J[4 * tId].dot(impulse[2 * idx1]) + J[4 * tId + 1].dot(impulse[2 * idx1 + 1]);
5255 if (idx2 != INVALID)
5256 tmp += J[4 * tId + 2].dot(impulse[2 * idx2]) + J[4 * tId + 3].dot(impulse[2 * idx2 + 1]);
5259 tmp += CFM[tId] * lambda[tId];
5267 void calculateLinearSystemLHS(
5270 DArray<Vec3f>& impulse,
5271 DArray<float>& lambda,
5274 DArray<TConstraintPair<float>>& constraints
5277 int n = constraints.size();
5280 SF_calculateLinearSystemLHSImpulse,
5287 SF_calculateLinearSystemLHSResult,