Terrain Editor in Lumberyard 1.27 is missing

A little feedback first:
The editor feels stable now. I haven’t experience crashes at all and it is so smooth and light to use as if I am using Blender (I am also using Cryengine so I can feel the difference). The building of Gems are pretty easy now but I still do it through command prompt because I just want to see the progress (this is just my own preference). I love this landscape canvas. However…

The issue:
I can’t figure out where is the Terrain Editor in 1.27. Can anyone help me with this.




Some icons are also missing.

You have the new viewport option enabled. You have to disable that in the general settings.

3 Likes

Yes @wcb is right you need to turn off the new interactive model, it does not and probably wont get the terrain editors until they make a new terrain system for lumberyard.

1 Like

Thank you. I hope they have road map. This engine is so smooth with this version.
Just another question. Can I paint vegetation through terrain tool and make an entity out of it? Or the only option is to save it as vegetation.

Not to my knowledge. You can, however, use the vegetation components and new landscape system but that’s for dynamic vegetation and there’s no painting. It’s all procedural.

I already tried that. Thanks again.

Hi @ralpha, actually I did write some code a that lets you convert vegetation to entities and used it to export some of the StarterGame vegetation to entities - however the problem with vegetation using the mesh component for your vegetation is the LOD transitions do not work as smoothly so you get LOD popping and the vegetation doesn’t fade in as nicely as it does when rendered using traditional vegetation. Also, the vegetation system has additional cvars for controlling all vegetation which can be handy when tweaking performance.

created_entities

In either case, you can try out this code and see if it works for your use case:
Edit dev/Code/Sandbox/Editor/VegetationPanel.cpp

Import a bunch more headers (probably don’t need all of these)

#include <AzToolsFramework/API/EditorVegetationRequestsBus.h>
#include <AzToolsFramework/Entity/EditorEntityContextBus.h>
#include <AzToolsFramework/API/EntityCompositionRequestBus.h>
#include <AzToolsFramework/ToolsComponents/TransformComponent.h>
#include <AzToolsFramework/PropertyTreeEditor/PropertyTreeEditor.h>
#include <AzToolsFramework/Slice/SliceUtilities.h> //probly dont need this
#include <AzToolsFramework/Slice/SliceTransaction.h> // probly don't need this
#include <LmbrCentral/Rendering/MeshAsset.h>
#include <LmbrCentral/Rendering/MeshComponentBus.h>

Add a new entry to the right-click context menu on line 684

VEGETATION_MENU_EXPORT_ENTITIES

Add a menu action on line 1754

CreateMenuAction(m_menu, tr("Export Entities"), VEGETATION_MENU_EXPORT_ENTITIES);

Add the functionality that converts vegetation meshes to entities & components on line 1833

    case VEGETATION_MENU_EXPORT_ENTITIES:
    {
        using namespace AzToolsFramework;

        Selection objects;
        m_tool->GetSelectedObjects(objects);
        if (objects.empty())
        {
            QMessageBox::warning(this, tr("Select Objects for Export"), tr("Please select some vegetation objects to export to entities"));
            return;
        }

        std::vector<CVegetationInstance*> vegetationInstances;
        m_vegetationMap->GetAllInstances(vegetationInstances);

        auto* console = GetISystem()->GetIConsole();
        AZ_Assert(console, "ISystem or IConsole are invalid");
        auto* viewDistMinCVar = console->GetCVar("e_ViewDistMin");
        float viewDistMin = viewDistMinCVar->GetFVal();

        auto* viewDistRatioVegetationCVar = console->GetCVar("e_ViewDistRatioVegetation");
        float viewDistRatioVegetation = viewDistRatioVegetationCVar->GetFVal();

        for (const auto& vegetation : vegetationInstances)
        {
            bool shouldExportInstance = false;
            for (CVegetationObject* vegetationObject : objects)
            {
                if (vegetation->object == vegetationObject)
                {
                    shouldExportInstance = true;
                    break;
                }
            }

            if (!shouldExportInstance)
            {
                continue;
            }

            QString vegFileName = vegetation->object->GetFileName();

            // get the vegetation mesh asset
            AZ::Data::AssetId meshId;
            AZ::Data::AssetCatalogRequestBus::BroadcastResult(meshId, &AZ::Data::AssetCatalogRequests::GetAssetIdByPath, vegFileName.toUtf8().data(), AZ::Data::s_invalidAssetType, false);
            if (!meshId.IsValid())
            {
                continue;
            }

            // vegetation scale is limited to scale of size 4 because of how it is stored in veg system
            float vegScale = AZStd::clamp<float>(vegetation->scale, 0.1, 4.0);
            float angle = vegetation->angle;

            AZStd::string instanceName(vegFileName.toLatin1().data());
            AzFramework::StringFunc::Path::StripPath(instanceName);
            AzFramework::StringFunc::Path::StripExtension(instanceName);
            //AZStd::transform(instanceName.begin(), instanceName.end(), instanceName.begin(), ::tolower);
            //const AZStd::string entityName = AZStd::string::format("%s_%d", instanceName.c_str(), instanceCount);

            AZ::EntityId newEntityId;
            EditorEntityContextRequestBus::BroadcastResult(newEntityId, &EditorEntityContextRequests::CreateNewEditorEntity, instanceName.c_str());

            const AZ::Uuid editorMeshComponentUuid("{FC315B86-3280-4D03-B4F0-5553D7D08432}");
            EntityCompositionRequests::AddComponentsOutcome outcome = AZ::Failure(AZStd::string("Failed to add MeshComponent"));
            EntityCompositionRequestBus::BroadcastResult(outcome, &EntityCompositionRequests::AddComponentsToEntities, EntityIdList{ newEntityId }, AZ::ComponentTypeList{ editorMeshComponentUuid });
            if (outcome.IsSuccess())
            {
                // Assign mesh asset.
                LmbrCentral::MeshComponentRequestBus::Event(newEntityId, &LmbrCentral::MeshComponentRequests::SetMeshAsset, meshId);

                Matrix34 tm;
                tm.SetIdentity();
                if (!vegetation->pRenderNode || !vegetation->pRenderNode->GetEntityStatObj(0, 0, &tm))
                {
                    // GetEntityStatObj is the only reliable way to get the correct transform
                    // this fallback method may have issues

                    // this precision loss is intended to mimic what the vegetation system does
                    const uint8 x = RAD2BYTE(vegetation->angleX);
                    const uint8 y = RAD2BYTE(vegetation->angleY);
                    const uint8 z = RAD2BYTE(vegetation->angle);
                    const float fx = BYTE2RAD(x);
                    const float fy = BYTE2RAD(y);
                    const float fz = BYTE2RAD(z);
                    tm = Matrix34::CreateRotationXYZ(Ang3(fx, fy, fz));

                    if (vegScale != 1.0f)
                    {
                        Matrix33 m33;
                        m33.SetIdentity();
                        m33.SetScale(Vec3(vegScale, vegScale, vegScale));
                        tm = m33 * tm;
                    }

                    tm.SetTranslation(vegetation->pos);
                }

                // Move entity to same transform.
                AZ::TransformBus::Event(newEntityId, &AZ::TransformInterface::SetWorldTM, LYTransformToAZTransform(tm));
            }
            else
            {
                AZ_WarningOnce("Editor", false, "Vegetation category %s could not be converted because mesh component could not be created.", vegetation->object->GetCategory().toUtf8().data());
            }
        }
    }
    break;
4 Likes