hyperstellar 0.1.67__tar.gz → 0.1.69__tar.gz

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.
Files changed (18) hide show
  1. {hyperstellar-0.1.67 → hyperstellar-0.1.69}/PKG-INFO +1 -1
  2. {hyperstellar-0.1.67 → hyperstellar-0.1.69}/hyperstellar/src/hyperstellar/_native/windows-x64/shaders/math.comp +152 -96
  3. {hyperstellar-0.1.67 → hyperstellar-0.1.69}/hyperstellar/src/hyperstellar/_native/windows-x64/stellar.pyd +0 -0
  4. {hyperstellar-0.1.67 → hyperstellar-0.1.69}/hyperstellar/src/hyperstellar.egg-info/PKG-INFO +1 -1
  5. {hyperstellar-0.1.67 → hyperstellar-0.1.69}/pyproject.toml +3 -1
  6. {hyperstellar-0.1.67 → hyperstellar-0.1.69}/LICENSE +0 -0
  7. {hyperstellar-0.1.67 → hyperstellar-0.1.69}/README.md +0 -0
  8. {hyperstellar-0.1.67 → hyperstellar-0.1.69}/hyperstellar/src/hyperstellar/__init__.py +0 -0
  9. {hyperstellar-0.1.67 → hyperstellar-0.1.69}/hyperstellar/src/hyperstellar/__init__.pyi +0 -0
  10. {hyperstellar-0.1.67 → hyperstellar-0.1.69}/hyperstellar/src/hyperstellar/_native/windows-x64/shaders/quad.frag +0 -0
  11. {hyperstellar-0.1.67 → hyperstellar-0.1.69}/hyperstellar/src/hyperstellar/_native/windows-x64/shaders/quad.geom +0 -0
  12. {hyperstellar-0.1.67 → hyperstellar-0.1.69}/hyperstellar/src/hyperstellar/_native/windows-x64/shaders/quad.vert +0 -0
  13. {hyperstellar-0.1.67 → hyperstellar-0.1.69}/hyperstellar/src/hyperstellar/py.typed +0 -0
  14. {hyperstellar-0.1.67 → hyperstellar-0.1.69}/hyperstellar/src/hyperstellar.egg-info/SOURCES.txt +0 -0
  15. {hyperstellar-0.1.67 → hyperstellar-0.1.69}/hyperstellar/src/hyperstellar.egg-info/dependency_links.txt +0 -0
  16. {hyperstellar-0.1.67 → hyperstellar-0.1.69}/hyperstellar/src/hyperstellar.egg-info/top_level.txt +0 -0
  17. {hyperstellar-0.1.67 → hyperstellar-0.1.69}/setup.cfg +0 -0
  18. {hyperstellar-0.1.67 → hyperstellar-0.1.69}/tests/test.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hyperstellar
3
- Version: 0.1.67
3
+ Version: 0.1.69
4
4
  Summary: GPU-accelerated physics simulation engine
5
5
  Author-email: Aiden Jabari <Jabariaiden15@email.com>
6
6
  License: MIT License
@@ -1110,7 +1110,7 @@ void applyConstraints(inout vec2 pos, inout vec2 vel, int objectIndex, vec2 orig
1110
1110
  }
1111
1111
 
1112
1112
  // ============================================================================
1113
- // COLLISION DETECTION FUNCTIONS
1113
+ // COLLISION DETECTION FUNCTIONS (UNCHANGED - KEEP YOUR EXISTING CODE)
1114
1114
  // ============================================================================
1115
1115
 
1116
1116
  // Circle-Circle collision detection
@@ -1137,41 +1137,35 @@ CollisionInfo detectCircleCircle(vec2 posA, float radiusA, vec2 posB, float radi
1137
1137
  return info;
1138
1138
  }
1139
1139
 
1140
- // Hybrid AABB detection: current positions for penetration, old positions for normal direction
1141
- CollisionInfo detectAABBAABB(vec2 posA_curr, vec2 halfExtA, vec2 posB_curr, vec2 halfExtB,
1142
- vec2 posA_old, vec2 posB_old, int objB)
1140
+ // Axis-Aligned Bounding Box collision detection
1141
+ CollisionInfo detectAABBAABB(vec2 posA, vec2 halfExtA, vec2 posB, vec2 halfExtB, int objB)
1143
1142
  {
1144
1143
  CollisionInfo info;
1145
1144
  info.hasCollision = false;
1146
1145
  info.otherObjectID = objB;
1147
-
1148
- // Penetration uses CURRENT (predicted/selfNew) positions
1149
- vec2 delta_curr = posB_curr - posA_curr;
1150
- vec2 overlap = halfExtA + halfExtB - abs(delta_curr);
1151
-
1146
+
1147
+ // Calculate separation vector
1148
+ vec2 delta = posB - posA;
1149
+ vec2 overlap = halfExtA + halfExtB - abs(delta);
1150
+
1151
+ // Check for overlap on both axes
1152
1152
  if (overlap.x > 0.0 && overlap.y > 0.0)
1153
1153
  {
1154
1154
  info.hasCollision = true;
1155
-
1156
- // Normal direction uses OLD positions (physically correct side)
1157
- vec2 delta_old = posB_old - posA_old;
1158
-
1159
- // Choose the MINIMUM overlap axis — that's the separation axis
1160
- if (overlap.x < overlap.y ||
1161
- (abs(overlap.x - overlap.y) < 0.001 && abs(delta_old.x) >= abs(delta_old.y)))
1155
+
1156
+ // Resolve along minimum penetration axis
1157
+ if (overlap.x < overlap.y)
1162
1158
  {
1163
- // Minimum penetration is along X — push along X
1164
- info.normal = vec2(sign(delta_old.x), 0.0);
1159
+ info.normal = vec2(sign(delta.x), 0.0);
1165
1160
  info.penetration = overlap.x;
1166
1161
  }
1167
1162
  else
1168
1163
  {
1169
- // Minimum penetration is along Y — push along Y
1170
- info.normal = vec2(0.0, sign(delta_old.y));
1164
+ info.normal = vec2(0.0, sign(delta.y));
1171
1165
  info.penetration = overlap.y;
1172
1166
  }
1173
1167
  }
1174
-
1168
+
1175
1169
  return info;
1176
1170
  }
1177
1171
 
@@ -1393,38 +1387,43 @@ CollisionInfo detectCirclePolygon(vec2 circlePos, float circleRadius,
1393
1387
  return info;
1394
1388
  }
1395
1389
 
1396
- // Master collision detection dispatcher - hybrid for AABB
1397
- CollisionInfo detectCollision(Object objA, Object objB, int objIndexB,
1398
- vec2 posA_old, vec2 posB_old)
1390
+ // Master collision detection dispatcher
1391
+ CollisionInfo detectCollision(Object objA, Object objB, int objIndexB)
1399
1392
  {
1400
1393
  CollisionInfo info;
1401
1394
  info.hasCollision = false;
1402
1395
 
1396
+ // Get collision properties for both objects
1403
1397
  CollisionProperties propsA = collisionProps[gl_GlobalInvocationID.x];
1404
1398
  CollisionProperties propsB = collisionProps[objIndexB];
1405
1399
 
1400
+ // Check if collisions are enabled for both objects
1406
1401
  if (propsA.enabled == 0 || propsB.enabled == 0)
1407
1402
  return info;
1408
1403
 
1409
1404
  int shapeA = propsA.shapeType;
1410
1405
  int shapeB = propsB.shapeType;
1411
1406
 
1407
+ // Skip if either object has no collision shape
1412
1408
  if (shapeA == COLLISION_NONE || shapeB == COLLISION_NONE)
1413
1409
  return info;
1414
1410
 
1411
+ // Dispatch to appropriate collision detection function based on shape types
1415
1412
  if (shapeA == COLLISION_CIRCLE && shapeB == COLLISION_CIRCLE)
1416
1413
  {
1414
+ // Circle vs Circle
1417
1415
  info = detectCircleCircle(objA.position, objA.visualData.x,
1418
1416
  objB.position, objB.visualData.x, objIndexB);
1419
1417
  }
1418
+ // AABB vs AABB
1420
1419
  else if (shapeA == COLLISION_AABB && shapeB == COLLISION_AABB)
1421
1420
  {
1422
1421
  vec2 halfExtA = objA.visualData.xy * 0.5;
1423
1422
  vec2 halfExtB = objB.visualData.xy * 0.5;
1424
1423
  info = detectAABBAABB(objA.position, halfExtA,
1425
- objB.position, halfExtB,
1426
- posA_old, posB_old, objIndexB);
1424
+ objB.position, halfExtB, objIndexB);
1427
1425
  }
1426
+ // Polygon vs Polygon
1428
1427
  else if (shapeA == COLLISION_POLYGON && shapeB == COLLISION_POLYGON)
1429
1428
  {
1430
1429
  info = detectPolygonPolygon(
@@ -1432,6 +1431,7 @@ CollisionInfo detectCollision(Object objA, Object objB, int objIndexB,
1432
1431
  objB.position, objB.visualData.x, int(objB.visualData.y), objB.visualData.z,
1433
1432
  objIndexB);
1434
1433
  }
1434
+ // Circle vs AABB
1435
1435
  else if (shapeA == COLLISION_CIRCLE && shapeB == COLLISION_AABB)
1436
1436
  {
1437
1437
  vec2 halfExtB = objB.visualData.xy * 0.5;
@@ -1443,7 +1443,7 @@ CollisionInfo detectCollision(Object objA, Object objB, int objIndexB,
1443
1443
  vec2 halfExtA = objA.visualData.xy * 0.5;
1444
1444
  info = detectCircleAABB(objB.position, objB.visualData.x,
1445
1445
  objA.position, halfExtA, objIndexB);
1446
- info.normal = -info.normal;
1446
+ info.normal = -info.normal; // Flip normal
1447
1447
  }
1448
1448
  else if (shapeA == COLLISION_CIRCLE && shapeB == COLLISION_POLYGON)
1449
1449
  {
@@ -1458,14 +1458,14 @@ CollisionInfo detectCollision(Object objA, Object objB, int objIndexB,
1458
1458
  objA.position, objA.visualData.x,
1459
1459
  int(objA.visualData.y), objA.visualData.z,
1460
1460
  objIndexB);
1461
- info.normal = -info.normal;
1461
+ info.normal = -info.normal; // Flip normal
1462
1462
  }
1463
1463
  else if (shapeA == COLLISION_AABB && shapeB == COLLISION_POLYGON)
1464
1464
  {
1465
1465
  vec2 halfExtA = objA.visualData.xy * 0.5;
1466
1466
  info = detectCircleAABB(objB.position, objB.visualData.x,
1467
1467
  objA.position, halfExtA, objIndexB);
1468
- info.normal = -info.normal;
1468
+ info.normal = -info.normal; // Flip normal
1469
1469
  }
1470
1470
  else if (shapeA == COLLISION_POLYGON && shapeB == COLLISION_AABB)
1471
1471
  {
@@ -1853,94 +1853,144 @@ void main() {
1853
1853
  vec2 new_pos = pos + new_vel * uDt;
1854
1854
  new_pos = sanitizeVec2(new_pos);
1855
1855
 
1856
- Object selfNew = p; // copy original
1857
- selfNew.position = new_pos; // update position
1858
-
1859
1856
  // 3. Same for angular motion
1860
1857
  float new_angular_vel = angular_vel + angular_accel * uDt;
1861
1858
  float new_rotation = rotation + new_angular_vel * uDt;
1862
1859
  new_rotation = mod(new_rotation, 2.0 * PI); // Wrap rotation
1863
1860
 
1861
+ // ========================================================================
1862
+ // WORLD BOUNDARIES
1863
+ // ========================================================================
1864
+ const vec2 world_min = vec2(-1000000.0, -1000000.0);
1865
+ const vec2 world_max = vec2(1000000.0, 1000000.0);
1866
+ const float boundary_friction = 0.95;
1867
+
1868
+ // X boundaries
1869
+ if (new_pos.x < world_min.x) {
1870
+ new_pos.x = world_min.x;
1871
+ new_vel.x = abs(new_vel.x) * uRestitution;
1872
+ new_vel.y *= boundary_friction;
1873
+ }
1874
+ else if (new_pos.x > world_max.x) {
1875
+ new_pos.x = world_max.x;
1876
+ new_vel.x = -abs(new_vel.x) * uRestitution;
1877
+ new_vel.y *= boundary_friction;
1878
+ }
1879
+
1880
+ // Y boundaries
1881
+ if (new_pos.y < world_min.y) {
1882
+ new_pos.y = world_min.y;
1883
+ new_vel.y = abs(new_vel.y) * uRestitution;
1884
+ new_vel.x *= boundary_friction;
1885
+ }
1886
+ else if (new_pos.y > world_max.y) {
1887
+ new_pos.y = world_max.y;
1888
+ new_vel.y = -abs(new_vel.y) * uRestitution;
1889
+ new_vel.x *= boundary_friction;
1890
+ }
1891
+
1864
1892
  // ========================================================================
1865
1893
  // CONSTRAINT RESOLUTION (UNCHANGED)
1866
1894
  // ========================================================================
1867
1895
  applyConstraints(new_pos, new_vel, objectIndex, originalPos);
1868
1896
 
1869
- // ========================================================================
1870
- // COLLISION HANDLING - Hybrid AABB + safe normal direction
1871
- // ========================================================================
1872
- vec2 collision_vel = new_vel;
1873
- vec2 final_pos = new_pos;
1874
- bool had_collision = false;
1897
+ // ========================================================================
1898
+ // NEW: COLLISION SYSTEM - FIXED FOR PARALLEL EXECUTION
1899
+ // ========================================================================
1900
+
1901
+ // Strategy:
1902
+ // 1. Each thread only modifies its OWN object's velocity
1903
+ // 2. Use impulses that conserve momentum without modifying other objects
1904
+ // 3. Position correction happens AFTER all velocity updates
1905
+
1906
+ vec2 collision_vel = new_vel;
1907
+ bool had_collision = false;
1908
+
1909
+ // Check collisions with ALL other objects (not just higher indices)
1910
+ for (int i = 0; i < uNumObjects; i++) {
1911
+ if (i == objectIndex) continue; // Skip self
1912
+
1913
+ Object other = objectsIn[i];
1875
1914
 
1876
- for (int i = 0; i < uNumObjects; i++) {
1877
- if (i == objectIndex) continue;
1915
+ // Detect collision
1916
+ CollisionInfo collision = detectCollision(p, other, i);
1917
+
1918
+ if (collision.hasCollision) {
1919
+ had_collision = true;
1878
1920
 
1879
- Object other = objectsIn[i];
1921
+ // Get collision properties
1922
+ CollisionProperties propsA = collisionProps[objectIndex];
1923
+ CollisionProperties propsB = collisionProps[i];
1880
1924
 
1881
- CollisionInfo collision = detectCollision(selfNew, other, i, p.position, other.position);
1925
+ // Calculate effective properties
1926
+ float restitution = min(propsA.restitution, propsB.restitution);
1927
+ float friction = sqrt(propsA.friction * propsB.friction);
1882
1928
 
1883
- if (collision.hasCollision) {
1884
- had_collision = true;
1885
-
1886
- CollisionProperties propsA = collisionProps[objectIndex];
1887
- CollisionProperties propsB = collisionProps[i];
1888
-
1889
- float restitution = min(propsA.restitution, propsB.restitution);
1890
- float friction = sqrt(propsA.friction * propsB.friction);
1891
-
1892
- float massA = mass;
1893
- float massB = max(EPSILON, other.mass);
1894
-
1895
- // === ENSURE NORMAL POINTS AWAY FROM THIS OBJECT ===
1896
- vec2 fromOther = selfNew.position - other.position;
1897
- if (dot(collision.normal, fromOther) < 0.0) {
1898
- collision.normal = -collision.normal;
1899
- }
1929
+ // Get masses
1930
+ float massA = mass;
1931
+ float massB = max(EPSILON, other.mass);
1932
+
1933
+ // Relative velocity
1934
+ vec2 relativeVel = other.velocity - collision_vel;
1935
+ float velocityAlongNormal = dot(relativeVel, collision.normal);
1936
+
1937
+ // Only resolve if moving toward each other
1938
+ if (velocityAlongNormal < 0.0) {
1939
+ // Calculate impulse (standard rigid body physics)
1940
+ float e = clamp(restitution, 0.0, 1.0);
1941
+ float j = -(1.0 + e) * velocityAlongNormal;
1942
+ j /= (1.0 / massA + 1.0 / massB);
1900
1943
 
1901
- // Velocity impulse
1902
- vec2 relativeVel = other.velocity - collision_vel;
1903
- float velAlongNormal = dot(relativeVel, collision.normal);
1944
+ // Apply impulse to THIS object only
1945
+ vec2 impulse = j * collision.normal;
1946
+ collision_vel -= impulse / massA;
1904
1947
 
1905
- if (velAlongNormal < 0.0) {
1906
- float e = clamp(restitution, 0.0, 1.0);
1907
- float j = -(1.0 + e) * velAlongNormal / (1.0/massA + 1.0/massB);
1908
- collision_vel -= (j * collision.normal) / massA;
1948
+ // Friction
1949
+ if (friction > 0.0) {
1950
+ vec2 tangent = relativeVel - collision.normal * dot(relativeVel, collision.normal);
1951
+ float tangentLength = length(tangent);
1909
1952
 
1910
- if (friction > 0.0) {
1911
- vec2 tangent = relativeVel - collision.normal * dot(relativeVel, collision.normal);
1912
- float tLen = length(tangent);
1913
- if (tLen > 0.01) {
1914
- tangent = normalize(tangent);
1915
- float vt = dot(relativeVel, tangent);
1916
- float jt = -vt * friction * 0.5;
1917
- float maxJt = abs(j) * friction;
1918
- jt = clamp(jt, -maxJt, maxJt);
1919
- collision_vel -= (jt * tangent) / massA;
1920
- }
1953
+ if (tangentLength > EPSILON) {
1954
+ tangent = normalize(tangent);
1955
+ float vt = dot(relativeVel, tangent);
1956
+
1957
+ float jt = -vt * friction;
1958
+ jt /= (1.0 / massA + 1.0 / massB);
1959
+
1960
+ // Coulomb friction limit
1961
+ float maxFriction = abs(j) * friction;
1962
+ jt = clamp(jt, -maxFriction, maxFriction);
1963
+
1964
+ vec2 frictionImpulse = jt * tangent;
1965
+ collision_vel -= frictionImpulse / massA;
1921
1966
  }
1922
1967
  }
1968
+ }
1969
+
1970
+ // POSITION CORRECTION - only for deep penetrations
1971
+ // Move THIS object away from penetration
1972
+ const float slop = 0.01;
1973
+ const float percent = 0.4; // Less aggressive than before
1974
+
1975
+ if (collision.penetration > slop) {
1976
+ float totalMass = massA + massB;
1977
+ vec2 correction = collision.normal * (collision.penetration - slop) * percent;
1923
1978
 
1924
- // Position correction - conservative for stability
1925
- const float slop = 0.045;
1926
- const float percent = 0.62;
1927
-
1928
- if (collision.penetration > slop) {
1929
- float totalMass = massA + massB;
1930
- vec2 correction = collision.normal * (collision.penetration - slop) * percent * (massB / totalMass);
1931
- final_pos -= correction;
1932
- }
1979
+ // Only correct THIS object's position
1980
+ // The correction is weighted by the inverse mass ratio
1981
+ new_pos -= correction * (massB / totalMass);
1933
1982
  }
1934
1983
  }
1935
-
1936
- if (had_collision) {
1937
- new_vel = sanitizeVec2(collision_vel);
1938
- }
1939
- new_pos = sanitizeVec2(final_pos);
1984
+ }
1940
1985
 
1941
- // ========================================================================
1942
- // REST OF CODE (age contacts, final sanity, write output)
1943
- // ========================================================================
1986
+ // Apply collision-modified velocity
1987
+ if (had_collision) {
1988
+ new_vel = sanitizeVec2(collision_vel);
1989
+ }
1990
+
1991
+ // ========================================================================
1992
+ // REST OF CODE(boundaries, final write, etc.)
1993
+ // ========================================================================
1944
1994
 
1945
1995
  // Age out old contacts for this object
1946
1996
  if (uEnableWarmStart == 1) {
@@ -1951,14 +2001,20 @@ void main() {
1951
2001
  new_pos = sanitizeVec2(new_pos);
1952
2002
  new_vel = sanitizeVec2(new_vel);
1953
2003
 
1954
- // Final sanity checks
2004
+ // ========================================================================
2005
+ // FINAL SANITY CHECKS
2006
+ // ========================================================================
2007
+
2008
+ // Ensure velocities aren't excessive
1955
2009
  float maxSpeed = 1000.0;
1956
2010
  float currentSpeed = length(new_vel);
1957
2011
  if (currentSpeed > maxSpeed) {
1958
2012
  new_vel = normalize(new_vel) * maxSpeed;
1959
2013
  }
1960
2014
 
1961
- // Write updated object state
2015
+ // ========================================================================
2016
+ // WRITE UPDATED OBJECT STATE
2017
+ // ========================================================================
1962
2018
  objectsOut[gid].position = new_pos;
1963
2019
  objectsOut[gid].velocity = new_vel;
1964
2020
  objectsOut[gid].mass = mass;
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hyperstellar
3
- Version: 0.1.67
3
+ Version: 0.1.69
4
4
  Summary: GPU-accelerated physics simulation engine
5
5
  Author-email: Aiden Jabari <Jabariaiden15@email.com>
6
6
  License: MIT License
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "hyperstellar"
7
- version = "0.1.67"
7
+ version = "0.1.69"
8
8
  description = "GPU-accelerated physics simulation engine"
9
9
  readme = "README.md"
10
10
  authors = [{name = "Aiden Jabari", email = "Jabariaiden15@email.com"}]
@@ -65,6 +65,8 @@ where = ["hyperstellar/src"]
65
65
 
66
66
 
67
67
 
68
+
69
+
68
70
 
69
71
 
70
72
 
File without changes
File without changes
File without changes