Skip to content

Commit

Permalink
Wrote tests for initial cloud positioning by the cloud manager
Browse files Browse the repository at this point in the history
Includes a lot of supporting changes.
Also did some changes unrelated to the tests to the cloud code, like
undoing the variable I didn't like.

Contains a few changes that I started to make to the cloud
positioning, but I'll probably undo later.
  • Loading branch information
hhyyrylainen committed Feb 15, 2019
1 parent b92db01 commit 46d9232
Show file tree
Hide file tree
Showing 20 changed files with 357 additions and 621 deletions.
2 changes: 1 addition & 1 deletion SetupThrive.rb
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ def parseExtraArgs
leviathan = Leviathan.new(
# Use this if you always want the latest commit
# version: "develop",
version: "556a6584f4f74d2c16d85b85ba26281a88c02171",
version: "ebaf03d6086c5cac39b66a54093e3926e1c0c359",
# Doesn't actually work, but leviathan doesn't install with sudo by
# default, or install at all for that matter
noInstallSudo: true
Expand Down
25 changes: 20 additions & 5 deletions src/ThriveGame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,10 @@ void
netSettings.IsAuthoritative = true;
netSettings.DoInterpolation = true;

// TODO: switch to
// Leviathan::WorldNetworkSettings::GetSettingsForSinglePlayer() once we
// no longer do the interpolation once variable rate ticks are supported

LOG_INFO("ThriveGame: startNewGame: Creating new cellstage world");
m_impl->m_cellStage =
std::dynamic_pointer_cast<CellStageWorld>(engine->CreateWorld(
Expand Down Expand Up @@ -494,7 +498,8 @@ void
m_impl->m_microbeEditor =
std::dynamic_pointer_cast<MicrobeEditorWorld>(engine->CreateWorld(
window1, static_cast<int>(THRIVE_WORLD_TYPE::MICROBE_EDITOR),
createPhysicsMaterials(), netSettings));
createPhysicsMaterials(),
Leviathan::WorldNetworkSettings::GetSettingsForSinglePlayer()));
}

LEVIATHAN_ASSERT(
Expand Down Expand Up @@ -984,17 +989,27 @@ void
ThriveGame::Tick(int mspassed)
{}

void
ThriveGame::CustomizeEnginePostLoad()
bool
ThriveGame::createImpl()
{
Engine* engine = Engine::Get();

try {
m_impl = std::make_unique<Implementation>(*this);
} catch(const Leviathan::InvalidArgument& e) {

LOG_ERROR("ThriveGame: loading configuration data failed: ");
e.PrintToLog();
return false;
}

return true;
}

void
ThriveGame::CustomizeEnginePostLoad()
{
Engine* engine = Engine::Get();

if(!createImpl()) {
MarkAsClosing();
return;
}
Expand Down
8 changes: 8 additions & 0 deletions src/ThriveGame.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@

namespace thrive {

namespace test {
class TestThriveGame;
}

class CellStageWorld;

class ThriveNetHandler;
Expand All @@ -25,6 +29,7 @@ class PlayerMicrobeControl;
//! running the engine and the event loop
class ThriveGame : public Leviathan::ClientApplication, public ThriveCommon {
class Implementation;
friend test::TestThriveGame;

public:
ThriveGame();
Expand Down Expand Up @@ -150,6 +155,9 @@ class ThriveGame : public Leviathan::ClientApplication, public ThriveCommon {
void
_ShutdownApplicationPacketHandler() override;

bool
createImpl();

private:
std::unique_ptr<ThriveNetHandler> m_network;

Expand Down
7 changes: 7 additions & 0 deletions src/general/json_registry.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,13 @@
// Base class of things to register.
class RegistryType {
public:
RegistryType() {}

//! \brief Helper for derived test constructors
RegistryType(size_t id, const std::string& name) :
id(id), displayName(name), internalName(name)
{}

// Used to search by id.
size_t id = std::numeric_limits<size_t>::max(); // This would mean an error.

Expand Down
126 changes: 36 additions & 90 deletions src/microbe_stage/compound_cloud_system.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,11 @@ void
const auto meshName =
"CompoundCloudSystem_Plane_" + std::to_string(++CloudMeshNumberCounter);

// TODO: fix this in the engine to make this method simpler
// This crashes when used with RenderDoc and doesn't render anything
// m_planeMesh = Leviathan::GeometryHelpers::CreateXZPlane(
// meshName, CLOUD_WIDTH, CLOUD_HEIGHT);

// Create a background plane on which the fluid clouds will be drawn.
m_planeMesh = Ogre::MeshManager::getSingleton().createManual(
meshName, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
Expand Down Expand Up @@ -683,65 +688,29 @@ void
const Float3& playerPos)
{
// Initial spawning if everything is empty
int cloudTypesNum = m_cloudTypes.size();

if(m_managedClouds.empty()) {

LOG_INFO("CompoundCloudSystem doing initial spawning");

m_cloudGridCenter = Float3(0, 0, 0);
for(size_t i = 0; i < cloudTypesNum; i += CLOUDS_IN_ONE) {

// Center
_spawnCloud(world, m_cloudGridCenter, i);

// Top left
_spawnCloud(world,
m_cloudGridCenter +
Float3(-CLOUD_WIDTH * 2, 0, -CLOUD_HEIGHT * 2),
i);

// Up
_spawnCloud(
world, m_cloudGridCenter + Float3(0, 0, -CLOUD_HEIGHT * 2), i);

// Top right
_spawnCloud(world,
m_cloudGridCenter +
Float3(CLOUD_WIDTH * 2, 0, -CLOUD_HEIGHT * 2),
i);

// Left
_spawnCloud(
world, m_cloudGridCenter + Float3(-CLOUD_WIDTH * 2, 0, 0), i);

// Right
_spawnCloud(
world, m_cloudGridCenter + Float3(CLOUD_WIDTH * 2, 0, 0), i);

// Bottom left
_spawnCloud(world,
m_cloudGridCenter +
Float3(-CLOUD_WIDTH * 2, 0, CLOUD_HEIGHT * 2),
i);

// Down
_spawnCloud(
world, m_cloudGridCenter + Float3(0, 0, CLOUD_HEIGHT * 2), i);

// Bottom right
_spawnCloud(world,
m_cloudGridCenter +
Float3(CLOUD_WIDTH * 2, 0, CLOUD_HEIGHT * 2),
i);

const auto requiredCloudPositions{
calculateGridPositions(m_cloudGridCenter)};

for(size_t i = 0; i < m_cloudTypes.size(); i += CLOUDS_IN_ONE) {

// All positions
for(const auto& pos : requiredCloudPositions) {
_spawnCloud(world, pos, i);
}
}
}
// This rounds up to the nearest multiple of 4,
// divides that by 4 and multiplies by 9 to get all the clouds we have
// (if we have 5 compounds that are clouds, we need 18 clouds, if 4 we need
// 9 etc)
LEVIATHAN_ASSERT(
m_managedClouds.size() == ((((cloudTypesNum + 4 - 1) / 4 * 4) / 4) * 9),
LEVIATHAN_ASSERT(m_managedClouds.size() ==
((((m_cloudTypes.size() + 4 - 1) / 4 * 4) / 4) * 9),
"A CompoundCloud entity has mysteriously been destroyed");

const auto moved = playerPos - m_cloudGridCenter;
Expand All @@ -767,42 +736,18 @@ void
}

// Calculate the new positions
const Float3 requiredCloudPositions[] = {
// Center
m_cloudGridCenter,

// Top left
m_cloudGridCenter + Float3(-CLOUD_WIDTH * 2, 0, -CLOUD_HEIGHT * 2),

// Up
m_cloudGridCenter + Float3(0, 0, -CLOUD_HEIGHT * 2),

// Top right
m_cloudGridCenter + Float3(CLOUD_WIDTH * 2, 0, -CLOUD_HEIGHT * 2),

// Left
m_cloudGridCenter + Float3(-CLOUD_WIDTH * 2, 0, 0),

// Right
m_cloudGridCenter + Float3(CLOUD_WIDTH * 2, 0, 0),

// Bottom left
m_cloudGridCenter + Float3(-CLOUD_WIDTH * 2, 0, CLOUD_HEIGHT * 2),

// Down
m_cloudGridCenter + Float3(0, 0, CLOUD_HEIGHT * 2),

// Bottom right
m_cloudGridCenter + Float3(CLOUD_WIDTH * 2, 0, CLOUD_HEIGHT * 2),
};
const auto requiredCloudPositions{
calculateGridPositions(m_cloudGridCenter)};

// Reposition clouds according to the origin
// The max amount of clouds is that all need to be moved
const size_t MAX_FAR_CLOUDS = m_managedClouds.size();

// According to spec this check is superfluous, but it makes me feel
// better
if(m_tooFarAwayClouds.size() != MAX_FAR_CLOUDS)
m_tooFarAwayClouds.resize(MAX_FAR_CLOUDS);

// Reposition clouds according to the origin
// MAX of our cloud compounds is nearest multiple of 4 , divided by 4
// and multiplied by 9 This case only happens when you respawn.
constexpr size_t MAX_FAR_CLOUDS = 18;
std::array<CompoundCloudComponent*, MAX_FAR_CLOUDS> tooFarAwayClouds;
size_t farAwayIndex = 0;

// All clouds that aren't at one of the requiredCloudPositions needs to
Expand All @@ -822,6 +767,7 @@ void
// An exact check might work but just to be safe slight
// inaccuracy is allowed here
if((pos - requiredPos).HAddAbs() < Leviathan::EPSILON) {

matched = true;
break;
}
Expand All @@ -836,7 +782,7 @@ void
break;
}

tooFarAwayClouds[farAwayIndex++] = iter->second;
m_tooFarAwayClouds[farAwayIndex++] = iter->second;
}
}

Expand All @@ -846,8 +792,8 @@ void
size_t farAwayRepositionedIndex = 0;

// Loop through the cloud groups
for(size_t c = 0; c < cloudTypesNum; c += CLOUDS_IN_ONE) {
// Loop for moving clouds
for(size_t c = 0; c < m_cloudTypes.size(); c += CLOUDS_IN_ONE) {
// Loop for moving clouds to all needed positions for each group
for(size_t i = 0; i < std::size(requiredCloudPositions); ++i) {
bool hasCloud = false;
const auto& requiredPos = requiredCloudPositions[i];
Expand Down Expand Up @@ -877,8 +823,8 @@ void
break;
}

tooFarAwayClouds[farAwayRepositionedIndex++]->recycleToPosition(
requiredPos);
m_tooFarAwayClouds[farAwayRepositionedIndex++]
->recycleToPosition(requiredPos);
}
}
}
Expand Down Expand Up @@ -906,12 +852,13 @@ void
nullptr;
CompoundCloudComponent& cloud = world.Create_CompoundCloudComponent(
entity, *this, first, second, third, fourth);
m_managedClouds[entity] = &cloud;

// Set correct position
// TODO: this should probably be made a constructor parameter
cloud.m_position = pos;

initializeCloud(cloud, world.GetScene());
m_managedClouds[entity] = &cloud;
}


Expand Down Expand Up @@ -1041,7 +988,6 @@ void

auto* densityState = pass->createTextureUnitState();
densityState->setTexture(cloud.m_texture);
// densityState->setTextureName("TestImageThing.png");
densityState->setSamplerblock(wrappedBlock);

Ogre::TexturePtr texturePtr =
Expand All @@ -1052,8 +998,8 @@ void

noiseState->setSamplerblock(wrappedBlock);

// Maybe compiling this here is the best place
cloud.m_planeMaterial->compile();
// // Maybe compiling this here is the best place
// cloud.m_planeMaterial->compile();

// Needs to create a plane instance on which the material is used on
cloud.m_compoundCloudsPlane = scene->createItem(m_planeMesh);
Expand Down
39 changes: 39 additions & 0 deletions src/microbe_stage/compound_cloud_system.h
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,9 @@ class CompoundCloudComponent : public Leviathan::Component {
//! \todo This can be removed once there is a proper clear method available
//! for systems to detect
CompoundCloudSystem& m_owner;

// //! A helper value to handle cloud repositioning
// bool m_repositioned = false;
};


Expand Down Expand Up @@ -443,6 +446,39 @@ class CompoundCloudSystem {
convertWorldToCloudLocalForGrab(const Float3& cloudPosition,
const Float3& worldPosition);

static inline auto
calculateGridPositions(const Float3& center)
{
return std::array<Float3, 9>{
// Center
center,

// Top left
center + Float3(-CLOUD_WIDTH * 2, 0, -CLOUD_HEIGHT * 2),

// Up
center + Float3(0, 0, -CLOUD_HEIGHT * 2),

// Top right
center + Float3(CLOUD_WIDTH * 2, 0, -CLOUD_HEIGHT * 2),

// Left
center + Float3(-CLOUD_WIDTH * 2, 0, 0),

// Right
center + Float3(CLOUD_WIDTH * 2, 0, 0),

// Bottom left
center + Float3(-CLOUD_WIDTH * 2, 0, CLOUD_HEIGHT * 2),

// Down
center + Float3(0, 0, CLOUD_HEIGHT * 2),

// Bottom right
center + Float3(CLOUD_WIDTH * 2, 0, CLOUD_HEIGHT * 2),
};
}

protected:
//! \brief Removes deleted clouds from m_managedClouds
void
Expand Down Expand Up @@ -514,6 +550,9 @@ class CompoundCloudSystem {
//! the best way to simulate fluid velocity
std::vector<std::vector<float>> m_xVelocity;
std::vector<std::vector<float>> m_yVelocity;

//! This is here to not have to allocate memory every tick
std::vector<CompoundCloudComponent*> m_tooFarAwayClouds;
};

} // namespace thrive
11 changes: 11 additions & 0 deletions src/microbe_stage/compounds.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,17 @@ using namespace thrive;

Compound::Compound() {}

Compound::Compound(size_t id,
const std::string& name,
bool isCloud,
bool isUseful,
bool isEnvironmental,
Ogre::ColourValue colour) :
RegistryType(id, name),
isCloud(isCloud), isUseful(isUseful), isEnvironmental(isEnvironmental),
colour(colour)
{}

Compound::Compound(Json::Value value)
{
volume = value["volume"].asDouble();
Expand Down
Loading

0 comments on commit 46d9232

Please sign in to comment.