@@ -1422,6 +1422,211 @@ static void make_weak_uuid_table(lua_State *L)
14221422 lua_setmetatable (L, -2 );
14231423}
14241424
1425+ // ServerLua: callable quaternion module
1426+ static int quaternion_call (lua_State *L)
1427+ {
1428+ luaL_checktype (L, 1 , LUA_TTABLE);
1429+ lua_remove (L, 1 );
1430+ return lsl_quaternion_ctor (L);
1431+ }
1432+
1433+ static inline float quaternion_dot (const float * a, const float * b) {
1434+ return ((a)[0 ] * (b)[0 ] + (a)[1 ] * (b)[1 ] + (a)[2 ] * (b)[2 ] + (a)[3 ] * (b)[3 ]);
1435+ }
1436+
1437+ static int lua_quaternion_normalize (lua_State *L)
1438+ {
1439+ const float * quat = luaSL_checkquaternion (L, 1 );
1440+ float invNorm = 1 .0f / sqrtf (quaternion_dot (quat, quat));
1441+ luaSL_pushquaternion (L, quat[0 ] * invNorm, quat[1 ] * invNorm, quat[2 ] * invNorm, quat[3 ] * invNorm);
1442+ return 1 ;
1443+ }
1444+
1445+ static int lua_quaternion_magnitude (lua_State *L)
1446+ {
1447+ const float * quat = luaSL_checkquaternion (L, 1 );
1448+ lua_pushnumber (L, sqrtf (quaternion_dot (quat, quat)));
1449+ return 1 ;
1450+ }
1451+
1452+
1453+ static int lua_quaternion_dot (lua_State *L)
1454+ {
1455+ const float * a = luaSL_checkquaternion (L, 1 );
1456+ const float * b = luaSL_checkquaternion (L, 2 );
1457+ lua_pushnumber (L, quaternion_dot (a, b));
1458+ return 1 ;
1459+ }
1460+
1461+ static int lua_quaternion_slerp (lua_State *L)
1462+ {
1463+ const float * a = luaSL_checkquaternion (L, 1 );
1464+ const float * b = luaSL_checkquaternion (L, 2 );
1465+ const float u = luaL_checknumber (L, 3 );
1466+
1467+ float cos_t = quaternion_dot (a, b);
1468+
1469+ bool bflip = false ;
1470+ if (cos_t < 0 .0f )
1471+ {
1472+ cos_t = -cos_t ;
1473+ bflip = true ;
1474+ }
1475+
1476+ float alpha;
1477+ float beta;
1478+ if (1 .0f - cos_t < 0 .00001f )
1479+ {
1480+ beta = 1 .0f - u;
1481+ alpha = u;
1482+ }
1483+ else
1484+ {
1485+ float theta = acosf (cos_t );
1486+ float sin_t = sinf (theta);
1487+ beta = sinf (theta - u*theta) / sin_t ;
1488+ alpha = sinf (u*theta) / sin_t ;
1489+ }
1490+
1491+ if (bflip)
1492+ {
1493+ beta = -beta;
1494+ }
1495+
1496+ luaSL_pushquaternion (L,
1497+ beta*a[0 ] + alpha*b[0 ],
1498+ beta*a[1 ] + alpha*b[1 ],
1499+ beta*a[2 ] + alpha*b[2 ],
1500+ beta*a[3 ] + alpha*b[3 ]);
1501+ return 1 ;
1502+ }
1503+
1504+ static int lua_quaternion_conjugate (lua_State *L)
1505+ {
1506+ const float * quat = luaSL_checkquaternion (L, 1 );
1507+ luaSL_pushquaternion (L, -quat[0 ], -quat[1 ], -quat[2 ], quat[3 ]);
1508+ return 1 ;
1509+ }
1510+
1511+
1512+ static inline void push_rotated_vector (lua_State *L, const float * vec) {
1513+ const float * quat = luaSL_checkquaternion (L, 1 );
1514+ float res[3 ] = {0 .0f };
1515+ rot_vec (vec, quat, res);
1516+ float invSqrt = 1 .0f / sqrtf (res[0 ] * res[0 ] + res[1 ] * res[1 ] + res[2 ] * res[2 ]);
1517+ lua_pushvector (L, res[0 ] * invSqrt, res[1 ] * invSqrt, res[2 ] * invSqrt);
1518+ }
1519+
1520+ static int lua_quaternion_tofwd (lua_State *L)
1521+ {
1522+ const float vec[3 ] = {1 .0f , 0 .0f , 0 .0f };
1523+ push_rotated_vector (L, vec);
1524+ return 1 ;
1525+ }
1526+
1527+ static int lua_quaternion_toleft (lua_State *L)
1528+ {
1529+ const float vec[3 ] = {0 .0f , 1 .0f , 0 .0f };
1530+ push_rotated_vector (L, vec);
1531+ return 1 ;
1532+ }
1533+
1534+ static int lua_quaternion_toup (lua_State *L)
1535+ {
1536+ const float vec[3 ] = {0 .0f , 0 .0f , 1 .0f };
1537+ push_rotated_vector (L, vec);
1538+ return 1 ;
1539+ }
1540+
1541+ static const luaL_Reg quaternionlib[] = {
1542+ {" create" , lsl_quaternion_ctor},
1543+ {" normalize" , lua_quaternion_normalize},
1544+ {" magnitude" , lua_quaternion_magnitude},
1545+ {" dot" , lua_quaternion_dot},
1546+ {" slerp" , lua_quaternion_slerp},
1547+ {" conjugate" , lua_quaternion_conjugate},
1548+ {" tofwd" , lua_quaternion_tofwd},
1549+ {" toleft" , lua_quaternion_toleft},
1550+ {" toup" , lua_quaternion_toup},
1551+ {NULL , NULL },
1552+ };
1553+
1554+ int luaopen_sl_quaternion (lua_State* L, const char * name)
1555+ {
1556+ [[maybe_unused]] int old_top = lua_gettop (L);
1557+ lua_newtable (L);
1558+ luaL_register (L, NULL , quaternionlib);
1559+
1560+ luaSL_pushquaternion (L, 0.0 , 0.0 , 0.0 , 1.0 );
1561+ lua_setfield (L, -2 , " identity" );
1562+
1563+ // ServerLua: `quaternion()` is an alias to `quaternion.create()`, so we need to add a metatable
1564+ // to the quaternion module which allows calling it.
1565+ lua_newtable (L);
1566+ lua_pushcfunction (L, quaternion_call, " __call" );
1567+ lua_setfield (L, -2 , " __call" );
1568+
1569+ // We need to override __iter so generalized iteration doesn't try to use __call.
1570+ lua_rawgetfield (L, LUA_BASEGLOBALSINDEX, " pairs" );
1571+ // This is confusing at first, but we want a unique function identity
1572+ // when this shows up anywhere other than globals, otherwise we can
1573+ // muck up Ares serialization.
1574+ luau_dupcclosure (L, -1 , " __iter" );
1575+ lua_replace (L, -2 );
1576+ lua_rawsetfield (L, -2 , " __iter" );
1577+
1578+ lua_setreadonly (L, -1 , true );
1579+ lua_setmetatable (L, -2 );
1580+
1581+ lua_setglobal (L, name);
1582+
1583+ LUAU_ASSERT (lua_gettop (L) == old_top);
1584+ return 1 ;
1585+ }
1586+
1587+ // ServerLua: callable uuid module
1588+ static int uuid_call (lua_State *L)
1589+ {
1590+ luaL_checktype (L, 1 , LUA_TTABLE);
1591+ lua_remove (L, 1 );
1592+ return lua_uuid_ctor (L);
1593+ }
1594+
1595+ static const luaL_Reg uuidlib[] = {
1596+ {" create" , lua_uuid_ctor},
1597+ {NULL , NULL },
1598+ };
1599+
1600+ int luaopen_sl_uuid (lua_State* L)
1601+ {
1602+ [[maybe_unused]] int old_top = lua_gettop (L);
1603+ lua_newtable (L);
1604+ luaL_register (L, NULL , uuidlib);
1605+
1606+ // ServerLua: `uuid()` is an alias to `uuid.create()`, so we need to add a metatable
1607+ // to the uuid module which allows calling it.
1608+ lua_newtable (L);
1609+ lua_pushcfunction (L, uuid_call, " __call" );
1610+ lua_setfield (L, -2 , " __call" );
1611+
1612+ // We need to override __iter so generalized iteration doesn't try to use __call.
1613+ lua_rawgetfield (L, LUA_BASEGLOBALSINDEX, " pairs" );
1614+ // This is confusing at first, but we want a unique function identity
1615+ // when this shows up anywhere other than globals, otherwise we can
1616+ // muck up Ares serialization.
1617+ luau_dupcclosure (L, -1 , " __iter" );
1618+ lua_replace (L, -2 );
1619+ lua_rawsetfield (L, -2 , " __iter" );
1620+
1621+ lua_setreadonly (L, -1 , true );
1622+ lua_setmetatable (L, -2 );
1623+
1624+ lua_setglobal (L, " uuid" );
1625+
1626+ LUAU_ASSERT (lua_gettop (L) == old_top);
1627+ return 1 ;
1628+ }
1629+
14251630int luaopen_sl (lua_State* L, int expose_internal_funcs)
14261631{
14271632 if (!LUAU_IS_SL_VM (L))
@@ -1432,23 +1637,14 @@ int luaopen_sl(lua_State* L, int expose_internal_funcs)
14321637 int top = lua_gettop (L);
14331638
14341639 // Load these into the global namespace
1435- lua_pushcfunction (L, lsl_quaternion_ctor, " quaternion" );
1436- luau_dupcclosure (L, -1 , " rotation" );
1437- // Alias it as "rotation"
1438- lua_setglobal (L, " rotation" );
1439- lua_setglobal (L, " quaternion" );
14401640
14411641 if (LUAU_IS_LSL_VM (L))
14421642 {
14431643 lua_pushcfunction (L, lsl_key_ctor, " uuid" );
1644+ luau_dupcclosure (L, -1 , " touuid" );
1645+ lua_setglobal (L, " touuid" );
1646+ lua_setglobal (L, " uuid" );
14441647 }
1445- else
1446- {
1447- lua_pushcfunction (L, lua_uuid_ctor, " uuid" );
1448- }
1449- luau_dupcclosure (L, -1 , " touuid" );
1450- lua_setglobal (L, " touuid" );
1451- lua_setglobal (L, " uuid" );
14521648
14531649 lua_pushcfunction (L, lsl_to_vector, " tovector" );
14541650 lua_setglobal (L, " tovector" );
@@ -1509,6 +1705,15 @@ int luaopen_sl(lua_State* L, int expose_internal_funcs)
15091705 lua_pop (L, 1 );
15101706 LUAU_ASSERT (lua_gettop (L) == top);
15111707
1708+ if (!LUAU_IS_LSL_VM (L))
1709+ {
1710+ // Create uuid module table
1711+ luaopen_sl_uuid (L);
1712+ LUAU_ASSERT (lua_gettop (L) == top);
1713+ lua_pushcfunction (L, lua_uuid_ctor, " touuid" );
1714+ lua_setglobal (L, " touuid" );
1715+ }
1716+
15121717 // ////
15131718 // / Quaternions
15141719 // ////
@@ -1555,6 +1760,11 @@ int luaopen_sl(lua_State* L, int expose_internal_funcs)
15551760 lua_pop (L, 1 );
15561761 LUAU_ASSERT (lua_gettop (L) == top);
15571762
1763+ // Create quaternion module table
1764+ luaopen_sl_quaternion (L, " quaternion" );
1765+ luaopen_sl_quaternion (L, " rotation" );
1766+ LUAU_ASSERT (lua_gettop (L) == top);
1767+
15581768 // ////
15591769 // / DetectedEvent
15601770 // ////
0 commit comments