// Verify that BeginContact() and EndContact() are called for collisions // between particles. TEST_F(BodyContactTests, ParticleContactListener) { // Drop particle B on top of particle A. b2ParticleDef pd; pd.flags = b2_particleContactListenerParticle; pd.position.Set(0.0f, m_particleDiameter); pd.velocity.Set(0.0f, -m_particleDiameter); const int32 particleA = m_particleSystem->CreateParticle(pd); pd.position.Set(0.0f, m_particleDiameter * 3.0f); pd.velocity.Set(0.0f, m_particleDiameter * -2.0f); const int32 particleB = m_particleSystem->CreateParticle(pd); ParticleContactListener listener(m_particleSystem); m_world->SetContactListener(&listener); RunStep(60.0f, 2.0f); EXPECT_GT(listener.m_beginParticleContacts.size(), 0U); EXPECT_EQ(listener.m_endParticleContacts.size(), 0U); for (uint32 i = 0; i < listener.m_beginParticleContacts.size(); ++i) { b2ParticleContact contact = listener.m_beginParticleContacts[i]; EXPECT_TRUE(contact.indexA == particleA ? contact.indexB == particleB : contact.indexB == particleA); } // Push particleB away from particleA. b2Vec2* velocities = m_particleSystem->GetVelocityBuffer(); velocities[particleB].x = m_particleDiameter; velocities[particleB].y = 0.0f; listener.m_beginParticleContacts.clear(); RunStep(60.0f, 0.5f); EXPECT_EQ(listener.m_beginParticleContacts.size(), 0U); EXPECT_GT(listener.m_endParticleContacts.size(), 0U); }
// Verify that it's possible to enable / disable collisions between fixtures // and particles. TEST_F(BodyContactTests, EnableDisableFixtureParticleContactsWithContactFilter) { // Create a fixture to drop particles on to. b2Fixture* const groundFixture = CreateGroundBox(); // Create a particle above the ground and drop it. b2ParticleDef pd; pd.flags = b2_fixtureContactFilterParticle; pd.position.Set(0.0f, m_particleDiameter * 2.0f); pd.velocity.Set(0.0f, -m_particleDiameter); m_particleSystem->CreateParticle(pd); // Leave contacts enabled. ParticleContactDisabler contactDisabler; m_world->SetContactFilter(&contactDisabler); // Run the simulation and verify the particle is on top of the ground // fixture. RunStep(60.0f, 2.0f); EXPECT_GE(m_particleSystem->GetPositionBuffer()[0].y, groundFixture->GetAABB(0).upperBound.y); // Disable fixture / particle contacts. contactDisabler.m_enableFixtureParticleCollisions = false; // Run the simulation and verify the particle falls through the ground. RunStep(60.0f, 2.0f); EXPECT_LT(m_particleSystem->GetPositionBuffer()[0].y, groundFixture->GetAABB(0).upperBound.y); }
// Verify that it's possible to enable / disable collisions between particles. TEST_F(BodyContactTests, EnableDisableParticleContactsWithContactFilter) { m_world->SetGravity(b2Vec2_zero); // Through two particles horizontally at each other // (A moving right, B moving left). b2ParticleDef pd; pd.flags = b2_particleContactFilterParticle; pd.position.Set(-m_particleDiameter * 2.0f, 0.0f); pd.velocity.Set(m_particleDiameter, 0.0f); int32 particleIndexA = m_particleSystem->CreateParticle(pd); pd.flags = b2_particleContactFilterParticle; pd.position.Set(m_particleDiameter * 2.0f, 0.0f); pd.velocity.Set(-m_particleDiameter, 0.0f); int32 particleIndexB = m_particleSystem->CreateParticle(pd); // Leave contacts enabled. ParticleContactDisabler contactDisabler; m_world->SetContactFilter(&contactDisabler); // Run the simulation and verify that particles don't pass each other. RunStep(60.0f, 3.0f); // WARNING: This assumes particle indicies have not been reallocated during // the simulation. b2Vec2* positions = m_particleSystem->GetPositionBuffer(); b2Vec2* velocities = m_particleSystem->GetVelocityBuffer(); EXPECT_LT(positions[particleIndexA].x, positions[particleIndexB].x); EXPECT_LT(b2Abs(velocities[particleIndexA].x), m_particleDiameter); EXPECT_LT(b2Abs(velocities[particleIndexB].x), m_particleDiameter); // Disable particle / particle contacts. contactDisabler.m_enableParticleParticleCollisions = false; // Reset the positions and velocities of the particles. positions[particleIndexA].Set(-m_particleDiameter * 2.0f, 0.0f); velocities[particleIndexA].Set(m_particleDiameter, 0.0f); positions[particleIndexB].Set(m_particleDiameter * 2.0f, 0.0f); velocities[particleIndexB].Set(-m_particleDiameter, 0.0f); // Run the simulation and verify that particles now pass each other (i.e // they no longer collide). RunStep(60.0f, 3.0f); positions = m_particleSystem->GetPositionBuffer(); velocities = m_particleSystem->GetVelocityBuffer(); EXPECT_GT(positions[particleIndexA].x, positions[particleIndexB].x); EXPECT_FLOAT_EQ(velocities[particleIndexA].x, m_particleDiameter); EXPECT_FLOAT_EQ(velocities[particleIndexB].x, -m_particleDiameter); }
// Verify that it's possible to detect collisions between TEST_F(BodyContactTests, ParticleParticleContactFilter) { // Drop particle B on top of particle A. b2ParticleDef pd; pd.flags = b2_particleContactFilterParticle; pd.position.Set(0.0f, m_particleDiameter); pd.velocity.Set(0.0f, -m_particleDiameter); const int32 particleA = m_particleSystem->CreateParticle(pd); pd.position.Set(0.0f, m_particleDiameter * 3.0f); pd.velocity.Set(0.0f, m_particleDiameter * -2.0f); const int32 particleB = m_particleSystem->CreateParticle(pd); ParticleContactTracker tracker(m_particleSystem); m_world->SetContactFilter(&tracker); RunStep(60.0f, 2.0f); EXPECT_EQ(tracker.m_fixtureParticleContacts.size(), 0U); EXPECT_GT(tracker.m_particleContacts.size(), 0U); for (uint32 i = 0; i < tracker.m_particleContacts.size(); ++i) { const ParticleContactTracker::ParticleContact contact = tracker.m_particleContacts[i]; EXPECT_TRUE(contact.first == particleA || contact.first == particleB); EXPECT_TRUE(contact.first == particleA ? contact.second == particleB : contact.second == particleA); } }
void CNetServerWorker::Run() { // The script runtime uses the profiler and therefore the thread must be registered before the runtime is created g_Profiler2.RegisterCurrentThread("Net server"); // To avoid the need for JS_SetContextThread, we create and use and destroy // the script interface entirely within this network thread m_ScriptInterface = new ScriptInterface("Engine", "Net server", ScriptInterface::CreateRuntime(g_ScriptRuntime)); m_GameAttributes.set(m_ScriptInterface->GetJSRuntime(), JS::UndefinedValue()); while (true) { if (!RunStep()) break; // Implement autostart mode if (m_State == SERVER_STATE_PREGAME && (int)m_PlayerAssignments.size() == m_AutostartPlayers) StartGame(); // Update profiler stats m_Stats->LatchHostState(m_Host); } // Clear roots before deleting their context m_GameAttributes.clear(); m_SavedCommands.clear(); SAFE_DELETE(m_ScriptInterface); }
// Verify that BeginContact() and EndContact() are called for collisions // between fixtures and particles. TEST_F(BodyContactTests, ParticleFixtureContactListener) { // Create a fixture to drop particles on to. b2Fixture* const groundFixture = CreateGroundBox(); // Create a particle above the ground and drop it. b2ParticleDef pd; pd.flags = b2_fixtureContactListenerParticle; pd.position.Set(0.0f, m_particleDiameter * 2.0f); pd.velocity.Set(0.0f, -m_particleDiameter); const int32 particleIndex = m_particleSystem->CreateParticle(pd); // Listen for particle / fixture contacts. ParticleContactListener tracker(m_particleSystem); m_world->SetContactListener(&tracker); // Run the simulation and verify that the particle contacts with the // fixture. RunStep(60.0f, 3.0f); EXPECT_EQ(tracker.m_beginFixtureContacts.size(), 1U); EXPECT_EQ(tracker.m_endFixtureContacts.size(), 0U); for (uint32 i = 0; i < tracker.m_beginFixtureContacts.size(); ++i) { const b2ParticleBodyContact contact = tracker.m_beginFixtureContacts[i]; EXPECT_EQ(contact.index, particleIndex); EXPECT_EQ(contact.fixture, groundFixture); } tracker.m_beginFixtureContacts.clear(); // Throw the particle above the ground fixture and verify it's no longer // touching. m_particleSystem->GetVelocityBuffer()[particleIndex].y = m_particleDiameter * 2.0f; RunStep(60.0f, 0.5f); EXPECT_EQ(tracker.m_beginFixtureContacts.size(), 0U); EXPECT_EQ(tracker.m_endFixtureContacts.size(), 1U); for (uint32 i = 0; i < tracker.m_endFixtureContacts.size(); ++i) { const FixtureParticleContact contact = tracker.m_endFixtureContacts[i]; EXPECT_EQ(contact.first, groundFixture); EXPECT_EQ(contact.second, particleIndex); } }
void dgWorld::UpdateAsync (dgFloat32 timestep) { m_concurrentUpdate = true; Sync (); m_savetimestep = timestep; #ifdef DG_USE_THREAD_EMULATION dgFloatExceptions exception; dgSetPrecisionDouble precision; RunStep (); #else // execute one update, but do not wait for the update to finish, instead return immediately to the caller Tick(); #endif }
void dgWorld::Update (dgFloat32 timestep) { m_concurrentUpdate = false; m_savetimestep = timestep; #ifdef DG_USE_THREAD_EMULATION dgFloatExceptions exception; dgSetPrecisionDouble precision; RunStep (); #else // runs the update in a separate thread and wait until the update is completed before it returns. // this will run well on single core systems, since the two thread are mutually exclusive Tick(); SuspendExecution(dgWorld::m_mutex); #endif }
// Verify that it's possible to detect particle / body collisions using // a contact filter. TEST_F(BodyContactTests, FixtureParticleContactFilter) { // Create the ground. b2Fixture* const groundFixture = CreateGroundBox(); { // Create a particle above the ground and slightly to the left of the // particle with the contact filter enabled. b2ParticleDef pd; pd.position.Set(2.0f * m_particleDiameter, 2.0f * m_particleDiameter); pd.position.Set(0.0f, -m_particleDiameter); m_particleSystem->CreateParticle(pd); } // Create a particle above the ground and drop it. int32 contactFilterParticleIndex; { b2ParticleDef pd; pd.flags = b2_fixtureContactFilterParticle; pd.position.Set(0.0f, 2.0f * m_particleDiameter); pd.position.Set(0.0f, -m_particleDiameter); // WARNING: This assumes that this particle index will not change // between simulation steps. contactFilterParticleIndex = m_particleSystem->CreateParticle(pd); } // Set the tracker as a contact listener. ParticleContactTracker tracker(m_particleSystem); m_world->SetContactFilter(&tracker); RunStep(60.0f, 1.0f); EXPECT_EQ(tracker.m_particleContacts.size(), 0U); EXPECT_GT(tracker.m_fixtureParticleContacts.size(), 0U); for (uint32 i = 0; i < tracker.m_fixtureParticleContacts.size(); ++i) { const FixtureParticleContact contact = tracker.m_fixtureParticleContacts[i]; // Verify the contact is with the ground fixture. EXPECT_EQ(contact.first, groundFixture); // Since there is only one particle, the index will always be zero. EXPECT_EQ(contact.second, contactFilterParticleIndex); } }
void dgWorld::TickCallback (dgInt32 threadID) { RunStep (); }