From 8d4f290819610ea5b277ab132ba30218e982f197 Mon Sep 17 00:00:00 2001 From: Mikulas Florek Date: Fri, 21 Oct 2016 11:43:07 +0200 Subject: [PATCH] Grass independant on the ground texture - closes #1024 --- src/renderer/editor/terrain_editor.cpp | 182 ++++++++++++++++++------- src/renderer/editor/terrain_editor.h | 10 +- src/renderer/render_scene.cpp | 12 -- src/renderer/render_scene.h | 3 +- src/renderer/renderer.cpp | 4 - src/renderer/terrain.cpp | 36 ++--- src/renderer/terrain.h | 36 +++-- 7 files changed, 171 insertions(+), 112 deletions(-) diff --git a/src/renderer/editor/terrain_editor.cpp b/src/renderer/editor/terrain_editor.cpp index c0a2665ae..f8b86d09d 100644 --- a/src/renderer/editor/terrain_editor.cpp +++ b/src/renderer/editor/terrain_editor.cpp @@ -64,7 +64,7 @@ struct PaintTerrainCommand LUMIX_FINAL : public Lumix::IEditorCommand PaintTerrainCommand(Lumix::WorldEditor& editor, - TerrainEditor::Type type, + TerrainEditor::ActionType action_type, int texture_idx, const Lumix::Vec3& hit_pos, Lumix::BinaryArray& mask, @@ -80,8 +80,9 @@ struct PaintTerrainCommand LUMIX_FINAL : public Lumix::IEditorCommand , m_new_data(editor.getAllocator()) , m_old_data(editor.getAllocator()) , m_items(editor.getAllocator()) - , m_type(type) + , m_action_type(action_type) , m_texture_idx(texture_idx) + , m_grass_idx(texture_idx) , m_mask(editor.getAllocator()) , m_flat_height(flat_height) { @@ -109,8 +110,9 @@ struct PaintTerrainCommand LUMIX_FINAL : public Lumix::IEditorCommand void serialize(Lumix::JsonSerializer& serializer) override { - serializer.serialize("type", (int)m_type); + serializer.serialize("type", (int)m_action_type); serializer.serialize("texture_idx", m_texture_idx); + serializer.serialize("grass_idx", m_grass_idx); serializer.beginArray("items"); for (int i = 0; i < m_items.size(); ++i) { @@ -135,10 +137,11 @@ struct PaintTerrainCommand LUMIX_FINAL : public Lumix::IEditorCommand void deserialize(Lumix::JsonSerializer& serializer) override { m_items.clear(); - int type; - serializer.deserialize("type", type, 0); - m_type = (TerrainEditor::Type)type; + int action_type; + serializer.deserialize("type", action_type, 0); + m_action_type = (TerrainEditor::ActionType)action_type; serializer.deserialize("texture_idx", m_texture_idx, 0); + serializer.deserialize("grass_idx", m_grass_idx, 0); serializer.deserializeArrayBegin("items"); while (!serializer.isArrayEnd()) { @@ -195,7 +198,7 @@ struct PaintTerrainCommand LUMIX_FINAL : public Lumix::IEditorCommand return false; } PaintTerrainCommand& my_command = static_cast(command); - if (m_terrain == my_command.m_terrain && m_type == my_command.m_type && + if (m_terrain == my_command.m_terrain && m_action_type == my_command.m_action_type && m_texture_idx == my_command.m_texture_idx) { my_command.m_items.push(m_items.back()); @@ -236,8 +239,10 @@ private: Lumix::Texture* getDestinationTexture() { const char* uniform_name = ""; - switch (m_type) + switch (m_action_type) { + case TerrainEditor::REMOVE_GRASS: + case TerrainEditor::ADD_GRASS: case TerrainEditor::LAYER: uniform_name = SPLATMAP_UNIFORM; break; @@ -365,6 +370,46 @@ private: } } + void rasterGrassItem(Lumix::Texture* texture, Lumix::Array& data, Item& item, TerrainEditor::ActionType action_type) + { + int texture_width = texture->width; + Rectangle r = item.getBoundingRectangle(texture_width, texture->height); + + if (texture->bytes_per_pixel != 4) + { + ASSERT(false); + return; + } + + float fx = 0; + float fstepx = 1.0f / (r.m_to_x - r.m_from_x); + float fstepy = 1.0f / (r.m_to_y - r.m_from_y); + for (int i = r.m_from_x, end = r.m_to_x; i < end; ++i, fx += fstepx) + { + float fy = 0; + for (int j = r.m_from_y, end2 = r.m_to_y; j < end2; ++j, fy += fstepy) + { + if (isMasked(fx, fy)) + { + int offset = 4 * (i - m_x + (j - m_y) * m_width) + 2; + float attenuation = getAttenuation(item, i, j); + int add = int(attenuation * item.m_amount * 255); + if (add > 0) + { + if (m_action_type == TerrainEditor::REMOVE_GRASS) + { + data[offset] &= ~(1 << m_grass_idx); + } + else + { + data[offset] |= 1 << m_grass_idx; + } + } + } + } + } + } + void rasterSmoothHeightItem(Lumix::Texture* texture, Lumix::Array& data, Item& item) { @@ -415,22 +460,27 @@ private: void rasterItem(Lumix::Texture* texture, Lumix::Array& data, Item& item) { - if (m_type == TerrainEditor::COLOR) + if (m_action_type == TerrainEditor::COLOR) { rasterColorItem(texture, data, item); return; } - else if (m_type == TerrainEditor::LAYER) + else if (m_action_type == TerrainEditor::LAYER) { rasterLayerItem(texture, data, item); return; } - else if (m_type == TerrainEditor::SMOOTH_HEIGHT) + else if (m_action_type == TerrainEditor::ADD_GRASS || m_action_type == TerrainEditor::REMOVE_GRASS) + { + rasterGrassItem(texture, data, item, m_action_type); + return; + } + else if (m_action_type == TerrainEditor::SMOOTH_HEIGHT) { rasterSmoothHeightItem(texture, data, item); return; } - else if (m_type == TerrainEditor::FLAT_HEIGHT) + else if (m_action_type == TerrainEditor::FLAT_HEIGHT) { rasterFlatHeightItem(texture, data, item); return; @@ -454,7 +504,7 @@ private: int add = int(attenuation * amount); Lumix::uint16 x = ((Lumix::uint16*)texture->getData())[(i + j * texture_width)]; - x += m_type == TerrainEditor::RAISE_HEIGHT ? Lumix::Math::minimum(add, 0xFFFF - x) + x += m_action_type == TerrainEditor::RAISE_HEIGHT ? Lumix::Math::minimum(add, 0xFFFF - x) : Lumix::Math::maximum(-add, -x); ((Lumix::uint16*)&data[0])[offset] = x; } @@ -525,7 +575,8 @@ private: texture->onDataUpdated(m_x, m_y, m_width, m_height); static_cast(m_terrain.scene)->forceGrassUpdate(m_terrain.handle); - if (m_type != TerrainEditor::LAYER && m_type != TerrainEditor::COLOR) + if (m_action_type != TerrainEditor::LAYER && m_action_type != TerrainEditor::COLOR && + m_action_type != TerrainEditor::ADD_GRASS && m_action_type != TerrainEditor::REMOVE_GRASS) { Lumix::IScene* scene = m_world_editor.getUniverse()->getScene(Lumix::crc32("physics")); if (!scene) return; @@ -616,11 +667,12 @@ private: Lumix::Array m_new_data; Lumix::Array m_old_data; int m_texture_idx; + int m_grass_idx; int m_width; int m_height; int m_x; int m_y; - TerrainEditor::Type m_type; + TerrainEditor::ActionType m_action_type; Lumix::Array m_items; Lumix::ComponentUID m_terrain; Lumix::WorldEditor& m_world_editor; @@ -694,6 +746,11 @@ TerrainEditor::TerrainEditor(Lumix::WorldEditor& editor, StudioApp& app) app.addAction(m_smooth_terrain_action); app.addAction(m_lower_terrain_action); + m_remove_grass_action = + LUMIX_NEW(editor.getAllocator(), Action)("Remove grass from terrain", "removeGrassFromTerrain"); + m_remove_grass_action->is_global = false; + app.addAction(m_remove_grass_action); + m_remove_entity_action = LUMIX_NEW(editor.getAllocator(), Action)("Remove entities from terrain", "removeEntitiesFromTerrain"); m_remove_entity_action->is_global = false; @@ -702,8 +759,9 @@ TerrainEditor::TerrainEditor(Lumix::WorldEditor& editor, StudioApp& app) editor.addPlugin(*this); m_terrain_brush_size = 10; m_terrain_brush_strength = 0.1f; - m_type = RAISE_HEIGHT; + m_action_type = RAISE_HEIGHT; m_texture_idx = 0; + m_grass_idx = 0; m_is_align_with_normal = false; m_is_rotate_x = false; m_is_rotate_y = false; @@ -758,7 +816,7 @@ void TerrainEditor::drawCursor(Lumix::RenderScene& scene, Lumix::ComponentHandle { PROFILE_FUNCTION(); static const int SLICE_COUNT = 30; - if (m_type == TerrainEditor::FLAT_HEIGHT && ImGui::GetIO().KeyCtrl) + if (m_action_type == TerrainEditor::FLAT_HEIGHT && ImGui::GetIO().KeyCtrl) { scene.addDebugCross(center, 1.0f, 0xff0000ff, 0); return; @@ -790,34 +848,46 @@ void TerrainEditor::drawCursor(Lumix::RenderScene& scene, Lumix::ComponentHandle void TerrainEditor::detectModifiers() { - bool is_height_tool = m_type == LOWER_HEIGHT || m_type == RAISE_HEIGHT || - m_type == SMOOTH_HEIGHT; + bool is_height_tool = m_action_type == LOWER_HEIGHT || m_action_type == RAISE_HEIGHT || + m_action_type == SMOOTH_HEIGHT; if (is_height_tool) { if (m_lower_terrain_action->isActive()) { - m_type = LOWER_HEIGHT; + m_action_type = LOWER_HEIGHT; } else if (m_smooth_terrain_action->isActive()) { - m_type = SMOOTH_HEIGHT; + m_action_type = SMOOTH_HEIGHT; } else { - m_type = RAISE_HEIGHT; + m_action_type = RAISE_HEIGHT; } } - bool is_entity_tool = m_type == ENTITY || m_type == REMOVE_ENTITY; + if (m_action_type == ADD_GRASS || m_action_type == REMOVE_GRASS) + { + if (m_remove_grass_action->isActive()) + { + m_action_type = REMOVE_GRASS; + } + else + { + m_action_type = ADD_GRASS; + } + } + + bool is_entity_tool = m_action_type == ENTITY || m_action_type == REMOVE_ENTITY; if (is_entity_tool) { if (m_remove_entity_action->isActive()) { - m_type = REMOVE_ENTITY; + m_action_type = REMOVE_ENTITY; } else { - m_type = ENTITY; + m_action_type = ENTITY; } } } @@ -857,14 +927,14 @@ bool TerrainEditor::onEntityMouseDown(const Lumix::WorldEditor::RayHit& hit, int if (selected_entities.size() != 1) return false; bool is_terrain = m_world_editor.getUniverse()->hasComponent(selected_entities[0], TERRAIN_TYPE); if (!is_terrain) return false; - if (m_type == NOT_SET || !m_component.isValid()) return false; + if (m_action_type == NOT_SET || !m_component.isValid()) return false; detectModifiers(); if (selected_entities[0] == hit.entity && m_component.isValid()) { Lumix::Vec3 hit_pos = hit.pos; - switch (m_type) + switch (m_action_type) { case FLAT_HEIGHT: if (ImGui::GetIO().KeyCtrl) @@ -873,14 +943,16 @@ bool TerrainEditor::onEntityMouseDown(const Lumix::WorldEditor::RayHit& hit, int } else { - paint(hit.pos, m_type, false); + paint(hit.pos, m_action_type, false); } break; case RAISE_HEIGHT: case LOWER_HEIGHT: case SMOOTH_HEIGHT: + case REMOVE_GRASS: + case ADD_GRASS: case COLOR: - case LAYER: paint(hit.pos, m_type, false); break; + case LAYER: paint(hit.pos, m_action_type, false); break; case ENTITY: paintEntities(hit.pos); break; case REMOVE_ENTITY: removeEntities(hit.pos); break; default: ASSERT(false); break; @@ -1166,14 +1238,16 @@ void TerrainEditor::onMouseMove(int x, int y, int, int) bool is_terrain = m_world_editor.getUniverse()->hasComponent(hit.m_entity, TERRAIN_TYPE); if (!is_terrain) return; - switch (m_type) + switch (m_action_type) { case FLAT_HEIGHT: case RAISE_HEIGHT: case LOWER_HEIGHT: case SMOOTH_HEIGHT: + case REMOVE_GRASS: + case ADD_GRASS: case COLOR: - case LAYER: paint(hit.m_origin + hit.m_dir * hit.m_t, m_type, true); break; + case LAYER: paint(hit.m_origin + hit.m_dir * hit.m_t, m_action_type, true); break; case ENTITY: paintEntities(hit.m_origin + hit.m_dir * hit.m_t); break; case REMOVE_ENTITY: removeEntities(hit.m_origin + hit.m_dir * hit.m_t); break; default: ASSERT(false); break; @@ -1220,7 +1294,8 @@ void TerrainEditor::onGUI() HEIGHT, LAYER, ENTITY, - COLOR + COLOR, + GRASS }; bool is_grass_enabled = scene->isGrassEnabled(); @@ -1228,9 +1303,9 @@ void TerrainEditor::onGUI() if (ImGui::Checkbox("Enable grass", &is_grass_enabled)) scene->enableGrass(is_grass_enabled); if (ImGui::Combo( - "Brush type", &m_current_brush, "Height\0Layer\0Entity\0Color\0")) + "Brush type", &m_current_brush, "Height\0Layer\0Entity\0Color\0Grass\0")) { - m_type = m_current_brush == HEIGHT ? TerrainEditor::RAISE_HEIGHT : m_type; + m_action_type = m_current_brush == HEIGHT ? TerrainEditor::RAISE_HEIGHT : m_action_type; } switch (m_current_brush) @@ -1239,8 +1314,9 @@ void TerrainEditor::onGUI() if (ImGui::Button("Save heightmap")) getMaterial()->getTextureByUniform(HEIGHTMAP_UNIFORM)->save(); break; + case GRASS: case LAYER: - if (ImGui::Button("Save layermap")) + if (ImGui::Button("Save layermap and grassmap")) getMaterial()->getTextureByUniform(SPLATMAP_UNIFORM)->save(); break; case COLOR: @@ -1249,7 +1325,7 @@ void TerrainEditor::onGUI() break; } - if (m_current_brush == LAYER || m_current_brush == COLOR) + if (m_current_brush == LAYER || m_current_brush == GRASS || m_current_brush == COLOR) { if (m_brush_texture) { @@ -1308,28 +1384,42 @@ void TerrainEditor::onGUI() { case HEIGHT: { - bool is_flat_tool = m_type == TerrainEditor::FLAT_HEIGHT; + bool is_flat_tool = m_action_type == TerrainEditor::FLAT_HEIGHT; if (ImGui::Checkbox("Flat", &is_flat_tool)) { - m_type = is_flat_tool ? TerrainEditor::FLAT_HEIGHT : TerrainEditor::RAISE_HEIGHT; + m_action_type = is_flat_tool ? TerrainEditor::FLAT_HEIGHT : TerrainEditor::RAISE_HEIGHT; } - if (m_type == TerrainEditor::FLAT_HEIGHT) + if (m_action_type == TerrainEditor::FLAT_HEIGHT) { ImGui::SameLine(); ImGui::Text("- Press Ctrl to pick height"); } break; } + case GRASS: + { + m_action_type = TerrainEditor::ADD_GRASS; + int type_count = scene->getGrassCount(m_component.handle); + for (int i = 0; i < type_count; ++i) + { + if (i % 4 != 0) ImGui::SameLine(); + if (ImGui::RadioButton(Lumix::StaticString<20>("", i, "###rb", i), m_grass_idx == i)) + { + m_grass_idx = i; + } + } + break; + } case COLOR: { - m_type = TerrainEditor::COLOR; + m_action_type = TerrainEditor::COLOR; ImGui::ColorPicker(&m_color.x, false); break; } case LAYER: { - m_type = TerrainEditor::LAYER; + m_action_type = TerrainEditor::LAYER; Lumix::Texture* tex = getMaterial()->getTextureByUniform(TEX_COLOR_UNIFORM); if (tex) { @@ -1346,7 +1436,7 @@ void TerrainEditor::onGUI() } case ENTITY: { - m_type = TerrainEditor::ENTITY; + m_action_type = TerrainEditor::ENTITY; auto& template_system = m_world_editor.getEntityTemplateSystem(); auto& template_names = template_system.getTemplateNames(); if (template_names.empty()) @@ -1433,7 +1523,7 @@ void TerrainEditor::onGUI() } if(!m_component.isValid()) return; - if(m_type == NOT_SET) return; + if(m_action_type == NOT_SET) return; if(!m_is_enabled) return; float mouse_x = m_world_editor.getMouseX(); @@ -1460,11 +1550,11 @@ void TerrainEditor::onGUI() } -void TerrainEditor::paint(const Lumix::Vec3& hit_pos, Type type, bool old_stroke) +void TerrainEditor::paint(const Lumix::Vec3& hit_pos, ActionType action_type, bool old_stroke) { PaintTerrainCommand* command = LUMIX_NEW(m_world_editor.getAllocator(), PaintTerrainCommand)(m_world_editor, - type, - m_texture_idx, + action_type, + action_type == ADD_GRASS || action_type == REMOVE_GRASS ? m_grass_idx : m_texture_idx, hit_pos, m_brush_mask, m_terrain_brush_size, diff --git a/src/renderer/editor/terrain_editor.h b/src/renderer/editor/terrain_editor.h index 421a8ebec..1820f05a6 100644 --- a/src/renderer/editor/terrain_editor.h +++ b/src/renderer/editor/terrain_editor.h @@ -19,7 +19,7 @@ class Texture; class TerrainEditor LUMIX_FINAL : public Lumix::WorldEditor::Plugin { public: - enum Type + enum ActionType { RAISE_HEIGHT, LOWER_HEIGHT, @@ -29,6 +29,8 @@ public: ENTITY, REMOVE_ENTITY, COLOR, + ADD_GRASS, + REMOVE_GRASS, NOT_SET }; @@ -46,7 +48,7 @@ private: void detectModifiers(); void drawCursor(Lumix::RenderScene& scene, Lumix::ComponentHandle cmp, const Lumix::Vec3& center); Lumix::Material* getMaterial(); - void paint(const Lumix::Vec3& hit, TerrainEditor::Type type, bool new_stroke); + void paint(const Lumix::Vec3& hit, TerrainEditor::ActionType action_type, bool new_stroke); static void getProjections(const Lumix::Vec3& axis, const Lumix::Vec3 vertices[8], @@ -64,11 +66,12 @@ private: private: Lumix::WorldEditor& m_world_editor; - Type m_type; + ActionType m_action_type; Lumix::ComponentUID m_component; float m_terrain_brush_strength; float m_terrain_brush_size; int m_texture_idx; + int m_grass_idx; Lumix::uint16 m_flat_height; Lumix::Vec3 m_color; int m_current_brush; @@ -80,6 +83,7 @@ private: Action* m_lower_terrain_action; Action* m_smooth_terrain_action; Action* m_remove_entity_action; + Action* m_remove_grass_action; Lumix::BinaryArray m_brush_mask; Lumix::Texture* m_brush_texture; Lumix::Vec2 m_size_spread; diff --git a/src/renderer/render_scene.cpp b/src/renderer/render_scene.cpp index e24e483fa..ec74514b8 100644 --- a/src/renderer/render_scene.cpp +++ b/src/renderer/render_scene.cpp @@ -2441,18 +2441,6 @@ public: } - void setGrassGround(ComponentHandle cmp, int index, int ground) override - { - m_terrains[{cmp.index}]->setGrassTypeGround(index, ground); - } - - - int getGrassGround(ComponentHandle cmp, int index) override - { - return m_terrains[{cmp.index}]->getGrassTypeGround(index); - } - - void setGrassPath(ComponentHandle cmp, int index, const Path& path) override { m_terrains[{cmp.index}]->setGrassTypePath(index, path); diff --git a/src/renderer/render_scene.h b/src/renderer/render_scene.h index b5da7d5de..79c3ceac2 100644 --- a/src/renderer/render_scene.h +++ b/src/renderer/render_scene.h @@ -55,6 +55,7 @@ enum class RenderSceneVersion : int32 DECAL, PARTICLE_EMITTER_SUBIMAGE_MODULE, PARTICLE_EMITTER_LOCAL_SPACE, + NEW_GRASS, LATEST, INVALID = -1, @@ -383,8 +384,6 @@ public: virtual void enableGrass(bool enabled) = 0; virtual void setGrassPath(ComponentHandle cmp, int index, const Path& path) = 0; virtual Path getGrassPath(ComponentHandle cmp, int index) = 0; - virtual void setGrassGround(ComponentHandle cmp, int index, int ground) = 0; - virtual int getGrassGround(ComponentHandle cmp, int index) = 0; virtual void setGrassDensity(ComponentHandle cmp, int index, int density) = 0; virtual int getGrassDensity(ComponentHandle cmp, int index) = 0; virtual int getGrassCount(ComponentHandle cmp) = 0; diff --git a/src/renderer/renderer.cpp b/src/renderer/renderer.cpp index 38a4af81e..1e0942899 100644 --- a/src/renderer/renderer.cpp +++ b/src/renderer/renderer.cpp @@ -407,10 +407,6 @@ static void registerProperties(IAllocator& allocator) "Mesh", &RenderScene::getGrassPath, &RenderScene::setGrassPath, "Mesh (*.msh)", MODEL_TYPE)); grass->addChild(LUMIX_NEW(allocator, DecimalPropertyDescriptor)( "Distance", &RenderScene::getGrassDistance, &RenderScene::setGrassDistance, 1.0f, FLT_MAX, 1.0f)); - auto ground = LUMIX_NEW(allocator, IntPropertyDescriptor)( - "Ground", &RenderScene::getGrassGround, &RenderScene::setGrassGround); - ground->setLimit(0, 4); - grass->addChild(ground); grass->addChild(LUMIX_NEW(allocator, IntPropertyDescriptor)( "Density", &RenderScene::getGrassDensity, &RenderScene::setGrassDensity)); PropertyRegister::add("terrain", grass); diff --git a/src/renderer/terrain.cpp b/src/renderer/terrain.cpp index 081fd8fb3..d4c3b437a 100644 --- a/src/renderer/terrain.cpp +++ b/src/renderer/terrain.cpp @@ -229,13 +229,13 @@ Terrain::~Terrain() } -Terrain::GrassType::GrassType(Terrain& terrain) +Terrain::GrassType::GrassType(Terrain& terrain, int idx) : m_terrain(terrain) { m_grass_model = nullptr; - m_ground = 0; m_density = 10; m_distance = 50; + m_idx = idx; } @@ -249,11 +249,11 @@ void Terrain::addGrassType(int index) { if(index < 0) { - m_grass_types.push(LUMIX_NEW(m_allocator, GrassType)(*this)); + m_grass_types.push(LUMIX_NEW(m_allocator, GrassType)(*this, m_grass_types.size())); } else { - m_grass_types.insert(index, LUMIX_NEW(m_allocator, GrassType)(*this)); + m_grass_types.insert(index, LUMIX_NEW(m_allocator, GrassType)(*this, index)); } } @@ -301,23 +301,6 @@ float Terrain::getGrassTypeDistance(int index) const } -void Terrain::setGrassTypeGround(int index, int ground) -{ - Lumix::Texture* tex = getMaterial()->getTextureByUniform(TEX_COLOR_UNIFORM); - if(tex) ground = Math::clamp(ground, 0, tex->layers - 1); - forceGrassUpdate(); - GrassType& type = *m_grass_types[index]; - type.m_ground = ground; -} - - -int Terrain::getGrassTypeGround(int index) const -{ - GrassType& type = *m_grass_types[index]; - return type.m_ground; -} - - AABB Terrain::getAABB() const { Vec3 min(0, 0, 0); @@ -421,8 +404,8 @@ void Terrain::generateGrassTypeQuad(GrassPatch& patch, const Matrix& terrain_mat int tx = int(base_tx + tx_step * dx); uint32 pixel_value = splat_data[tx]; - int ground_index = pixel_value & 0xff; - if (ground_index != patch.m_type->m_ground) continue; + int ground_mask = (pixel_value >> 16) & 0xff; + if ((ground_mask & (1 << patch.m_type->m_idx)) == 0) continue; float density = ((pixel_value >> 8) & 0xff) * DIV255; if (density < 0.25f) continue; @@ -621,7 +604,11 @@ void Terrain::deserialize(InputBlob& serializer, for(int i = 0; i < count; ++i) { serializer.readString(path, MAX_PATH_LENGTH); - serializer.read(m_grass_types[i]->m_ground); + if (version <= (int)RenderSceneVersion::NEW_GRASS) + { + int dummy; + serializer.read(dummy); + } serializer.read(m_grass_types[i]->m_density); if (version > (int)RenderSceneVersion::GRASS_TYPE_DISTANCE) { @@ -646,7 +633,6 @@ void Terrain::serialize(OutputBlob& serializer) { GrassType& type = *m_grass_types[i]; serializer.writeString(type.m_grass_model ? type.m_grass_model->getPath().c_str() : ""); - serializer.write(type.m_ground); serializer.write(type.m_density); serializer.write(type.m_distance); } diff --git a/src/renderer/terrain.h b/src/renderer/terrain.h index 447e0d893..f78bb31a7 100644 --- a/src/renderer/terrain.h +++ b/src/renderer/terrain.h @@ -34,19 +34,18 @@ class Universe; class Terrain { public: - class GrassType + struct GrassType { - public: - explicit GrassType(Terrain& terrain); - ~GrassType(); + GrassType(Terrain& terrain, int idx); + ~GrassType(); - void grassLoaded(Resource::State, Resource::State, Resource&); + void grassLoaded(Resource::State, Resource::State, Resource&); - Model* m_grass_model; - Terrain& m_terrain; - int32 m_ground; - int32 m_density; - float m_distance; + Model* m_grass_model; + Terrain& m_terrain; + int32 m_density; + float m_distance; + int m_idx; }; struct GrassPatch @@ -64,16 +63,15 @@ class Terrain GrassType* m_type; }; - class GrassQuad + struct GrassQuad { - public: - explicit GrassQuad(IAllocator& allocator) - : m_patches(allocator) - {} + explicit GrassQuad(IAllocator& allocator) + : m_patches(allocator) + {} - Array m_patches; - Vec3 pos; - float radius; + Array m_patches; + Vec3 pos; + float radius; }; public: @@ -99,7 +97,6 @@ class Terrain AABB getAABB() const; int getWidth() const { return m_width; } int getHeight() const { return m_height; } - int getGrassTypeGround(int index) const; int getGrassTypeDensity(int index) const; float getGrassTypeDistance(int index) const; int getGrassTypeCount() const { return m_grass_types.size(); } @@ -109,7 +106,6 @@ class Terrain void setXZScale(float scale) { m_scale.x = scale; m_scale.z = scale; } void setYScale(float scale) { m_scale.y = scale; } void setGrassTypePath(int index, const Path& path); - void setGrassTypeGround(int index, int ground); void setGrassTypeDensity(int index, int density); void setGrassTypeDistance(int index, float value); void setMaterial(Material* material);