game: change flag extents to 3D markers

Works better for 3D terrain
This commit is contained in:
Crypto City 2020-07-18 00:39:02 +00:00
parent 6e04ee20dc
commit bdfc76b151
4 changed files with 79 additions and 40 deletions

View File

@ -1,6 +1,6 @@
<material>
<technique name="Techniques/DiffUnlitAlpha.xml" />
<texture unit="diffuse" name="Textures/selmask.png" />
<texture unit="diffuse" name="Textures/blank.png" />
<parameter name="MatDiffColor" value="1 1 1 1" />
<parameter name="MatSpecColor" value="1 1 1 1" />
</material>

BIN
GameData/Textures/blank.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 B

View File

@ -67,7 +67,7 @@ static CustomModel *createModel(const std::vector<float> &vertex_data, const std
// https://martin.ankerl.com/2009/12/09/how-to-create-random-colors-programmatically/
static Color GetRandomColor(size_t n, float alpha = 1.0f)
{
static constexpr float s = .7f;
static constexpr float s = .9f;
static constexpr float v = .95f;
static constexpr float golden_ratio_conjugate = 0.618033988749895;
float h = 0;
@ -171,6 +171,8 @@ CityMeshResources::CityMeshResources(ResourceCache *cache)
influenceModel = cache->GetResource<Model>("Models/Plane.mdl");
cursorModel = cache->GetResource<Model>("Models/Box.mdl");
markerModel = cache->GetResource<Model>("Models/Pyramid.mdl");
VertexBuffer *vbuffer = blockModel->GetGeometry(0, 0)->GetVertexBuffer(0);
const float *vertexData = (const float*)vbuffer->Lock(0, vbuffer->GetVertexCount());
if (vertexData)
@ -435,12 +437,14 @@ void CityMeshSection::setView(uint32_t vx0, uint32_t vy0, uint32_t vx1, uint32_t
void CityMeshSection::setCameraPos(const Vector3 &pos)
{
height_scale = get_height_scale(pos);
#if 0
for (const auto &node: flagNodes)
{
Vector3 p = node.second->GetPosition();
p.y_ = 0.01f * height_scale;
node.second->SetPosition(p);
}
#endif
if (selectionNode)
selectionNode->SetPosition(Vector3(0.0f, 0.01f * height_scale, 0.0f));
}
@ -698,6 +702,47 @@ static CustomModel *create_area(Node *node, Material *material, uint32_t fx0, ui
return model;
}
static void add_marker(Node *node, Model *model, Material *material, uint32_t x, uint32_t y, uint32_t ox, uint32_t oy, float height)
{
Node *markerNode = node->CreateChild("marker");
markerNode->SetPosition(Vector3((int32_t)(x - ox), height + 1.5f, (int32_t)(y - oy)));
markerNode->SetScale(Vector3(0.5f, 3.0f, 0.5f));
static const Quaternion upside_down(180.0f, Vector3(1.0f, 0.0f, 0.0f));
markerNode->SetRotation(upside_down);
auto object = markerNode->CreateComponent<StaticModel>();
object->SetModel(model, true);
object->SetMaterial(material);
object->SetCastShadows(false);
}
void CityMeshSection::CreateMarkerArea(Node *node, Material *material, uint32_t fx0, uint32_t fy0, uint32_t fx1, uint32_t fy1, float height)
{
const CityState *city = &game->cityState;
const uint32_t ox = city->ox;
const uint32_t oy = city->oy;
const cc::cc_potential_state_t *state = cc::get_cc_potential_state(city->id, city->seed);
++fx1;
++fy1;
add_marker(node, resources.markerModel, material, fx0, fy0, ox, oy, height + cc::get_cc_height(state, fx0, fy0) / (float)HEIGHT_UNITS_PER_BLOCK);
add_marker(node, resources.markerModel, material, fx0, fy1, ox, oy, height + cc::get_cc_height(state, fx0, fy1) / (float)HEIGHT_UNITS_PER_BLOCK);
add_marker(node, resources.markerModel, material, fx1, fy0, ox, oy, height + cc::get_cc_height(state, fx1, fy0) / (float)HEIGHT_UNITS_PER_BLOCK);
add_marker(node, resources.markerModel, material, fx1, fy1, ox, oy, height + cc::get_cc_height(state, fx1, fy1) / (float)HEIGHT_UNITS_PER_BLOCK);
static const uint32_t delta = 4;
for (uint32_t y = fy0 + delta; y <= fy1 - (delta - 1); y += delta)
{
add_marker(node, resources.markerModel, material, fx0, y, ox, oy, height + cc::get_cc_height(state, fx0, y) / (float)HEIGHT_UNITS_PER_BLOCK);
add_marker(node, resources.markerModel, material, fx1, y, ox, oy, height + cc::get_cc_height(state, fx1, y) / (float)HEIGHT_UNITS_PER_BLOCK);
}
for (uint32_t x = fx0 + delta; x <= fx1 - (delta - 1); x += delta)
{
add_marker(node, resources.markerModel, material, x, fy0, ox, oy, height + cc::get_cc_height(state, x, fy0) / (float)HEIGHT_UNITS_PER_BLOCK);
add_marker(node, resources.markerModel, material, x, fy1, ox, oy, height + cc::get_cc_height(state, x, fy1) / (float)HEIGHT_UNITS_PER_BLOCK);
}
}
void CityMeshSection::GetFlags(std::set<uint32_t> &flags) const
{
for (const auto &e: blockNodes)
@ -1283,14 +1328,12 @@ void CityMeshSection::RebuildFlags(const C &flags, const Selection &selection, b
if (!material)
{
material = resources.ownershipMaterial->Clone();
material->SetShaderParameter("MatDiffColor", GetRandomColor(flag->owner, .6f));
material->SetShaderParameter("MatDiffColor", GetRandomColor(flag->owner, 1.0f));
resources.ownership_materials[flag->id] = material;
}
create_area(flagNode, material, flag->x0, flag->y0, flag->x1, flag->y1, ox, oy, 0.0f);
CreateMarkerArea(flagNode, material, flag->x0, flag->y0, flag->x1, flag->y1, 0.0f);
}
flagNode->SetPosition(Vector3(U2Fd(flag->, x), 0.01f * height_scale, U2Fd(flag->, y)));
}
if (has_new)
@ -1394,13 +1437,10 @@ void CityMeshUrho3D::CreateGroundTiles()
ResourceCache* cache = node->GetSubsystem<ResourceCache>();
influenceNode = node->CreateChild("influence");
influenceNode->SetPosition(Vector3(0.0f, 0.02f * height_scale, 0.0f));
generatorExtentsNode = node->CreateChild("generator_extents");
generatorExtentsNode->SetPosition(Vector3(0.0f, 0.0175f * height_scale, 0.0f));
maxGeneratorExtentsNode = node->CreateChild("max_generator_extents");
maxGeneratorExtentsNode->SetPosition(Vector3(0.0f, 0.0175f * height_scale, 0.0f));
for (int i = 0; i < 2; ++i)
{
@ -1474,10 +1514,9 @@ void CityMeshUrho3D::setHighlight(const Selection &selection, const std::shared_
uint32_t iy0 = flag->y0 - influence;
uint32_t ix1 = flag->x1 + influence;
uint32_t iy1 = flag->y1 + influence;
influenceNode->SetPosition(Vector3(U2F(i, x), 0.315f * height_scale, U2F(i, y)));
node->AddChild(influenceNode); // does not double add and removes from existing parent if needed
influenceNode->RemoveComponents<CustomModel>();
create_area(influenceNode, resources.influenceMaterial, ix0, iy0, ix1, iy1, ox, oy, 0.0f);
influenceNode->RemoveAllChildren();
CreateMarkerArea(influenceNode, resources.influenceMaterial, ix0, iy0, ix1, iy1, 0.0f);
if (cc::is_generator(flag->role))
{
uint32_t generator_extents = RESOURCE_AVAILABILITY_SCALE(influence);
@ -1485,17 +1524,15 @@ void CityMeshUrho3D::setHighlight(const Selection &selection, const std::shared_
uint32_t gy0 = flag->y0 - generator_extents;
uint32_t gx1 = flag->x1 + generator_extents;
uint32_t gy1 = flag->y1 + generator_extents;
generatorExtentsNode->RemoveComponents<CustomModel>();
generatorExtentsNode->SetPosition(Vector3(U2F(g, x), 0.3175f * height_scale, U2F(g, y)));
create_area(generatorExtentsNode, resources.influenceMaterial, gx0, gy0, gx1, gy1, ox, oy, 0.0f);
generatorExtentsNode->RemoveAllChildren();
CreateMarkerArea(generatorExtentsNode, resources.influenceMaterial, gx0, gy0, gx1, gy1, 0.0f);
uint32_t mgx0 = flag->x0 - generator_extents * MAX_DISTANCE_PERCENTAGE / 100;
uint32_t mgy0 = flag->y0 - generator_extents * MAX_DISTANCE_PERCENTAGE / 100;
uint32_t mgx1 = flag->x1 - generator_extents * MAX_DISTANCE_PERCENTAGE / 100;
uint32_t mgy1 = flag->y1 - generator_extents * MAX_DISTANCE_PERCENTAGE / 100;
maxGeneratorExtentsNode->RemoveComponents<CustomModel>();
maxGeneratorExtentsNode->SetPosition(Vector3(U2F(mg, x), 0.3175f * height_scale, U2F(mg, y)));
create_area(maxGeneratorExtentsNode, resources.influenceMaterial, mgx0, mgy0, mgx1, mgy1, ox, oy, 0.0f);
maxGeneratorExtentsNode->RemoveAllChildren();
CreateMarkerArea(maxGeneratorExtentsNode, resources.influenceMaterial, mgx0, mgy0, mgx1, mgy1, 0.0f);
}
else
{
@ -1572,18 +1609,6 @@ void CityMeshSection::updateHeightMap()
printf("Height map changed in %f seconds, geometry rebuilt in %f seconds\n", (t1-t0)/1e6, (t2-t1)/1e6);
}
bool CityMeshSection::IsIn(uint32_t x, uint32_t y) const
{
return (x >= vx0 && x <= vx1 && y >= vy0 && y <= vy1);
}
uint16_t CityMeshSection::GetTerrainHeight(uint32_t x, uint32_t y) const
{
uint16_t h = terrainHeightMap->GetPixelInt(x - vx0, terrainHeightMap->GetHeight() - 1 - (y - vy0));
h = SWAP16(h);
return h / HEIGHT_UNITS_PER_BLOCK;
}
void CityMeshSection::SetNorth(const Urho3D::SharedPtr<CityMeshSection> &section)
{
terrain->SetNorthNeighbor(section ? section->terrain : NULL);
@ -1610,7 +1635,7 @@ void CityMeshUrho3D::Update(float timeStep, const Selection &selection, bool mar
float pulseIntensity = (sinf(time * 10) + 1) / 2;
Color color(pulseIntensity / 2, pulseIntensity / 2 + .75f, pulseIntensity / 2 + .75f, 0.5);
resources.selectedMaterial->SetShaderParameter("MatDiffColor", color);
color.a_ = 0.3;
color.a_ = 1.0f;
resources.influenceMaterial->SetShaderParameter("MatDiffColor", color);
if (mark_new_block)
empower_t0 = time;
@ -1765,19 +1790,32 @@ void CityMeshUrho3D::ClearFlags(const std::set<uint32_t> &flags)
sections[x][y]->ClearFlags(flags);
}
uint16_t CityMeshUrho3D::GetTerrainHeight(uint32_t tx, uint32_t ty) const
uint16_t CityMeshUrho3D::GetTerrainHeight(uint32_t x, uint32_t y) const
{
for (int y = 0; y < NUM_CITY_SECTIONS; ++y)
for (int x = 0; x < NUM_CITY_SECTIONS; ++x)
if (sections[x][y] && sections[x][y]->IsIn(tx, ty))
return sections[x][y]->GetTerrainHeight(tx, ty);
const CityState *city = &game->cityState;
const cc::cc_potential_state_t *state = cc::get_cc_potential_state(city->id, city->seed);
const uint16_t raw_height = cc::get_cc_height(state, tx, ty);
const uint16_t raw_height = cc::get_cc_height(state, x, y);
return raw_height / HEIGHT_UNITS_PER_BLOCK;
}
void CityMeshUrho3D::CreateMarkerArea(Node *node, Material *material, uint32_t fx0, uint32_t fy0, uint32_t fx1, uint32_t fy1, float height)
{
const CityState *city = &game->cityState;
const uint32_t ox = city->ox;
const uint32_t oy = city->oy;
const cc::cc_potential_state_t *state = cc::get_cc_potential_state(city->id, city->seed);
for (uint32_t y = fy0; y <= fy1; y += 4)
{
add_marker(node, resources.markerModel, material, fx0, y, ox, oy, height + cc::get_cc_height(state, fx0, y) / (float)HEIGHT_UNITS_PER_BLOCK);
add_marker(node, resources.markerModel, material, fx1, y, ox, oy, height + cc::get_cc_height(state, fx1, y) / (float)HEIGHT_UNITS_PER_BLOCK);
}
for (uint32_t x = fx0 + 4; x <= fx1 - 4; x += 4)
{
add_marker(node, resources.markerModel, material, x, fy0, ox, oy, height + cc::get_cc_height(state, x, fy0) / (float)HEIGHT_UNITS_PER_BLOCK);
add_marker(node, resources.markerModel, material, x, fy1, ox, oy, height + cc::get_cc_height(state, x, fy1) / (float)HEIGHT_UNITS_PER_BLOCK);
}
}
template<typename C>
void CityMeshUrho3D::RebuildFlags(const C &flags, const Selection &selection, bool highlight_new)
{

View File

@ -68,6 +68,7 @@ struct CityMeshResources
Urho3D::SharedPtr<Urho3D::Model> selectionModel;
Urho3D::SharedPtr<Urho3D::Model> influenceModel;
Urho3D::SharedPtr<Urho3D::Model> cursorModel;
Urho3D::SharedPtr<Urho3D::Model> markerModel;
Urho3D::Quaternion FrontRotation;
Urho3D::Quaternion BackRotation;
@ -96,8 +97,6 @@ public:
void ClearFlags(const std::set<uint32_t> &flags);
template<typename C> void RebuildFlags(const C &flags, const Selection &selection, bool highlight_new);
bool hasFlagsWithNew() const { return !flagsWithNew.empty(); }
bool IsIn(uint32_t x, uint32_t y) const;
uint16_t GetTerrainHeight(uint32_t x, uint32_t y) const;
void SetNorth(const Urho3D::SharedPtr<CityMeshSection> &section);
void SetSouth(const Urho3D::SharedPtr<CityMeshSection> &section);
@ -107,6 +106,7 @@ public:
private:
void CreateTerrain();
void updateHeightMap();
void CreateMarkerArea(Urho3D::Node *node, Urho3D::Material *material, uint32_t fx0, uint32_t fy0, uint32_t fx1, uint32_t fy1, float height = 0.0f);
private:
const GameState *game;
@ -179,6 +179,7 @@ private:
void CreateGroundTiles();
void CreateTerrain();
void SetupMaterials();
void CreateMarkerArea(Urho3D::Node *node, Urho3D::Material *material, uint32_t fx0, uint32_t fy0, uint32_t fx1, uint32_t fy1, float height = 0.0f);
private:
Urho3D::SharedPtr<Urho3D::Node> node;