diff --git a/src/microbe_stage/compound_cloud_system.cpp b/src/microbe_stage/compound_cloud_system.cpp index 49481653b09..03781591a4c 100644 --- a/src/microbe_stage/compound_cloud_system.cpp +++ b/src/microbe_stage/compound_cloud_system.cpp @@ -159,13 +159,12 @@ void if(x >= m_density1.size() || y >= m_density1[0].size()) throw std::runtime_error( "CompoundCloudComponent coordinates out of range"); - if(compound != NULL_COMPOUND) { - switch(getSlotForCompound(compound)) { - case SLOT::FIRST: m_density1[x][y] += dens; break; - case SLOT::SECOND: m_density2[x][y] += dens; break; - case SLOT::THIRD: m_density3[x][y] += dens; break; - case SLOT::FOURTH: m_density4[x][y] += dens; break; - } + + switch(getSlotForCompound(compound)) { + case SLOT::FIRST: m_density1[x][y] += dens; break; + case SLOT::SECOND: m_density2[x][y] += dens; break; + case SLOT::THIRD: m_density3[x][y] += dens; break; + case SLOT::FOURTH: m_density4[x][y] += dens; break; } } @@ -175,41 +174,39 @@ int size_t y, float rate) { - if(compound != NULL_COMPOUND) { - switch(getSlotForCompound(compound)) { - case SLOT::FIRST: { - int amountToGive = static_cast(m_density1[x][y] * rate); - m_density1[x][y] -= amountToGive; - if(m_density1[x][y] < 1) - m_density1[x][y] = 0; - - return amountToGive; - } - case SLOT::SECOND: { - int amountToGive = static_cast(m_density2[x][y] * rate); - m_density2[x][y] -= amountToGive; - if(m_density2[x][y] < 1) - m_density2[x][y] = 0; + switch(getSlotForCompound(compound)) { + case SLOT::FIRST: { + int amountToGive = static_cast(m_density1[x][y] * rate); + m_density1[x][y] -= amountToGive; + if(m_density1[x][y] < 1) + m_density1[x][y] = 0; + + return amountToGive; + } + case SLOT::SECOND: { + int amountToGive = static_cast(m_density2[x][y] * rate); + m_density2[x][y] -= amountToGive; + if(m_density2[x][y] < 1) + m_density2[x][y] = 0; - return amountToGive; - } - case SLOT::THIRD: { - int amountToGive = static_cast(m_density3[x][y] * rate); - m_density3[x][y] -= amountToGive; - if(m_density3[x][y] < 1) - m_density3[x][y] = 0; + return amountToGive; + } + case SLOT::THIRD: { + int amountToGive = static_cast(m_density3[x][y] * rate); + m_density3[x][y] -= amountToGive; + if(m_density3[x][y] < 1) + m_density3[x][y] = 0; - return amountToGive; - } - case SLOT::FOURTH: { - int amountToGive = static_cast(m_density4[x][y] * rate); - m_density4[x][y] -= amountToGive; - if(m_density4[x][y] < 1) - m_density4[x][y] = 0; + return amountToGive; + } + case SLOT::FOURTH: { + int amountToGive = static_cast(m_density4[x][y] * rate); + m_density4[x][y] -= amountToGive; + if(m_density4[x][y] < 1) + m_density4[x][y] = 0; - return amountToGive; - } - } + return amountToGive; + } } LEVIATHAN_ASSERT(false, "Shouldn't get here"); @@ -222,26 +219,25 @@ int size_t y, float rate) { - if(compound != NULL_COMPOUND) { - switch(getSlotForCompound(compound)) { - case SLOT::FIRST: { - int amountToGive = static_cast(m_density1[x][y] * rate); - return amountToGive; - } - case SLOT::SECOND: { - int amountToGive = static_cast(m_density2[x][y] * rate); - return amountToGive; - } - case SLOT::THIRD: { - int amountToGive = static_cast(m_density3[x][y] * rate); - return amountToGive; - } - case SLOT::FOURTH: { - int amountToGive = static_cast(m_density4[x][y] * rate); - return amountToGive; - } - } + switch(getSlotForCompound(compound)) { + case SLOT::FIRST: { + int amountToGive = static_cast(m_density1[x][y] * rate); + return amountToGive; + } + case SLOT::SECOND: { + int amountToGive = static_cast(m_density2[x][y] * rate); + return amountToGive; + } + case SLOT::THIRD: { + int amountToGive = static_cast(m_density3[x][y] * rate); + return amountToGive; + } + case SLOT::FOURTH: { + int amountToGive = static_cast(m_density4[x][y] * rate); + return amountToGive; } + } + LEVIATHAN_ASSERT(false, "Shouldn't get here"); return -1; } @@ -435,7 +431,6 @@ void doSpawnCycle(world, Float3(0, 0, 0)); } -//! \brief Places specified amount of compound at position bool CompoundCloudSystem::addCloud(CompoundId compound, float density, @@ -472,7 +467,6 @@ bool return false; } -//! \param rate should be less than one. float CompoundCloudSystem::takeCompound(CompoundId compound, const Float3& worldPosition, @@ -507,7 +501,6 @@ float return 0; } -//! \param rate should be less than one. float CompoundCloudSystem::amountAvailable(CompoundId compound, const Float3& worldPosition, @@ -1022,6 +1015,8 @@ void // The perlin noise texture needs to be tileable. We can't do tricks with // the cloud's position + // Even though we ask for the RGBA format the actual order of pixels when + // locked for writing is something completely different cloud.m_texture = Ogre::TextureManager::getSingleton().createManual( cloud.m_textureName, "Generated", Ogre::TEX_TYPE_2D, CLOUD_SIMULATION_WIDTH, CLOUD_SIMULATION_HEIGHT, 0, Ogre::PF_BYTE_RGBA, @@ -1150,16 +1145,36 @@ void // This is probably branch predictor friendly to move each bunch of pixels // separately - // First channel - if(cloud.m_compoundId1 != NULL_COMPOUND) - fillCloudChannel(cloud.m_density1, 0, rowBytes, pDest); - // Second + // Due to Ogre making the pixelbox lock however it wants the order is + // actually: Ogre::PF_A8R8G8B8 + if(pixelBox.format != Ogre::PF_A8R8G8B8) { + LOG_INFO( + "Pixel format: " + Ogre::PixelUtil::getFormatName(pixelBox.format)); + LEVIATHAN_ASSERT(false, + "Ogre created texture write lock with unexpected pixel order"); + } + + // Even with that pixel format the actual channel indexes are: + // so PF_B8G8R8A8 for some reason + // R - 2 + // G - 1 + // B - 0 + // A - 3 + + if(cloud.m_compoundId1 == NULL_COMPOUND) + LEVIATHAN_ASSERT(false, "cloud with not even the first compound"); + + // First density. R goes to channel 2 (see above for the mapping) + fillCloudChannel(cloud.m_density1, 2, rowBytes, pDest); + + // Second. G - 1 if(cloud.m_compoundId2 != NULL_COMPOUND) fillCloudChannel(cloud.m_density2, 1, rowBytes, pDest); - // Etc. + // Etc. B - 0 if(cloud.m_compoundId3 != NULL_COMPOUND) - fillCloudChannel(cloud.m_density3, 2, rowBytes, pDest); + fillCloudChannel(cloud.m_density3, 0, rowBytes, pDest); + // A - 3 if(cloud.m_compoundId4 != NULL_COMPOUND) fillCloudChannel(cloud.m_density4, 3, rowBytes, pDest); diff --git a/src/microbe_stage/compound_cloud_system.h b/src/microbe_stage/compound_cloud_system.h index d132c5f6ac5..4aa8a187231 100644 --- a/src/microbe_stage/compound_cloud_system.h +++ b/src/microbe_stage/compound_cloud_system.h @@ -315,10 +315,10 @@ class CompoundCloudComponent : public Leviathan::Component { //! The color of the compound cloud. //! Every used channel must have alpha of 1. The others have alpha 0 so that //! they don't need to be worried about affecting the resulting colours - Ogre::Vector4 m_color1; - Ogre::Vector4 m_color2; - Ogre::Vector4 m_color3; - Ogre::Vector4 m_color4; + Ogre::Vector4 m_color1 = Ogre::Vector4(0, 0, 0, 0); + Ogre::Vector4 m_color2 = Ogre::Vector4(0, 0, 0, 0); + Ogre::Vector4 m_color3 = Ogre::Vector4(0, 0, 0, 0); + Ogre::Vector4 m_color4 = Ogre::Vector4(0, 0, 0, 0); //! \brief The compound id. //! \note NULL_COMPOUND means that this cloud doesn't have that slot filled diff --git a/test/test_clouds.cpp b/test/test_clouds.cpp index 529fa4de049..971d7921a98 100644 --- a/test/test_clouds.cpp +++ b/test/test_clouds.cpp @@ -533,8 +533,6 @@ TEST_CASE_METHOD(CloudManagerTestsFixture, multiCloudPositionCheckHelper( clouds, playerPos->Members._Position, cloudFirstTypes); - // SECTION("Moving CLOUD_WIDTH/2 units") {} - SECTION("Moving 1000 units") { constexpr auto PLAYER_MOVE_AMOUNT = 1000; @@ -544,6 +542,84 @@ TEST_CASE_METHOD(CloudManagerTestsFixture, multiCloudPositionCheckHelper( clouds, playerPos->Members._Position, cloudFirstTypes); } +} + +TEST_CASE_METHOD(CloudManagerTestsFixture, + "Cloud manager puts spawned cloud in right entity with 5 compound types", + "[microbe]") +{ + // This test assumes + static_assert(CLOUDS_IN_ONE == 4, "this test assumes this"); + + const std::vector types{ + Compound{1, "a", true, true, false, Ogre::ColourValue(0, 1, 2, 1)}, + Compound{2, "b", true, true, false, Ogre::ColourValue(3, 4, 5, 1)}, + Compound{3, "c", true, true, false, Ogre::ColourValue(6, 7, 8, 1)}, + Compound{4, "d", true, true, false, Ogre::ColourValue(9, 10, 11, 1)}, + Compound{5, "e", true, true, false, Ogre::ColourValue(12, 13, 14, 1)}}; + + std::array cloudFirstTypes; + cloudFirstTypes[0] = types[0].id; + cloudFirstTypes[1] = types[4].id; + + setCloudsAndRunInitial(types); + + // Find the cloud entities + const auto clouds = findClouds(); + + CHECK(clouds.size() == 18); + + CompoundCloudComponent* cloudGroup1AtOrigin = nullptr; + CompoundCloudComponent* cloudGroup2AtOrigin = nullptr; + + for(auto* cloud : clouds) { + + if(cloud->getPosition() != Float3(0, 0, 0)) + continue; + + if(cloudFirstTypes[0] == cloud->getCompoundId1()) { + + CHECK(!cloudGroup1AtOrigin); + cloudGroup1AtOrigin = cloud; + + } else if(cloudFirstTypes[1] == cloud->getCompoundId1()) { + + CHECK(!cloudGroup2AtOrigin); + cloudGroup2AtOrigin = cloud; + } + } + + REQUIRE(cloudGroup1AtOrigin); + REQUIRE(cloudGroup2AtOrigin); + + const auto centerCoords = CompoundCloudSystem::convertWorldToCloudLocal( + Float3(0, 0, 0), Float3(0, 0, 0)); + + // Spawn clouds one by one and make sure they went to the right place + world.GetCompoundCloudSystem().addCloud(3, 10, Float3(0, 0, 0)); + + CHECK(cloudGroup1AtOrigin->amountAvailable(3, std::get<0>(centerCoords), + std::get<1>(centerCoords), 1) == 10); + + + world.GetCompoundCloudSystem().addCloud(4, 12, Float3(0, 0, 0)); + + CHECK(cloudGroup1AtOrigin->amountAvailable(4, std::get<0>(centerCoords), + std::get<1>(centerCoords), 1) == 12); + + world.GetCompoundCloudSystem().addCloud(1, 13, Float3(0, 0, 0)); + + CHECK(cloudGroup1AtOrigin->amountAvailable(1, std::get<0>(centerCoords), + std::get<1>(centerCoords), 1) == 13); + + world.GetCompoundCloudSystem().addCloud(2, 14, Float3(0, 0, 0)); + + CHECK(cloudGroup1AtOrigin->amountAvailable(2, std::get<0>(centerCoords), + std::get<1>(centerCoords), 1) == 14); + + // Second group + world.GetCompoundCloudSystem().addCloud(5, 15, Float3(0, 0, 0)); - // SECTION("Moving CLOUD_WIDTH * 1.5 units") {} + CHECK(cloudGroup2AtOrigin->amountAvailable(5, std::get<0>(centerCoords), + std::get<1>(centerCoords), 1) == 15); }