hyperstellar 0.1.65__tar.gz → 0.1.67__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.65 → hyperstellar-0.1.67}/PKG-INFO +1 -1
  2. {hyperstellar-0.1.65 → hyperstellar-0.1.67}/hyperstellar/src/hyperstellar/_native/windows-x64/shaders/math.comp +50 -66
  3. {hyperstellar-0.1.65 → hyperstellar-0.1.67}/hyperstellar/src/hyperstellar/_native/windows-x64/stellar.pyd +0 -0
  4. {hyperstellar-0.1.65 → hyperstellar-0.1.67}/hyperstellar/src/hyperstellar.egg-info/PKG-INFO +1 -1
  5. {hyperstellar-0.1.65 → hyperstellar-0.1.67}/pyproject.toml +3 -1
  6. {hyperstellar-0.1.65 → hyperstellar-0.1.67}/LICENSE +0 -0
  7. {hyperstellar-0.1.65 → hyperstellar-0.1.67}/README.md +0 -0
  8. {hyperstellar-0.1.65 → hyperstellar-0.1.67}/hyperstellar/src/hyperstellar/__init__.py +0 -0
  9. {hyperstellar-0.1.65 → hyperstellar-0.1.67}/hyperstellar/src/hyperstellar/__init__.pyi +0 -0
  10. {hyperstellar-0.1.65 → hyperstellar-0.1.67}/hyperstellar/src/hyperstellar/_native/windows-x64/shaders/quad.frag +0 -0
  11. {hyperstellar-0.1.65 → hyperstellar-0.1.67}/hyperstellar/src/hyperstellar/_native/windows-x64/shaders/quad.geom +0 -0
  12. {hyperstellar-0.1.65 → hyperstellar-0.1.67}/hyperstellar/src/hyperstellar/_native/windows-x64/shaders/quad.vert +0 -0
  13. {hyperstellar-0.1.65 → hyperstellar-0.1.67}/hyperstellar/src/hyperstellar/py.typed +0 -0
  14. {hyperstellar-0.1.65 → hyperstellar-0.1.67}/hyperstellar/src/hyperstellar.egg-info/SOURCES.txt +0 -0
  15. {hyperstellar-0.1.65 → hyperstellar-0.1.67}/hyperstellar/src/hyperstellar.egg-info/dependency_links.txt +0 -0
  16. {hyperstellar-0.1.65 → hyperstellar-0.1.67}/hyperstellar/src/hyperstellar.egg-info/top_level.txt +0 -0
  17. {hyperstellar-0.1.65 → hyperstellar-0.1.67}/setup.cfg +0 -0
  18. {hyperstellar-0.1.65 → hyperstellar-0.1.67}/tests/test.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hyperstellar
3
- Version: 0.1.65
3
+ Version: 0.1.67
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 (UNCHANGED - KEEP YOUR EXISTING CODE)
1113
+ // COLLISION DETECTION FUNCTIONS
1114
1114
  // ============================================================================
1115
1115
 
1116
1116
  // Circle-Circle collision detection
@@ -1137,35 +1137,41 @@ CollisionInfo detectCircleCircle(vec2 posA, float radiusA, vec2 posB, float radi
1137
1137
  return info;
1138
1138
  }
1139
1139
 
1140
- // Axis-Aligned Bounding Box collision detection
1141
- CollisionInfo detectAABBAABB(vec2 posA, vec2 halfExtA, vec2 posB, vec2 halfExtB, int objB)
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)
1142
1143
  {
1143
1144
  CollisionInfo info;
1144
1145
  info.hasCollision = false;
1145
1146
  info.otherObjectID = objB;
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
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
+
1152
1152
  if (overlap.x > 0.0 && overlap.y > 0.0)
1153
1153
  {
1154
1154
  info.hasCollision = true;
1155
-
1156
- // Resolve along minimum penetration axis
1157
- if (overlap.x < overlap.y)
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)))
1158
1162
  {
1159
- info.normal = vec2(sign(delta.x), 0.0);
1163
+ // Minimum penetration is along X — push along X
1164
+ info.normal = vec2(sign(delta_old.x), 0.0);
1160
1165
  info.penetration = overlap.x;
1161
1166
  }
1162
1167
  else
1163
1168
  {
1164
- info.normal = vec2(0.0, sign(delta.y));
1169
+ // Minimum penetration is along Y — push along Y
1170
+ info.normal = vec2(0.0, sign(delta_old.y));
1165
1171
  info.penetration = overlap.y;
1166
1172
  }
1167
1173
  }
1168
-
1174
+
1169
1175
  return info;
1170
1176
  }
1171
1177
 
@@ -1387,43 +1393,38 @@ CollisionInfo detectCirclePolygon(vec2 circlePos, float circleRadius,
1387
1393
  return info;
1388
1394
  }
1389
1395
 
1390
- // Master collision detection dispatcher
1391
- CollisionInfo detectCollision(Object objA, Object objB, int objIndexB)
1396
+ // Master collision detection dispatcher - hybrid for AABB
1397
+ CollisionInfo detectCollision(Object objA, Object objB, int objIndexB,
1398
+ vec2 posA_old, vec2 posB_old)
1392
1399
  {
1393
1400
  CollisionInfo info;
1394
1401
  info.hasCollision = false;
1395
1402
 
1396
- // Get collision properties for both objects
1397
1403
  CollisionProperties propsA = collisionProps[gl_GlobalInvocationID.x];
1398
1404
  CollisionProperties propsB = collisionProps[objIndexB];
1399
1405
 
1400
- // Check if collisions are enabled for both objects
1401
1406
  if (propsA.enabled == 0 || propsB.enabled == 0)
1402
1407
  return info;
1403
1408
 
1404
1409
  int shapeA = propsA.shapeType;
1405
1410
  int shapeB = propsB.shapeType;
1406
1411
 
1407
- // Skip if either object has no collision shape
1408
1412
  if (shapeA == COLLISION_NONE || shapeB == COLLISION_NONE)
1409
1413
  return info;
1410
1414
 
1411
- // Dispatch to appropriate collision detection function based on shape types
1412
1415
  if (shapeA == COLLISION_CIRCLE && shapeB == COLLISION_CIRCLE)
1413
1416
  {
1414
- // Circle vs Circle
1415
1417
  info = detectCircleCircle(objA.position, objA.visualData.x,
1416
1418
  objB.position, objB.visualData.x, objIndexB);
1417
1419
  }
1418
- // AABB vs AABB
1419
1420
  else if (shapeA == COLLISION_AABB && shapeB == COLLISION_AABB)
1420
1421
  {
1421
1422
  vec2 halfExtA = objA.visualData.xy * 0.5;
1422
1423
  vec2 halfExtB = objB.visualData.xy * 0.5;
1423
1424
  info = detectAABBAABB(objA.position, halfExtA,
1424
- objB.position, halfExtB, objIndexB);
1425
+ objB.position, halfExtB,
1426
+ posA_old, posB_old, objIndexB);
1425
1427
  }
1426
- // Polygon vs Polygon
1427
1428
  else if (shapeA == COLLISION_POLYGON && shapeB == COLLISION_POLYGON)
1428
1429
  {
1429
1430
  info = detectPolygonPolygon(
@@ -1431,7 +1432,6 @@ CollisionInfo detectCollision(Object objA, Object objB, int objIndexB)
1431
1432
  objB.position, objB.visualData.x, int(objB.visualData.y), objB.visualData.z,
1432
1433
  objIndexB);
1433
1434
  }
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;
@@ -1440,13 +1440,11 @@ CollisionInfo detectCollision(Object objA, Object objB, int objIndexB)
1440
1440
  }
1441
1441
  else if (shapeA == COLLISION_AABB && shapeB == COLLISION_CIRCLE)
1442
1442
  {
1443
- // Swap roles and flip normal
1444
1443
  vec2 halfExtA = objA.visualData.xy * 0.5;
1445
1444
  info = detectCircleAABB(objB.position, objB.visualData.x,
1446
1445
  objA.position, halfExtA, objIndexB);
1447
- info.normal = -info.normal; // Flip normal
1446
+ info.normal = -info.normal;
1448
1447
  }
1449
- // Circle vs Polygon
1450
1448
  else if (shapeA == COLLISION_CIRCLE && shapeB == COLLISION_POLYGON)
1451
1449
  {
1452
1450
  info = detectCirclePolygon(objA.position, objA.visualData.x,
@@ -1460,15 +1458,14 @@ CollisionInfo detectCollision(Object objA, Object objB, int objIndexB)
1460
1458
  objA.position, objA.visualData.x,
1461
1459
  int(objA.visualData.y), objA.visualData.z,
1462
1460
  objIndexB);
1463
- info.normal = -info.normal; // Flip normal
1461
+ info.normal = -info.normal;
1464
1462
  }
1465
- // AABB vs Polygon (simplified - treat polygon as circle for collision)
1466
1463
  else if (shapeA == COLLISION_AABB && shapeB == COLLISION_POLYGON)
1467
1464
  {
1468
1465
  vec2 halfExtA = objA.visualData.xy * 0.5;
1469
1466
  info = detectCircleAABB(objB.position, objB.visualData.x,
1470
1467
  objA.position, halfExtA, objIndexB);
1471
- info.normal = -info.normal; // Flip normal
1468
+ info.normal = -info.normal;
1472
1469
  }
1473
1470
  else if (shapeA == COLLISION_POLYGON && shapeB == COLLISION_AABB)
1474
1471
  {
@@ -1480,10 +1477,6 @@ CollisionInfo detectCollision(Object objA, Object objB, int objIndexB)
1480
1477
  return info;
1481
1478
  }
1482
1479
 
1483
- // ============================================================================
1484
- // RESEARCH-GRADE COLLISION RESOLUTION SYSTEM
1485
- // ============================================================================
1486
-
1487
1480
  // ============================================================================
1488
1481
  // BASIC COLLISION RESPONSE (Momentum-Conserving)
1489
1482
  // ============================================================================
@@ -1874,10 +1867,10 @@ void main() {
1874
1867
  applyConstraints(new_pos, new_vel, objectIndex, originalPos);
1875
1868
 
1876
1869
  // ========================================================================
1877
- // COLLISION HANDLING - Keep selfNew for circles, but fix stickiness for rectangles
1870
+ // COLLISION HANDLING - Hybrid AABB + safe normal direction
1878
1871
  // ========================================================================
1879
1872
  vec2 collision_vel = new_vel;
1880
- vec2 final_pos = new_pos; // Accumulate corrections (prevents feedback loop)
1873
+ vec2 final_pos = new_pos;
1881
1874
  bool had_collision = false;
1882
1875
 
1883
1876
  for (int i = 0; i < uNumObjects; i++) {
@@ -1885,8 +1878,7 @@ void main() {
1885
1878
 
1886
1879
  Object other = objectsIn[i];
1887
1880
 
1888
- // Keep your selfNew detection - this is what made circles bouncy
1889
- CollisionInfo collision = detectCollision(selfNew, other, i); // <--- selfNew here
1881
+ CollisionInfo collision = detectCollision(selfNew, other, i, p.position, other.position);
1890
1882
 
1891
1883
  if (collision.hasCollision) {
1892
1884
  had_collision = true;
@@ -1900,24 +1892,28 @@ void main() {
1900
1892
  float massA = mass;
1901
1893
  float massB = max(EPSILON, other.mass);
1902
1894
 
1903
- // Velocity impulse (asymmetric - only affect this object)
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
+ }
1900
+
1901
+ // Velocity impulse
1904
1902
  vec2 relativeVel = other.velocity - collision_vel;
1905
1903
  float velAlongNormal = dot(relativeVel, collision.normal);
1906
1904
 
1907
- if (velAlongNormal < 0.0) { // approaching
1905
+ if (velAlongNormal < 0.0) {
1908
1906
  float e = clamp(restitution, 0.0, 1.0);
1909
- float j = -(1.0 + e) * velAlongNormal / (1.0 / massA + 1.0 / massB);
1910
-
1907
+ float j = -(1.0 + e) * velAlongNormal / (1.0/massA + 1.0/massB);
1911
1908
  collision_vel -= (j * collision.normal) / massA;
1912
1909
 
1913
- // Friction - conservative
1914
1910
  if (friction > 0.0) {
1915
1911
  vec2 tangent = relativeVel - collision.normal * dot(relativeVel, collision.normal);
1916
1912
  float tLen = length(tangent);
1917
- if (tLen > EPSILON) {
1913
+ if (tLen > 0.01) {
1918
1914
  tangent = normalize(tangent);
1919
1915
  float vt = dot(relativeVel, tangent);
1920
- float jt = -vt * friction / (1.0 / massA + 1.0 / massB);
1916
+ float jt = -vt * friction * 0.5;
1921
1917
  float maxJt = abs(j) * friction;
1922
1918
  jt = clamp(jt, -maxJt, maxJt);
1923
1919
  collision_vel -= (jt * tangent) / massA;
@@ -1925,19 +1921,13 @@ void main() {
1925
1921
  }
1926
1922
  }
1927
1923
 
1928
- // Position correction - ACCUMULATED + rectangle-tuned values
1929
- const float slop = 0.025; // Increased to reduce micro-corrections on flat edges
1930
- const float percent = 0.75; // Stronger push to separate cleanly
1924
+ // Position correction - conservative for stability
1925
+ const float slop = 0.045;
1926
+ const float percent = 0.62;
1931
1927
 
1932
1928
  if (collision.penetration > slop) {
1933
1929
  float totalMass = massA + massB;
1934
1930
  vec2 correction = collision.normal * (collision.penetration - slop) * percent * (massB / totalMass);
1935
-
1936
- // Force correction direction away from the other object
1937
- if (dot(collision.normal, other.position - selfNew.position) < 0.0) {
1938
- correction = -correction;
1939
- }
1940
-
1941
1931
  final_pos -= correction;
1942
1932
  }
1943
1933
  }
@@ -1946,10 +1936,10 @@ void main() {
1946
1936
  if (had_collision) {
1947
1937
  new_vel = sanitizeVec2(collision_vel);
1948
1938
  }
1949
- new_pos = sanitizeVec2(final_pos); // Apply all corrections at once
1939
+ new_pos = sanitizeVec2(final_pos);
1950
1940
 
1951
1941
  // ========================================================================
1952
- // REST OF CODE(boundaries, final write, etc.)
1942
+ // REST OF CODE (age contacts, final sanity, write output)
1953
1943
  // ========================================================================
1954
1944
 
1955
1945
  // Age out old contacts for this object
@@ -1961,20 +1951,14 @@ void main() {
1961
1951
  new_pos = sanitizeVec2(new_pos);
1962
1952
  new_vel = sanitizeVec2(new_vel);
1963
1953
 
1964
- // ========================================================================
1965
- // FINAL SANITY CHECKS
1966
- // ========================================================================
1967
-
1968
- // Ensure velocities aren't excessive
1954
+ // Final sanity checks
1969
1955
  float maxSpeed = 1000.0;
1970
1956
  float currentSpeed = length(new_vel);
1971
1957
  if (currentSpeed > maxSpeed) {
1972
1958
  new_vel = normalize(new_vel) * maxSpeed;
1973
1959
  }
1974
1960
 
1975
- // ========================================================================
1976
- // WRITE UPDATED OBJECT STATE
1977
- // ========================================================================
1961
+ // Write updated object state
1978
1962
  objectsOut[gid].position = new_pos;
1979
1963
  objectsOut[gid].velocity = new_vel;
1980
1964
  objectsOut[gid].mass = mass;
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hyperstellar
3
- Version: 0.1.65
3
+ Version: 0.1.67
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.65"
7
+ version = "0.1.67"
8
8
  description = "GPU-accelerated physics simulation engine"
9
9
  readme = "README.md"
10
10
  authors = [{name = "Aiden Jabari", email = "Jabariaiden15@email.com"}]
@@ -63,6 +63,8 @@ where = ["hyperstellar/src"]
63
63
 
64
64
 
65
65
 
66
+
67
+
66
68
 
67
69
 
68
70
 
File without changes
File without changes
File without changes