cyclone-physics 1.1.2 → 1.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "cyclone-physics",
3
3
  "description": "Pure Javascript physics engine based on http://procyclone.com/",
4
- "version": "1.1.2",
4
+ "version": "1.1.4",
5
5
  "main": "",
6
6
  "author": "James Baicoianu",
7
7
  "license": "MIT",
@@ -9,6 +9,8 @@ elation.require(['physics.common', 'utils.math'], function() {
9
9
  // closure scratch variables
10
10
  var thispos = new THREE.Vector3(),
11
11
  otherpos = new THREE.Vector3(),
12
+ thisvel = new THREE.Vector3(),
13
+ othervel = new THREE.Vector3(),
12
14
  midline = new THREE.Vector3(),
13
15
  scaledVelocity = new THREE.Vector3(),
14
16
  intersectionPoint = new THREE.Vector3();
@@ -20,9 +22,6 @@ elation.require(['physics.common', 'utils.math'], function() {
20
22
  obj1.body.localToWorldPos(thispos.set(0,0,0));
21
23
  obj2.body.localToWorldPos(otherpos.set(0,0,0));
22
24
 
23
- let scaledRadius1 = obj1.radius * Math.max(obj1.body.scaleWorld.x, obj1.body.scaleWorld.y, obj1.body.scaleWorld.z),
24
- scaledRadius2 = obj2.radius * Math.max(obj2.body.scaleWorld.x, obj2.body.scaleWorld.y, obj2.body.scaleWorld.z);
25
-
26
25
  let dynamic = true; // TODO - this should either be a flag on rigid bodies, or a configurable threshold based on velocity
27
26
  if (!dynamic) {
28
27
  midline.subVectors(otherpos, thispos),
@@ -45,9 +44,17 @@ elation.require(['physics.common', 'utils.math'], function() {
45
44
  //console.log('crash a sphere-sphere', contact);
46
45
  }
47
46
  } else {
48
- let r = scaledRadius1 + scaledRadius2;
47
+ let r = obj1.radius + obj2.radius;
49
48
  // FIXME - probably need to transform velocity into world coordinates as well
50
- let v = scaledVelocity.copy(obj1.body.velocity).sub(obj2.body.velocity).multiplyScalar(dt);
49
+ obj1.body.localToWorldDir(thisvel.copy(obj1.body.velocity));
50
+ obj2.body.localToWorldDir(othervel.copy(obj2.body.velocity));
51
+
52
+
53
+ let v = scaledVelocity.copy(thisvel).sub(othervel).multiplyScalar(dt);
54
+
55
+ midline.copy(thispos).sub(otherpos).normalize();
56
+
57
+ //if (midline.dot(scaledVelocity) > 0) return; // moving away, can't collide
51
58
 
52
59
  let endpos = midline.copy(thispos).add(v);
53
60
 
@@ -61,7 +68,7 @@ elation.require(['physics.common', 'utils.math'], function() {
61
68
 
62
69
  var contact = new elation.physics.contact_dynamic({
63
70
  normal: normal,
64
- point: normal.clone().multiplyScalar(scaledRadius1).add(thispos), // allocate point
71
+ point: normal.clone().multiplyScalar(obj1.radius).add(thispos), // allocate point
65
72
  penetrationTime: intersection.t,
66
73
  bodies: [obj1.body, obj2.body],
67
74
  });
@@ -315,7 +322,7 @@ elation.require(['physics.common', 'utils.math'], function() {
315
322
  }
316
323
  })();
317
324
 
318
- this.box_box = function() {
325
+ this.box_box_old = function() {
319
326
  // closure scratch variables
320
327
  var diff = new THREE.Vector3(),
321
328
  thispos = new THREE.Vector3(),
@@ -477,6 +484,234 @@ elation.require(['physics.common', 'utils.math'], function() {
477
484
  }
478
485
  }();
479
486
 
487
+ this.box_box = (function() {
488
+ // closure scratch variables
489
+ const scratch = {
490
+ axes: Array(15).fill(null).map(() => new THREE.Vector3()),
491
+ box1Corners: Array(8).fill(null).map(() => new THREE.Vector3()),
492
+ box2Corners: Array(8).fill(null).map(() => new THREE.Vector3()),
493
+ box1Projection: { min: 0, max: 0 },
494
+ box2Projection: { min: 0, max: 0 },
495
+ tmpVec: new THREE.Vector3(),
496
+ tmpQuat: new THREE.Quaternion(),
497
+ contactAxis: new THREE.Vector3(),
498
+ };
499
+
500
+ function getAxesToTest(box1, box2, scratchAxes) {
501
+ const axes = scratchAxes;
502
+
503
+ // Get the three local axes of both boxes in world coordinates
504
+ const box1Axes = getWorldAxes(box1, axes.slice(0, 3));
505
+ const box2Axes = getWorldAxes(box2, axes.slice(3, 6));
506
+
507
+ // Add cross products of edges (9 cross-product axes)
508
+ let axesIndex = 6;
509
+ for (let i = 0; i < 3; i++) {
510
+ for (let j = 0; j < 3; j++) {
511
+ const cross = axes[axesIndex].crossVectors(box1Axes[i], box2Axes[j]);
512
+ if (cross.lengthSq() > 1e-6) { // Avoid zero vectors
513
+ cross.normalize();
514
+ }
515
+ axesIndex++;
516
+ }
517
+ }
518
+
519
+ return axes;
520
+ }
521
+
522
+ function getWorldAxes(box, axes) {
523
+ // The orientationWorld is already in world space
524
+ axes[0].set(1, 0, 0).applyQuaternion(box.body.orientationWorld);
525
+ axes[1].set(0, 1, 0).applyQuaternion(box.body.orientationWorld);
526
+ axes[2].set(0, 0, 1).applyQuaternion(box.body.orientationWorld);
527
+ return axes;
528
+ }
529
+ function getPenetrationOnAxis(box1, box2, axis) {
530
+ // Project both boxes onto the axis
531
+ const box1Projection = projectBoxOntoAxis(box1, axis, scratch.box1Corners, scratch.box1Projection);
532
+ const box2Projection = projectBoxOntoAxis(box2, axis, scratch.box2Corners, scratch.box2Projection);
533
+
534
+ // Check if projections overlap
535
+ const overlap = Math.min(box1Projection.max - box2Projection.min, box2Projection.max - box1Projection.min);
536
+ if (box1Projection.max < box2Projection.min || box2Projection.max < box1Projection.min) {
537
+ return false; // Separating axis found
538
+ }
539
+
540
+ return overlap; // Return penetration depth on this axis
541
+ }
542
+ function projectBoxOntoAxis(box, axis, corners, projection) {
543
+ getBoxCorners(box, corners);
544
+
545
+ projection.min = Infinity;
546
+ projection.max = -Infinity;
547
+
548
+ for (let corner of corners) {
549
+ const proj = corner.dot(axis);
550
+ projection.min = Math.min(projection.min, proj);
551
+ projection.max = Math.max(projection.max, proj);
552
+ }
553
+
554
+ return projection;
555
+ }
556
+ function getBoxCorners(box, corners) {
557
+ const halfSize = box.halfsize;
558
+ const offset = box.offset;
559
+
560
+ const scale = box.body.localToWorldScale(scratch.tmpVec.set(1,1,1));
561
+
562
+ // Define the eight corners of the box in local space
563
+ corners[0].set(halfSize.x, halfSize.y, halfSize.z).add(offset).divide(scale);
564
+ corners[1].set(halfSize.x, halfSize.y, -halfSize.z).add(offset).divide(scale);
565
+ corners[2].set(halfSize.x, -halfSize.y, halfSize.z).add(offset).divide(scale);
566
+ corners[3].set(halfSize.x, -halfSize.y, -halfSize.z).add(offset).divide(scale);
567
+ corners[4].set(-halfSize.x, halfSize.y, halfSize.z).add(offset).divide(scale);
568
+ corners[5].set(-halfSize.x, halfSize.y, -halfSize.z).add(offset).divide(scale);
569
+ corners[6].set(-halfSize.x, -halfSize.y, halfSize.z).add(offset).divide(scale);
570
+ corners[7].set(-halfSize.x, -halfSize.y, -halfSize.z).add(offset).divide(scale);
571
+
572
+ // Convert local corners to world space using localToWorld
573
+ for (let i = 0; i < 8; i++) {
574
+ box.body.localToWorldPos(corners[i]);
575
+ }
576
+
577
+ return corners;
578
+ }
579
+ function generateContacts(box1, box2, minPenetration, contactAxis, contacts) {
580
+ // The contact normal is the axis of minimum penetration
581
+ const contactNormal = contactAxis.clone().normalize();
582
+
583
+ // Find the closest points on the surface of both boxes
584
+ const box1Corners = getBoxCorners(box1, scratch.box1Corners);
585
+ const box2Corners = getBoxCorners(box2, scratch.box2Corners);
586
+
587
+ //const box1Closest = findClosestPointOnBox(box1Corners, contactNormal);
588
+ //const box2Closest = findClosestPointOnBox(box2Corners, contactNormal.clone().negate());
589
+ const box1Closest = findClosestPointOnFace(box1Corners, box2, contactNormal);
590
+ const box2Closest = findClosestPointOnFace(box2Corners, box1, contactNormal);
591
+
592
+ // Contact point is the midpoint between closest points on both boxes
593
+ const contactPoint = box1Closest.clone().add(box2Closest).multiplyScalar(0.5);
594
+
595
+ // Create the contact
596
+ const contact = new elation.physics.contact({
597
+ normal: contactNormal,
598
+ point: contactPoint.clone(),
599
+ penetration: 0, //-minPenetration, // negative value as it's penetration
600
+ //penetration: box1Closest.distanceTo(box2Closest),
601
+ bodies: [box1.body, box2.body]
602
+ });
603
+
604
+ contacts.push(contact);
605
+ return contacts;
606
+ }
607
+ function findClosestPointOnBox(corners, normal) {
608
+ let closestPoint = corners[0];
609
+ let minDistance = closestPoint.dot(normal);
610
+
611
+ for (let i = 1; i < corners.length; i++) {
612
+ const dist = corners[i].dot(normal);
613
+ if (dist < minDistance) {
614
+ closestPoint = corners[i];
615
+ minDistance = dist;
616
+ }
617
+ }
618
+ return closestPoint;
619
+ }
620
+ function findClosestPointOnFace(corners, otherBox, normal) {
621
+ let closestPoint = null;
622
+ let minDistance = Infinity;
623
+
624
+ // Check the projection of each corner onto the face of the other box
625
+ for (let i = 0; i < corners.length; i++) {
626
+ const corner = corners[i];
627
+ const projectedPoint = projectPointOntoFace(corner, otherBox, normal);
628
+
629
+ const distance = corner.distanceTo(projectedPoint);
630
+ if (distance < minDistance) {
631
+ closestPoint = projectedPoint;
632
+ minDistance = distance;
633
+ }
634
+ }
635
+
636
+ return closestPoint;
637
+ }
638
+
639
+ function projectPointOntoFace(point, box, normal) {
640
+ // First, find the center of the box in world space
641
+ const boxCenter = new THREE.Vector3();
642
+ box.body.localToWorldPos(boxCenter.set(0, 0, 0));
643
+
644
+ // Determine the plane of the face by using the box's normal and a point on the plane
645
+ // (the center of the face, which is aligned with one of the box's axes)
646
+ const halfSize = box.halfsize;
647
+ const offset = new THREE.Vector3().addVectors(box.min, box.max).multiplyScalar(.5);
648
+ const planePoint = new THREE.Vector3();
649
+ const planeNormal = normal.clone().normalize(); // Normal of the face (aligned with one of the box's axes)
650
+
651
+ // We need to determine which face we're projecting onto, so find the direction along the normal
652
+ // Set the point on the plane (face center) by adding/subtracting half the box size along the normal
653
+ for (let i = 0; i < 3; i++) {
654
+ const axisValue = planeNormal.getComponent(i);
655
+ if (axisValue !== 0) {
656
+ planePoint.setComponent(i, boxCenter.getComponent(i) + (axisValue * halfSize.getComponent(i)));
657
+ }
658
+ }
659
+
660
+ // Now, we project the point onto the plane
661
+ // To do that, find the vector from the point to the plane point
662
+ const pointToPlane = point.clone().sub(planePoint);
663
+
664
+ // Project this vector onto the normal to find how far away the point is from the plane
665
+ const distance = pointToPlane.dot(planeNormal);
666
+
667
+ // Move the point onto the plane by subtracting the distance along the normal
668
+ const projectedPoint = point.clone().sub(planeNormal.multiplyScalar(distance));
669
+
670
+ // Now we need to clamp the projected point to the bounds of the box face
671
+ // For each axis, clamp the value within the bounds of the face
672
+ for (let i = 0; i < 3; i++) {
673
+ const axisValue = planeNormal.getComponent(i);
674
+ if (axisValue === 0) {
675
+ // Clamp the coordinate to be within the face bounds (which are defined by the box size)
676
+ const minVal = boxCenter.getComponent(i) - halfSize.getComponent(i);
677
+ const maxVal = boxCenter.getComponent(i) + halfSize.getComponent(i);
678
+ const value = projectedPoint.getComponent(i);
679
+ projectedPoint.setComponent(i, Math.max(minVal, Math.min(value, maxVal)));
680
+ }
681
+ }
682
+
683
+ return projectedPoint.add(offset);
684
+
685
+ }
686
+
687
+
688
+
689
+ return function(box1, box2, contacts, dt) {
690
+ const axes = getAxesToTest(box1, box2, scratch.axes);
691
+ let hasCollision = true;
692
+ let minPenetration = Infinity;
693
+
694
+ // Check for overlap along each axis
695
+ for (let axis of axes) {
696
+ const overlap = getPenetrationOnAxis(box1, box2, axis);
697
+ if (overlap === false) {
698
+ hasCollision = false; // Separating axis found, no collision
699
+ break;
700
+ } else if (overlap < minPenetration) {
701
+ minPenetration = overlap; // Track the minimum penetration
702
+ scratch.contactAxis.copy(axis); // Store the axis with minimum penetration
703
+ }
704
+ }
705
+
706
+ if (!hasCollision) {
707
+ return false;
708
+ }
709
+
710
+ // If colliding, generate contact points and return them
711
+ return generateContacts(box1, box2, minPenetration, scratch.contactAxis, contacts);
712
+ }
713
+ })();
714
+
480
715
  /* cylinder helpers */
481
716
  this.cylinder_sphere = function() {
482
717
  // closure scratch variables
@@ -637,20 +872,23 @@ elation.require(['physics.common', 'utils.math'], function() {
637
872
  closest = new THREE.Vector3();
638
873
 
639
874
  return function(capsule, sphere, contacts, dt) {
640
- const radius = capsule.radius + sphere.radius;
641
- const capsuleDims = capsule.getDimensions();
875
+ const capsuleScaledRadius = capsule.radius * Math.max(capsule.body.scale.x, capsule.body.scale.z),
876
+ combinedRadius = capsuleScaledRadius + sphere.radius,
877
+ capsuleDims = capsule.getDimensions();
642
878
  sphere.body.localToWorldPos(point.set(0,0,0));
643
879
 
880
+
644
881
  elation.physics.colliders.helperfuncs.closest_point_on_line(capsuleDims.start, capsuleDims.end, point, closest);
882
+
645
883
  normal.subVectors(closest, point);
646
884
  const distance = normal.length();
647
- //console.log(distance, radius, capsule.radius, sphere.radius);
648
- if (distance <= radius) {
885
+
886
+ if (distance <= combinedRadius) {
649
887
  normal.divideScalar(distance);
650
888
  let contact = new elation.physics.contact({
651
889
  normal: normal.clone(), // allocate normal
652
- point: closest.clone().add(normal.multiplyScalar(capsule.radius)), // allocate point
653
- penetration: radius - distance,
890
+ point: closest.clone().add(normal.multiplyScalar(capsuleScaledRadius)), // allocate point
891
+ penetration: combinedRadius - distance,
654
892
  bodies: [capsule.body, sphere.body]
655
893
  });
656
894
  contacts.push(contact);
@@ -669,20 +907,23 @@ elation.require(['physics.common', 'utils.math'], function() {
669
907
 
670
908
  let distSquared = elation.physics.colliders.helperfuncs.distancesquared_between_lines(capsule1Dims.start, capsule1Dims.end, capsule2Dims.start, capsule2Dims.end, p1, p2);
671
909
 
672
- if (distSquared <= Math.pow(capsule1.radius + capsule2.radius, 2)) {
910
+ const capsule1ScaledRadius = capsule1.radius * Math.max(capsule1.body.scale.x, capsule1.body.scale.z),
911
+ capsule2ScaledRadius = capsule2.radius * Math.max(capsule2.body.scale.x, capsule2.body.scale.z);
912
+
913
+ if (distSquared <= Math.pow(capsule1ScaledRadius + capsule2ScaledRadius, 2)) {
673
914
  console.log('CAPSULE COLLIDE', capsule1, capsule2);
674
915
  let normal = new THREE.Vector3().subVectors(p2, p1),
675
916
  point = p1.clone();
676
917
  dist = Math.sqrt(distSquared);
677
918
  normal.divideScalar(dist);
678
- point.x += normal.x * capsule1.radius;
679
- point.y += normal.y * capsule1.radius;
680
- point.z += normal.z * capsule1.radius;
919
+ point.x += normal.x * capsule1ScaledRadius;
920
+ point.y += normal.y * capsule1ScaledRadius;
921
+ point.z += normal.z * capsule1ScaledRadius;
681
922
 
682
923
  let contact = new elation.physics.contact({
683
924
  normal: normal,
684
925
  point: point,
685
- penetration: dist - (capsule1.radius + capsule2.radius),
926
+ penetration: dist - (capsule1ScaledRadius + capsule2ScaledRadius),
686
927
  bodies: [capsule1.body, capsule2.body]
687
928
  });
688
929
  contacts.push(contact);
@@ -796,13 +1037,12 @@ elation.require(['physics.common', 'utils.math'], function() {
796
1037
  p3 = worldpoints.p3,
797
1038
  normal = worldpoints.normal;
798
1039
 
799
- //if (spherevel.dot(normal) > 0) return; // moving away, can't collide
800
-
1040
+ let velNormal = spherevel.dot(normal);
801
1041
 
802
1042
  // Check if we're already in contact
803
1043
  elation.physics.colliders.helperfuncs.closest_point_on_triangle(spherepos, p1, p2, p3, triangleClosestPoint);
804
1044
  let triangleDistSquared = triangleClosestPoint.distanceToSquared(spherepos)
805
- if (triangleDistSquared < sphere.radius * sphere.radius) {
1045
+ if (triangleDistSquared < sphere.radius * sphere.radius && velNormal <= 0) {
806
1046
  let contact = new elation.physics.contact({
807
1047
  normal: normal.clone(), // allocate normal
808
1048
  point: triangleClosestPoint.clone(), // allocate point
@@ -875,7 +1115,7 @@ elation.require(['physics.common', 'utils.math'], function() {
875
1115
  intersectionPoint.y - triangleClosestPoint.y,
876
1116
  intersectionPoint.z - triangleClosestPoint.z
877
1117
  );
878
- normal.normalize();
1118
+ collisionNormal.normalize();
879
1119
 
880
1120
  intersectionPoint.x += collisionNormal.x * -sphere.radius;
881
1121
  intersectionPoint.y += collisionNormal.y * -sphere.radius;
@@ -1687,6 +1927,8 @@ elation.require(['physics.common', 'utils.math'], function() {
1687
1927
  let triangles = [];
1688
1928
  let radiusSq = 0;
1689
1929
 
1930
+ this.body.updateState(); // ensure scaleWorld is up to date before processing triangles
1931
+ let doubleSided = false;
1690
1932
  if (!this.modeldata && this.mesh && this.mesh.geometry) {
1691
1933
  if (this.mesh.geometry instanceof THREE.BufferGeometry) {
1692
1934
  this.modeldata = {
@@ -1702,6 +1944,7 @@ elation.require(['physics.common', 'utils.math'], function() {
1702
1944
  }
1703
1945
  }
1704
1946
  }
1947
+ doubleSided = this.mesh.material.side == THREE.DoubleSide;
1705
1948
  }
1706
1949
  if (this.modeldata) {
1707
1950
  if (this.modeldata.index) {
@@ -1727,6 +1970,11 @@ elation.require(['physics.common', 'utils.math'], function() {
1727
1970
  if (!triangle.isDegenerate()) {
1728
1971
  triangles.push(triangle);
1729
1972
 
1973
+ if (doubleSided) {
1974
+ let triangle2 = new elation.physics.colliders.triangle(this.body, [p3, p2, p1]);
1975
+ triangles.push(triangle2);
1976
+ }
1977
+
1730
1978
  let l1 = p1.lengthSq(),
1731
1979
  l2 = p2.lengthSq(),
1732
1980
  l3 = p3.lengthSq();
@@ -1761,7 +2009,7 @@ elation.require(['physics.common', 'utils.math'], function() {
1761
2009
  }
1762
2010
  }
1763
2011
  }
1764
- this.radius = Math.sqrt(radiusSq);
2012
+ this.radius = Math.sqrt(radiusSq) * Math.max(this.body.scaleWorld.x, this.body.scaleWorld.y, this.body.scaleWorld.z);
1765
2013
  this.boundingSphere.radius = this.radius;
1766
2014
  return triangles;
1767
2015
  }
@@ -1797,11 +2045,11 @@ elation.require(['physics.common', 'utils.math'], function() {
1797
2045
  bodies[obj.uuid].scale.copy(obj.scale);
1798
2046
  bodies[obj.uuid].orientation.copy(obj.quaternion);
1799
2047
  bodies[obj.uuid].object = this.body.object;
2048
+ parent.add(bodies[obj.uuid]);
1800
2049
  if (obj instanceof THREE.Mesh) {
1801
2050
  bodies[obj.uuid].setCollider('mesh', {mesh: obj, isroot: false });
1802
2051
  //elation.events.add(bodies[obj.uuid], 'physics_collide', (ev) => elation.events.fire({type: 'physics_collide', element: this.body, event: ev}));
1803
2052
  }
1804
- parent.add(bodies[obj.uuid]);
1805
2053
  }
1806
2054
  parent = bodies[obj.uuid];
1807
2055
  }
@@ -2143,21 +2391,20 @@ elation.require(['physics.common', 'utils.math'], function() {
2143
2391
  var lastaccel = new THREE.Vector3();
2144
2392
 
2145
2393
  if (this.bodies[0] && !this.bodies[0].state.sleeping) {
2146
- velocityFromAccel -= .5 * lastaccel.copy(this.bodies[0].lastacceleration).multiplyScalar(duration).dot(this.normal);
2394
+ velocityFromAccel -= lastaccel.copy(this.bodies[0].lastacceleration).multiplyScalar(duration).dot(this.normal);
2147
2395
  }
2148
2396
  if (this.bodies[1] && !this.bodies[1].state.sleeping) {
2149
- velocityFromAccel += .5 * lastaccel.copy(this.bodies[1].lastacceleration).multiplyScalar(duration).dot(this.normal);
2397
+ velocityFromAccel += lastaccel.copy(this.bodies[1].lastacceleration).multiplyScalar(duration).dot(this.normal);
2150
2398
  }
2151
2399
 
2152
2400
  var restitution = this.restitution;
2153
- /*
2154
- if (Math.abs(this.velocity.y) < 0.25) { // FIXME - velocity threshold should be configurable
2401
+
2402
+ if (Math.abs(this.velocity.y) < 0.01) { // FIXME - velocity threshold should be configurable
2155
2403
  restitution = 0;
2156
2404
  }
2157
- */
2405
+
2158
2406
  this.desiredDeltaVelocity = -this.velocity.y - restitution * (this.velocity.y - velocityFromAccel);
2159
2407
  //if (this.desiredDeltaVelocity > 0) this.desiredDeltaVelocity *= -1;
2160
- //console.log('desiredDeltaV: ' + this.desiredDeltaVelocity);
2161
2408
  }
2162
2409
  this.calculateInternals = function(duration) {
2163
2410
  this.calculateContactMatrix();
package/scripts/common.js CHANGED
@@ -15,6 +15,9 @@ elation.require(['engine.external.three.three'], function() {
15
15
  toJSON() {
16
16
  return {x: this._x, y: this._y, z: this._z};
17
17
  }
18
+ clone() {
19
+ return super.clone();
20
+ }
18
21
  }
19
22
  // FIXME - orientation doesn't currently work properly because THREE.Quaternion already uses getters and setters internally
20
23
  class CycloneQuaternion extends THREE.Quaternion {
@@ -34,6 +37,9 @@ elation.require(['engine.external.three.three'], function() {
34
37
  this.changed = true;
35
38
  return super.copy(quat);
36
39
  }
40
+ clone() {
41
+ return super.clone();
42
+ }
37
43
  set(x, y, z, w) {
38
44
  this.changed = true;
39
45
  return super.set(x, y, z, w);
@@ -7,7 +7,7 @@ elation.require(["physics.common", "physics.processors", "physics.processors.wor
7
7
  this.position = this.positionWorld = new THREE.Vector3();
8
8
  this.orientation = this.orientationWorld = new THREE.Quaternion();
9
9
  this.scale = this.scaleWorld = new THREE.Vector3(1, 1, 1);
10
- this.substep = elation.utils.any(this.args.substep, true);
10
+ this.substep = false; //elation.utils.any(this.args.substep, true);
11
11
  this.substepMaxDelta = elation.utils.any(this.args.substepMaxDelta, 20/1000);
12
12
  this.substepMaxSteps = elation.utils.any(this.args.substepMaxSteps, 4);
13
13
  this.processortype = elation.utils.any(this.args.processortype, 'cpu');
@@ -39,7 +39,7 @@ elation.require(["physics.common", "physics.processors", "physics.processors.wor
39
39
  steps = Math.min(Math.round(t / this.substepMaxDelta), this.substepMaxSteps);
40
40
  }
41
41
 
42
- var step = 0;
42
+ var step = 1;
43
43
  while (t > 0) {
44
44
  var steptime = (step < steps ? Math.min(t, this.substepMaxDelta) : t);
45
45
 
package/scripts/forces.js CHANGED
@@ -415,6 +415,8 @@ elation.require(['physics.common'], function() {
415
415
  var _tmpvec2 = new THREE.Vector3();
416
416
 
417
417
  this.apply = function() {
418
+ if (this.disabled) return;
419
+
418
420
  var lws = this.body.localToWorldPos(_tmpvec1.copy(this.connectionpoint));
419
421
  var ows = (this.other ? this.other.localToWorldPos(_tmpvec2.copy(this.otherconnectionpoint)) : this.anchor);
420
422
 
@@ -53,6 +53,7 @@ elation.require(["physics.common"], function() {
53
53
  var obj1 = potentialpair[0], obj2 = potentialpair[1];
54
54
  // Get list of all contact points between the two objects
55
55
  var contacts = obj1.getContacts(obj2, [], t);
56
+ /*
56
57
  if (contacts && contacts.length > 0) {
57
58
  // Resolve the deepest contact first
58
59
  var deepest = this.getDeepestContact(contacts);
@@ -60,6 +61,14 @@ elation.require(["physics.common"], function() {
60
61
  obj1.state.colliding = true;
61
62
  obj2.state.colliding = true;
62
63
  }
64
+ */
65
+ if (contacts && contacts.length > 0) {
66
+ for (let i = 0; i < contacts.length; i++) {
67
+ collisions.push(contacts[i]);
68
+ obj1.state.colliding = true;
69
+ obj2.state.colliding = true;
70
+ }
71
+ }
63
72
  }
64
73
  //console.log(potentials.length + ' potential crashes:', potentials, collisions);
65
74
  }
@@ -103,7 +112,7 @@ elation.require(["physics.common"], function() {
103
112
  let contact = contacts.shift();
104
113
  contact.resolve(t, linearChange, angularChange, contacts);
105
114
  // console.log('blah', contacts.length, linearChange[1].toArray().map(x => +x.toFixed(4)), contact.bodies)
106
- break;
115
+ //break;
107
116
  }
108
117
  }
109
118
  });