@@ -329,6 +329,17 @@ class BenchmarkTumbler : public Sample
329329 polygon = b2MakeOffsetBox ( 10 .0f , 0 .5f , { 0 .0f , -10 .0f }, b2Rot_identity );
330330 b2CreatePolygonShape ( bodyId, &shapeDef, &polygon );
331331
332+ shapeDef.customColor = b2_colorBlueViolet;
333+ b2Circle circle = { { 5 .0f , 5 .0f }, 1 .0f };
334+ b2CreateCircleShape ( bodyId, &shapeDef, &circle );
335+ circle = { { 5 .0f , -5 .0f }, 1 .0f };
336+ b2CreateCircleShape ( bodyId, &shapeDef, &circle );
337+ circle = { { -5 .0f , -5 .0f }, 1 .0f };
338+ b2CreateCircleShape ( bodyId, &shapeDef, &circle );
339+ circle = { { -5 .0f , 5 .0f }, 1 .0f };
340+ b2CreateCircleShape ( bodyId, &shapeDef, &circle );
341+
342+
332343 // m_motorSpeed = 9.0f;
333344 m_motorSpeed = 25 .0f ;
334345
@@ -1436,8 +1447,8 @@ class BenchmarkCompound : public Sample
14361447 b2BodyDef bodyDef = b2DefaultBodyDef ();
14371448 bodyDef.type = b2_dynamicBody;
14381449 // defer mass properties to avoid n-squared mass computations
1439- bodyDef.automaticMass = false ;
14401450 b2ShapeDef shapeDef = b2DefaultShapeDef ();
1451+ shapeDef.updateBodyMass = false ;
14411452
14421453 for ( int m = 0 ; m < count; ++m )
14431454 {
@@ -1498,13 +1509,14 @@ class BenchmarkKinematic : public Sample
14981509 b2BodyDef bodyDef = b2DefaultBodyDef ();
14991510 bodyDef.type = b2_kinematicBody;
15001511 bodyDef.angularVelocity = 1 .0f ;
1501- // defer mass properties to avoid n-squared mass computations
1502- bodyDef.automaticMass = false ;
15031512
15041513 b2ShapeDef shapeDef = b2DefaultShapeDef ();
15051514 shapeDef.filter .categoryBits = 1 ;
15061515 shapeDef.filter .maskBits = 2 ;
15071516
1517+ // defer mass properties to avoid n-squared mass computations
1518+ shapeDef.updateBodyMass = false ;
1519+
15081520 b2BodyId bodyId = b2CreateBody ( m_worldId, &bodyDef );
15091521
15101522 for ( int i = -span; i < span; ++i )
@@ -1529,3 +1541,212 @@ class BenchmarkKinematic : public Sample
15291541};
15301542
15311543static int sampleKinematic = RegisterSample( " Benchmark" , " Kinematic" , BenchmarkKinematic::Create );
1544+
1545+ #if 1
1546+
1547+ enum QueryType
1548+ {
1549+ e_rayCast,
1550+ e_shapeCast,
1551+ e_overlap,
1552+ };
1553+
1554+ class BenchmarkCast : public Sample
1555+ {
1556+ public:
1557+ explicit BenchmarkCast ( Settings& settings )
1558+ : Sample( settings )
1559+ {
1560+ if ( settings.restart == false )
1561+ {
1562+ g_camera.m_center = { 500 .0f , 500 .0f };
1563+ g_camera.m_zoom = 25 .0f * 21 .0f ;
1564+ }
1565+
1566+ m_queryType = e_rayCast;
1567+ m_ratio = 5 .0f ;
1568+ m_grid = 1 .0f ;
1569+ m_fill = 0 .1f ;
1570+ m_rowCount = g_sampleDebug ? 100 : 1000 ;
1571+ m_columnCount = g_sampleDebug ? 100 : 1000 ;
1572+ m_categoryBits = true ;
1573+
1574+ BuildScene ();
1575+ }
1576+
1577+ void BuildScene ()
1578+ {
1579+ g_seed = 1234 ;
1580+ b2DestroyWorld ( m_worldId );
1581+ b2WorldDef worldDef = b2DefaultWorldDef ();
1582+ m_worldId = b2CreateWorld ( &worldDef );
1583+
1584+ b2BodyDef bodyDef = b2DefaultBodyDef ();
1585+ b2ShapeDef shapeDef = b2DefaultShapeDef ();
1586+
1587+ float y = 0 .0f ;
1588+
1589+ for ( int i = 0 ; i < m_rowCount; ++i )
1590+ {
1591+ float x = 0 .0f ;
1592+
1593+ for ( int j = 0 ; j < m_columnCount; ++j )
1594+ {
1595+ float fillTest = RandomFloat ( 0 .0f , 1 .0f );
1596+ if ( fillTest <= m_fill )
1597+ {
1598+ bodyDef.position = { x, y };
1599+ b2BodyId bodyId = b2CreateBody ( m_worldId, &bodyDef );
1600+
1601+ float ratio = RandomFloat ( 1 .0f , m_ratio );
1602+ float halfWidth = RandomFloat ( 0 .05f , 0 .25f );
1603+
1604+ b2Polygon box;
1605+ if ( RandomFloat () > 0 .0f )
1606+ {
1607+ box = b2MakeBox ( ratio * halfWidth, halfWidth );
1608+ }
1609+ else
1610+ {
1611+ box = b2MakeBox ( halfWidth, ratio * halfWidth );
1612+ }
1613+
1614+ int category = RandomInt ( 1 , 3 );
1615+ shapeDef.filter .categoryBits = category;
1616+ if ( category == 1 )
1617+ {
1618+ shapeDef.customColor = b2_colorBox2DBlue;
1619+ }
1620+ else if ( category == 2 )
1621+ {
1622+ shapeDef.customColor = b2_colorBox2DYellow;
1623+ }
1624+ else
1625+ {
1626+ shapeDef.customColor = b2_colorBox2DGreen;
1627+ }
1628+
1629+ b2CreatePolygonShape ( bodyId, &shapeDef, &box );
1630+ }
1631+
1632+ x += m_grid;
1633+ }
1634+
1635+ y += m_grid;
1636+ }
1637+ }
1638+
1639+ void UpdateUI () override
1640+ {
1641+ float height = 320 .0f ;
1642+ ImGui::SetNextWindowPos ( ImVec2 ( 10 .0f , g_camera.m_height - height - 50 .0f ), ImGuiCond_Once );
1643+ ImGui::SetNextWindowSize ( ImVec2 ( 200 .0f , height ) );
1644+
1645+ ImGui::Begin ( " Cast" , nullptr , ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize );
1646+
1647+ ImGui::PushItemWidth ( 100 .0f );
1648+
1649+ bool changed = false ;
1650+ if ( ImGui::SliderInt ( " rows" , &m_rowCount, 0 , 1000 , " %d" ) )
1651+ {
1652+ changed = true ;
1653+ }
1654+
1655+ if ( ImGui::SliderInt ( " columns" , &m_columnCount, 0 , 1000 , " %d" ) )
1656+ {
1657+ changed = true ;
1658+ }
1659+
1660+ if ( ImGui::SliderFloat ( " fill" , &m_fill, 0 .0f , 1 .0f , " %.2f" ) )
1661+ {
1662+ changed = true ;
1663+ }
1664+
1665+ if ( ImGui::SliderFloat ( " grid" , &m_grid, 0 .5f , 2 .0f , " %.2f" ) )
1666+ {
1667+ changed = true ;
1668+ }
1669+
1670+ if ( ImGui::SliderFloat ( " ratio" , &m_ratio, 1 .0f , 10 .0f , " %.2f" ) )
1671+ {
1672+ changed = true ;
1673+ }
1674+
1675+ if ( ImGui::Checkbox ( " categories" , &m_categoryBits) )
1676+ {
1677+ changed = true ;
1678+ }
1679+
1680+ const char * queryTypes[] = { " Ray Cast" , " Circle Cast" , " Overlap" };
1681+ int queryType = int ( m_queryType );
1682+ changed = changed || ImGui::Combo ( " Query" , &queryType, queryTypes, IM_ARRAYSIZE ( queryTypes ) );
1683+ m_queryType = QueryType ( queryType );
1684+
1685+ ImGui::PopItemWidth ();
1686+ ImGui::End ();
1687+
1688+ if ( changed )
1689+ {
1690+ BuildScene ();
1691+ }
1692+ }
1693+
1694+ void Step ( Settings& settings) override
1695+ {
1696+ Sample::Step ( settings );
1697+
1698+ int sampleCount = g_sampleDebug ? 10 : 1000 ;
1699+
1700+ float extent = m_rowCount * m_grid;
1701+ b2QueryFilter filter = b2DefaultQueryFilter ();
1702+ filter.maskBits = 1 ;
1703+ int hitCount = 0 ;
1704+ float ms = 0 .0f ;
1705+
1706+ if (m_queryType == e_rayCast)
1707+ {
1708+ b2Timer timer = b2CreateTimer ();
1709+
1710+ b2Vec2 rayStart = b2Vec2_zero;
1711+ b2Vec2 rayEnd = b2Vec2_zero;
1712+ for (int i = 0 ; i < sampleCount; ++i)
1713+ {
1714+ rayStart = RandomVec2 ( 0 .0f , extent );
1715+ rayEnd = RandomVec2 ( 0 .0f , extent );
1716+
1717+ b2RayResult result = b2World_CastRayClosest ( m_worldId, rayStart, b2Sub ( rayEnd, rayStart ), filter );
1718+ hitCount += result.hit ? 1 : 0 ;
1719+ }
1720+
1721+ ms = b2GetMilliseconds ( &timer );
1722+
1723+ g_draw.DrawSegment ( rayStart, rayEnd, b2_colorBeige );
1724+ }
1725+
1726+ g_draw.DrawString ( 5 , m_textLine, " hit count = %03d" , hitCount );
1727+ m_textLine += m_textIncrement;
1728+
1729+ g_draw.DrawString ( 5 , m_textLine, " ms = %.3f" ,ms );
1730+ m_textLine += m_textIncrement;
1731+ }
1732+
1733+ static Sample* Create ( Settings& settings )
1734+ {
1735+ return new BenchmarkCast ( settings );
1736+ }
1737+
1738+ QueryType m_queryType;
1739+
1740+ std::vector<b2Vec2> m_origins;
1741+ std::vector<b2Vec2> m_translations;
1742+
1743+ int m_rowCount, m_columnCount;
1744+ int m_updateType;
1745+ float m_fill;
1746+ float m_ratio;
1747+ float m_grid;
1748+ bool m_categoryBits;
1749+ };
1750+
1751+ static int sampleCast = RegisterSample( " Benchmark" , " Cast" , BenchmarkCast::Create );
1752+ #endif
0 commit comments