Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds the ability to generate UVs automatically during mesh import #15530

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,11 @@ namespace AZ
m_uvs.reserve(size);
}

void MeshVertexUVData::Clear()
{
m_uvs.clear();
}

void MeshVertexUVData::AppendUV(const AZ::Vector2& uv)
{
m_uvs.push_back(uv);
Expand Down
2 changes: 2 additions & 0 deletions Code/Tools/SceneAPI/SceneData/GraphData/MeshVertexUVData.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ namespace AZ
SCENE_DATA_API void ReserveContainerSpace(size_t size);
SCENE_DATA_API void AppendUV(const AZ::Vector2& uv);

SCENE_DATA_API void Clear();

SCENE_DATA_API void GetDebugOutput(AZ::SceneAPI::Utilities::DebugOutput& output) const override;
protected:
AZStd::vector<AZ::Vector2> m_uvs;
Expand Down
5 changes: 5 additions & 0 deletions Code/Tools/SceneAPI/SceneData/ManifestMetaInfoHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include <SceneAPI/SceneData/Rules/SkinRule.h>
#include <SceneAPI/SceneData/Rules/CoordinateSystemRule.h>
#include <SceneAPI/SceneData/Rules/TagRule.h>
#include <SceneAPI/SceneData/Rules/UVsRule.h>

namespace AZ
{
Expand Down Expand Up @@ -86,6 +87,10 @@ namespace AZ
{
modifiers.push_back(azrtti_typeid<CoordinateSystemRule>());
}
if (existingRules.find(SceneData::UVsRule::TYPEINFO_Uuid()) == existingRules.end())
{
modifiers.push_back(SceneData::UVsRule::TYPEINFO_Uuid());
}
if (existingRules.find(SceneData::TangentsRule::TYPEINFO_Uuid()) == existingRules.end())
{
modifiers.push_back(SceneData::TangentsRule::TYPEINFO_Uuid());
Expand Down
2 changes: 2 additions & 0 deletions Code/Tools/SceneAPI/SceneData/ReflectionRegistrar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include <SceneAPI/SceneData/Rules/ScriptProcessorRule.h>
#include <SceneAPI/SceneData/Rules/SkeletonProxyRule.h>
#include <SceneAPI/SceneData/Rules/TangentsRule.h>
#include <SceneAPI/SceneData/Rules/UVsRule.h>
#include <SceneAPI/SceneData/Rules/CoordinateSystemRule.h>
#include <SceneAPI/SceneData/Rules/TagRule.h>

Expand Down Expand Up @@ -75,6 +76,7 @@ namespace AZ
SceneData::SkeletonProxyRule::Reflect(context);
SceneData::SkinMeshAdvancedRule::Reflect(context);
SceneData::TangentsRule::Reflect(context);
SceneData::UVsRule::Reflect(context);
SceneData::CoordinateSystemRule::Reflect(context);
SceneData::TagRule::Reflect(context);

Expand Down
129 changes: 129 additions & 0 deletions Code/Tools/SceneAPI/SceneData/Rules/UVsRule.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/

#include <SceneAPI/SceneData/Rules/UVsRule.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/Serialization/EditContext.h>
#include <SceneAPI/SceneCore/Utilities/Reporting.h>
#include <AzCore/Settings/SettingsRegistry.h>

namespace AZ
{
namespace SceneAPI
{
namespace SceneData
{
static constexpr AZStd::string_view DefaultUVsGenerationMethodKeyIfNoRulePresent{
"/O3DE/SceneAPI/UVsGenerateComponent/DefaultGenerationMethodIfNoRulePresent"
};

static constexpr AZStd::string_view DefaultUVsGenerationMethodKeyWhenAddingNewRules{
"/O3DE/SceneAPI/UVsGenerateComponent/DefaultGenerationMethodWhenRuleIsPresent"
};


UVsRule::UVsRule()
: DataTypes::IRule()
{
m_generationMethod = GetDefaultGenerationMethodWhenAddingNewRule();
}

AZ::SceneAPI::DataTypes::UVsGenerationMethod GetGenerationMethodFromRegistry(
AZStd::string_view regKey, AZ::SceneAPI::DataTypes::UVsGenerationMethod defaultValue)
{
if (auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry != nullptr)
{
AZStd::string stringFromRegistry;
if (settingsRegistry->Get(stringFromRegistry, regKey))
{
const bool isCaseSensitive = false;
if (AZ::StringFunc::Equal(stringFromRegistry, "LeaveSceneDataAsIs", isCaseSensitive))
{
return AZ::SceneAPI::DataTypes::UVsGenerationMethod::LeaveSceneDataAsIs;
}
else if (AZ::StringFunc::Equal(stringFromRegistry, "SphericalProjection", isCaseSensitive))
{
return AZ::SceneAPI::DataTypes::UVsGenerationMethod::SphericalProjection;
}
else
{
AZ_Warning(
AZ::SceneAPI::Utilities::WarningWindow,
false,
"'%s' is not a valid default UV generation method. Check the value of " AZ_STRING_FORMAT " in your "
"settings registry, and change "
"it to 'LeaveSceneDataAsIs' or 'SphericalProjection'",
stringFromRegistry.c_str(),
AZ_STRING_ARG(regKey));
}
}
}
return defaultValue;
}

//! return the default method for when a new rule is explicitly created by script or user
AZ::SceneAPI::DataTypes::UVsGenerationMethod UVsRule::GetDefaultGenerationMethodWhenAddingNewRule()
{
// When someone goes to the effort of actually adding a new rule, make the default actually do something
return GetGenerationMethodFromRegistry(DefaultUVsGenerationMethodKeyWhenAddingNewRules,
AZ::SceneAPI::DataTypes::UVsGenerationMethod::SphericalProjection);
}

AZ::SceneAPI::DataTypes::UVsGenerationMethod UVsRule::GetDefaultGenerationMethodWithNoRule()
{
// when there is no rule on the mesh, do nothing by default
return GetGenerationMethodFromRegistry(DefaultUVsGenerationMethodKeyIfNoRulePresent,
AZ::SceneAPI::DataTypes::UVsGenerationMethod::LeaveSceneDataAsIs);
}

AZ::SceneAPI::DataTypes::UVsGenerationMethod UVsRule::GetGenerationMethod() const
{
return m_generationMethod;
}

bool UVsRule::GetReplaceExisting() const
{
return m_replaceExisting;
}

void UVsRule::Reflect(AZ::ReflectContext* context)
{
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
if (!serializeContext)
{
return;
}

serializeContext->Class<UVsRule, DataTypes::IRule>()
->Version(1)
->Field("generationMethod", &UVsRule::m_generationMethod)
->Field("replaceExisting", &UVsRule::m_replaceExisting);

AZ::EditContext* editContext = serializeContext->GetEditContext();
if (editContext)
{
editContext->Class<UVsRule>("UVs", "Specify how UVs are imported or generated.")
->ClassElement(Edit::ClassElements::EditorData, "")
->Attribute("AutoExpand", true)
->Attribute(AZ::Edit::Attributes::NameLabelOverride, "")
->DataElement(
AZ::Edit::UIHandlers::ComboBox,
&AZ::SceneAPI::SceneData::UVsRule::m_generationMethod,
"Generation Method",
"Specify the UVs generation method when UVs are generated.")
->EnumAttribute(AZ::SceneAPI::DataTypes::UVsGenerationMethod::LeaveSceneDataAsIs, "Do not generate UVs")
->EnumAttribute(AZ::SceneAPI::DataTypes::UVsGenerationMethod::SphericalProjection, "Spherical Projection")
->DataElement(0, &AZ::SceneAPI::SceneData::UVsRule::m_replaceExisting,
"Replace existing UVs",
"If true, will replace UVs in the source scene even if present in the incoming data.")
;
}
}
} // SceneData
} // SceneAPI
} // AZ
73 changes: 73 additions & 0 deletions Code/Tools/SceneAPI/SceneData/Rules/UVsRule.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/

#pragma once

#include <AzCore/Memory/SystemAllocator.h>
#include <SceneAPI/SceneCore/DataTypes/Rules/IRule.h>
#include <SceneAPI/SceneData/SceneDataConfiguration.h>

namespace AZ
{
class ReflectContext;

namespace SceneAPI
{
namespace Containers
{
class Scene;
}

namespace DataTypes
{
class IMeshVertexUVData;
enum class UVsGenerationMethod
{
LeaveSceneDataAsIs = 0, //! don't do anything to the scene
SphericalProjection = 1 //! generate UVs using simple spherical positional projection
};
}

namespace SceneData
{
//! The UVsRule class contains the settings for one particular instance of the "Generate UVs" modifier
//! on one particular mesh group in the scene.
class SCENE_DATA_CLASS UVsRule
: public DataTypes::IRule
{
public:
AZ_RTTI(UVsRule, "{79FB186C-E9B2-4569-9172-84B85DF81DB9}", DataTypes::IRule);
AZ_CLASS_ALLOCATOR(UVsRule, AZ::SystemAllocator)

SCENE_DATA_API UVsRule();
SCENE_DATA_API ~UVsRule() override = default;

SCENE_DATA_API AZ::SceneAPI::DataTypes::UVsGenerationMethod GetGenerationMethod() const;
SCENE_DATA_API bool GetReplaceExisting() const;

static void Reflect(ReflectContext* context);

// it can be useful to have a different default for when there is no rule ("do nothing" for example)
// versus if the user actually clicks a button or something to cause a rule to exist now, ie, actually do something
// useful.

//! Return the default method for UV Generation when a Generate UVs rule is attached as a modifier to a mesh group.
SCENE_DATA_API static AZ::SceneAPI::DataTypes::UVsGenerationMethod GetDefaultGenerationMethodWhenAddingNewRule();

//! Return the default method for when there is no Generate UVs rule attached to the mesh group.
//! this should probably be left as "do nothing" unless you want to auto-generate UVs for everything without UVs
SCENE_DATA_API static AZ::SceneAPI::DataTypes::UVsGenerationMethod GetDefaultGenerationMethodWithNoRule();

protected:
AZ::SceneAPI::DataTypes::UVsGenerationMethod m_generationMethod = AZ::SceneAPI::DataTypes::UVsGenerationMethod::LeaveSceneDataAsIs;
bool m_replaceExisting = false;

};
} // SceneData
} // SceneAPI
} // AZ
2 changes: 2 additions & 0 deletions Code/Tools/SceneAPI/SceneData/SceneData_files.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ set(FILES
Rules/TagRule.cpp
Rules/TangentsRule.h
Rules/TangentsRule.cpp
Rules/UVsRule.h
Rules/UVsRule.cpp
Rules/UnmodifiableRule.h
Rules/UnmodifiableRule.cpp
GraphData/CustomPropertyData.h
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ namespace AZ::SceneGenerationComponents
BindToCall(&TangentPreExportComponent::Register);
}

uint8_t TangentPreExportComponent::GetPriority() const
{
return AZ::SceneAPI::Events::CallProcessor::ProcessingPriority::LateProcessing;
}


void TangentPreExportComponent::Reflect(AZ::ReflectContext* context)
{
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ namespace AZ::SceneGenerationComponents

static void Reflect(AZ::ReflectContext* context);

// bumps Tangent export to later on in the generation phase, so that it can generate tangents after other rules have
// generated things like normals and UVs.

uint8_t GetPriority() const override;

AZ::SceneAPI::Events::ProcessingResult Register(AZ::SceneAPI::Events::GenerateAdditionEventContext& context);
};
} // namespace AZ::SceneGenerationComponents
Loading