cyclone-physics 1.1.2 → 1.1.3

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.3",
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
  });
@@ -637,20 +644,23 @@ elation.require(['physics.common', 'utils.math'], function() {
637
644
  closest = new THREE.Vector3();
638
645
 
639
646
  return function(capsule, sphere, contacts, dt) {
640
- const radius = capsule.radius + sphere.radius;
641
- const capsuleDims = capsule.getDimensions();
647
+ const capsuleScaledRadius = capsule.radius * Math.max(capsule.body.scale.x, capsule.body.scale.z),
648
+ combinedRadius = capsuleScaledRadius + sphere.radius,
649
+ capsuleDims = capsule.getDimensions();
642
650
  sphere.body.localToWorldPos(point.set(0,0,0));
643
651
 
652
+
644
653
  elation.physics.colliders.helperfuncs.closest_point_on_line(capsuleDims.start, capsuleDims.end, point, closest);
654
+
645
655
  normal.subVectors(closest, point);
646
656
  const distance = normal.length();
647
- //console.log(distance, radius, capsule.radius, sphere.radius);
648
- if (distance <= radius) {
657
+
658
+ if (distance <= combinedRadius) {
649
659
  normal.divideScalar(distance);
650
660
  let contact = new elation.physics.contact({
651
661
  normal: normal.clone(), // allocate normal
652
- point: closest.clone().add(normal.multiplyScalar(capsule.radius)), // allocate point
653
- penetration: radius - distance,
662
+ point: closest.clone().add(normal.multiplyScalar(capsuleScaledRadius)), // allocate point
663
+ penetration: combinedRadius - distance,
654
664
  bodies: [capsule.body, sphere.body]
655
665
  });
656
666
  contacts.push(contact);
@@ -669,20 +679,23 @@ elation.require(['physics.common', 'utils.math'], function() {
669
679
 
670
680
  let distSquared = elation.physics.colliders.helperfuncs.distancesquared_between_lines(capsule1Dims.start, capsule1Dims.end, capsule2Dims.start, capsule2Dims.end, p1, p2);
671
681
 
672
- if (distSquared <= Math.pow(capsule1.radius + capsule2.radius, 2)) {
682
+ const capsule1ScaledRadius = capsule1.radius * Math.max(capsule1.body.scale.x, capsule1.body.scale.z),
683
+ capsule2ScaledRadius = capsule2.radius * Math.max(capsule2.body.scale.x, capsule2.body.scale.z);
684
+
685
+ if (distSquared <= Math.pow(capsule1ScaledRadius + capsule2ScaledRadius, 2)) {
673
686
  console.log('CAPSULE COLLIDE', capsule1, capsule2);
674
687
  let normal = new THREE.Vector3().subVectors(p2, p1),
675
688
  point = p1.clone();
676
689
  dist = Math.sqrt(distSquared);
677
690
  normal.divideScalar(dist);
678
- point.x += normal.x * capsule1.radius;
679
- point.y += normal.y * capsule1.radius;
680
- point.z += normal.z * capsule1.radius;
691
+ point.x += normal.x * capsule1ScaledRadius;
692
+ point.y += normal.y * capsule1ScaledRadius;
693
+ point.z += normal.z * capsule1ScaledRadius;
681
694
 
682
695
  let contact = new elation.physics.contact({
683
696
  normal: normal,
684
697
  point: point,
685
- penetration: dist - (capsule1.radius + capsule2.radius),
698
+ penetration: dist - (capsule1ScaledRadius + capsule2ScaledRadius),
686
699
  bodies: [capsule1.body, capsule2.body]
687
700
  });
688
701
  contacts.push(contact);
@@ -796,13 +809,12 @@ elation.require(['physics.common', 'utils.math'], function() {
796
809
  p3 = worldpoints.p3,
797
810
  normal = worldpoints.normal;
798
811
 
799
- //if (spherevel.dot(normal) > 0) return; // moving away, can't collide
800
-
812
+ let velNormal = spherevel.dot(normal);
801
813
 
802
814
  // Check if we're already in contact
803
815
  elation.physics.colliders.helperfuncs.closest_point_on_triangle(spherepos, p1, p2, p3, triangleClosestPoint);
804
816
  let triangleDistSquared = triangleClosestPoint.distanceToSquared(spherepos)
805
- if (triangleDistSquared < sphere.radius * sphere.radius) {
817
+ if (triangleDistSquared < sphere.radius * sphere.radius && velNormal <= 0) {
806
818
  let contact = new elation.physics.contact({
807
819
  normal: normal.clone(), // allocate normal
808
820
  point: triangleClosestPoint.clone(), // allocate point
@@ -875,7 +887,7 @@ elation.require(['physics.common', 'utils.math'], function() {
875
887
  intersectionPoint.y - triangleClosestPoint.y,
876
888
  intersectionPoint.z - triangleClosestPoint.z
877
889
  );
878
- normal.normalize();
890
+ collisionNormal.normalize();
879
891
 
880
892
  intersectionPoint.x += collisionNormal.x * -sphere.radius;
881
893
  intersectionPoint.y += collisionNormal.y * -sphere.radius;
@@ -1687,6 +1699,8 @@ elation.require(['physics.common', 'utils.math'], function() {
1687
1699
  let triangles = [];
1688
1700
  let radiusSq = 0;
1689
1701
 
1702
+ this.body.updateState(); // ensure scaleWorld is up to date before processing triangles
1703
+ let doubleSided = false;
1690
1704
  if (!this.modeldata && this.mesh && this.mesh.geometry) {
1691
1705
  if (this.mesh.geometry instanceof THREE.BufferGeometry) {
1692
1706
  this.modeldata = {
@@ -1702,6 +1716,7 @@ elation.require(['physics.common', 'utils.math'], function() {
1702
1716
  }
1703
1717
  }
1704
1718
  }
1719
+ doubleSided = this.mesh.material.side == THREE.DoubleSide;
1705
1720
  }
1706
1721
  if (this.modeldata) {
1707
1722
  if (this.modeldata.index) {
@@ -1727,6 +1742,11 @@ elation.require(['physics.common', 'utils.math'], function() {
1727
1742
  if (!triangle.isDegenerate()) {
1728
1743
  triangles.push(triangle);
1729
1744
 
1745
+ if (doubleSided) {
1746
+ let triangle2 = new elation.physics.colliders.triangle(this.body, [p3, p2, p1]);
1747
+ triangles.push(triangle2);
1748
+ }
1749
+
1730
1750
  let l1 = p1.lengthSq(),
1731
1751
  l2 = p2.lengthSq(),
1732
1752
  l3 = p3.lengthSq();
@@ -1761,7 +1781,7 @@ elation.require(['physics.common', 'utils.math'], function() {
1761
1781
  }
1762
1782
  }
1763
1783
  }
1764
- this.radius = Math.sqrt(radiusSq);
1784
+ this.radius = Math.sqrt(radiusSq) * Math.max(this.body.scaleWorld.x, this.body.scaleWorld.y, this.body.scaleWorld.z);
1765
1785
  this.boundingSphere.radius = this.radius;
1766
1786
  return triangles;
1767
1787
  }
@@ -1797,11 +1817,11 @@ elation.require(['physics.common', 'utils.math'], function() {
1797
1817
  bodies[obj.uuid].scale.copy(obj.scale);
1798
1818
  bodies[obj.uuid].orientation.copy(obj.quaternion);
1799
1819
  bodies[obj.uuid].object = this.body.object;
1820
+ parent.add(bodies[obj.uuid]);
1800
1821
  if (obj instanceof THREE.Mesh) {
1801
1822
  bodies[obj.uuid].setCollider('mesh', {mesh: obj, isroot: false });
1802
1823
  //elation.events.add(bodies[obj.uuid], 'physics_collide', (ev) => elation.events.fire({type: 'physics_collide', element: this.body, event: ev}));
1803
1824
  }
1804
- parent.add(bodies[obj.uuid]);
1805
1825
  }
1806
1826
  parent = bodies[obj.uuid];
1807
1827
  }
@@ -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
  });