Merge branch 'stabilization/2106' into cpack/2106-3p-manifest
This commit is contained in:
@@ -15,7 +15,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_
|
||||
TEST_SUITE main
|
||||
TEST_SERIAL
|
||||
PATH ${CMAKE_CURRENT_LIST_DIR}
|
||||
PYTEST_MARKS "not SUITE_sandbox and not SUITE_periodic and not SUITE_benchmark"
|
||||
PYTEST_MARKS "SUITE_main and not REQUIRES_gpu"
|
||||
TIMEOUT 1500
|
||||
RUNTIME_DEPENDENCIES
|
||||
Legacy::Editor
|
||||
@@ -30,7 +30,23 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_
|
||||
TEST_SUITE periodic
|
||||
TEST_SERIAL
|
||||
PATH ${CMAKE_CURRENT_LIST_DIR}
|
||||
PYTEST_MARKS "SUITE_periodic"
|
||||
PYTEST_MARKS "SUITE_periodic and not REQUIRES_gpu"
|
||||
TIMEOUT 1500
|
||||
RUNTIME_DEPENDENCIES
|
||||
Legacy::Editor
|
||||
AZ::AssetProcessor
|
||||
AutomatedTesting.Assets
|
||||
COMPONENT
|
||||
Editor
|
||||
)
|
||||
|
||||
ly_add_pytest(
|
||||
NAME AutomatedTesting::EditorTests_Main_GPU
|
||||
TEST_SUITE main
|
||||
TEST_SERIAL
|
||||
TEST_REQUIRES gpu
|
||||
PATH ${CMAKE_CURRENT_LIST_DIR}
|
||||
PYTEST_MARKS "SUITE_main and REQUIRES_gpu"
|
||||
TIMEOUT 1500
|
||||
RUNTIME_DEPENDENCIES
|
||||
Legacy::Editor
|
||||
|
||||
@@ -66,3 +66,35 @@ class TestBasicEditorWorkflows(object):
|
||||
timeout=log_monitor_timeout,
|
||||
auto_test_mode=False
|
||||
)
|
||||
|
||||
@pytest.mark.test_case_id("C6351273", "C6384955", "C16929880", "C15167490", "C15167491")
|
||||
@pytest.mark.SUITE_main
|
||||
@pytest.mark.REQUIRES_gpu
|
||||
def test_BasicEditorWorkflows_GPU_LevelEntityComponentCRUD(self, request, editor, level, launcher_platform):
|
||||
|
||||
# Skip test if running against Debug build
|
||||
if "debug" in internal_plugin.build_directory:
|
||||
pytest.skip("Does not execute against debug builds.")
|
||||
|
||||
expected_lines = [
|
||||
"Create and load new level: True",
|
||||
"New entity creation: True",
|
||||
"Create entity hierarchy: True",
|
||||
"Add component: True",
|
||||
"Component update: True",
|
||||
"Remove component: True",
|
||||
"Save and Export: True",
|
||||
"BasicEditorWorkflows_LevelEntityComponent: result=SUCCESS",
|
||||
]
|
||||
|
||||
hydra.launch_and_validate_results(
|
||||
request,
|
||||
test_directory,
|
||||
editor,
|
||||
"BasicEditorWorkflows_LevelEntityComponentCRUD.py",
|
||||
expected_lines,
|
||||
cfg_args=[level],
|
||||
timeout=log_monitor_timeout,
|
||||
auto_test_mode=False,
|
||||
null_renderer=False
|
||||
)
|
||||
|
||||
@@ -198,11 +198,13 @@ namespace AzFramework
|
||||
AZ::SerializeContext* m_serializeContext{ nullptr };
|
||||
//! The priority at which this call will be executed.
|
||||
SpawnablePriority m_priority{ SpawnablePriority_Default };
|
||||
//! Entity references are resolved by referring to the last entity spawned from a template entity in the spawnable. If this
|
||||
//! is set to false entities from previous spawn calls are not taken into account. If set to true entity references may be
|
||||
//! resolved to a previously spawned entity. A lookup table has to be constructed when true, which may negatively impact
|
||||
//! performance, especially if a large number of entities are present on a ticket.
|
||||
bool m_referencePreviouslySpawnedEntities{ false };
|
||||
//! Entity references are resolved by referring to the most recent entity spawned from a template entity in the spawnable.
|
||||
//! If the entity referred to hasn't been spawned yet, the reference will be resolved to the first one that *will* be spawned.
|
||||
//! If this flag is set to "true", the id mappings will persist across SpawnEntites calls, and the entity references will resolve
|
||||
//! correctly across them.
|
||||
//! When "false", the entity id mappings will be reset on this call, so entity references will only work within this call, or
|
||||
//! potentially with any subsequent SpawnEntities call where the flag is true once again.
|
||||
bool m_referencePreviouslySpawnedEntities{ true };
|
||||
};
|
||||
|
||||
struct DespawnAllEntitiesOptionalArgs final
|
||||
|
||||
@@ -250,10 +250,47 @@ namespace AzFramework
|
||||
AZ::Entity* SpawnableEntitiesManager::CloneSingleEntity(const AZ::Entity& entityTemplate,
|
||||
EntityIdMap& templateToCloneMap, AZ::SerializeContext& serializeContext)
|
||||
{
|
||||
return AZ::IdUtils::Remapper<AZ::EntityId, true>::CloneObjectAndGenerateNewIdsAndFixRefs(
|
||||
// If the same ID gets remapped more than once, preserve the original remapping instead of overwriting it.
|
||||
constexpr bool allowDuplicateIds = false;
|
||||
|
||||
return AZ::IdUtils::Remapper<AZ::EntityId, allowDuplicateIds>::CloneObjectAndGenerateNewIdsAndFixRefs(
|
||||
&entityTemplate, templateToCloneMap, &serializeContext);
|
||||
}
|
||||
|
||||
void SpawnableEntitiesManager::InitializeEntityIdMappings(
|
||||
const Spawnable::EntityList& entities, EntityIdMap& idMap, AZStd::unordered_set<AZ::EntityId>& previouslySpawned)
|
||||
{
|
||||
// Make sure we don't have any previous data lingering around.
|
||||
idMap.clear();
|
||||
previouslySpawned.clear();
|
||||
|
||||
idMap.reserve(entities.size());
|
||||
previouslySpawned.reserve(entities.size());
|
||||
|
||||
for (auto& entity : entities)
|
||||
{
|
||||
idMap.emplace(entity->GetId(), AZ::Entity::MakeId());
|
||||
}
|
||||
}
|
||||
|
||||
void SpawnableEntitiesManager::RefreshEntityIdMapping(
|
||||
const AZ::EntityId& entityId, EntityIdMap& idMap, AZStd::unordered_set<AZ::EntityId>& previouslySpawned)
|
||||
{
|
||||
if (previouslySpawned.contains(entityId))
|
||||
{
|
||||
// This entity has already been spawned at least once before, so we need to generate a new id for it and
|
||||
// preserve the new id to fix up any future entity references to this entity.
|
||||
idMap[entityId] = AZ::Entity::MakeId();
|
||||
}
|
||||
else
|
||||
{
|
||||
// This entity hasn't been spawned yet, so use the first id we've already generated for this entity and mark
|
||||
// it as spawned so we know not to reuse this id next time.
|
||||
previouslySpawned.emplace(entityId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool SpawnableEntitiesManager::ProcessRequest(SpawnAllEntitiesCommand& request)
|
||||
{
|
||||
Ticket& ticket = *request.m_ticket;
|
||||
@@ -269,18 +306,24 @@ namespace AzFramework
|
||||
const Spawnable::EntityList& entitiesToSpawn = ticket.m_spawnable->GetEntities();
|
||||
size_t entitiesToSpawnSize = entitiesToSpawn.size();
|
||||
|
||||
// Map keeps track of ids from template (spawnable) to clone (instance)
|
||||
// Allowing patch ups of fields referring to entityIds outside of a given entity
|
||||
EntityIdMap templateToCloneEntityIdMap;
|
||||
|
||||
// Reserve buffers
|
||||
spawnedEntities.reserve(spawnedEntities.size() + entitiesToSpawnSize);
|
||||
spawnedEntityIndices.reserve(spawnedEntityIndices.size() + entitiesToSpawnSize);
|
||||
templateToCloneEntityIdMap.reserve(entitiesToSpawnSize);
|
||||
|
||||
// Pre-generate the full set of entity id to new entity id mappings, so that during the clone operation below,
|
||||
// any entity references that point to a not-yet-cloned entity will still get their ids remapped correctly.
|
||||
// We clear out and regenerate the set of IDs on every SpawnAllEntities call, because presumably every entity reference
|
||||
// in every entity we're about to instantiate is intended to point to an entity in our newly-instantiated batch, regardless
|
||||
// of spawn order. If we didn't clear out the map, it would be possible for some entities here to have references to
|
||||
// previously-spawned entities from a previous SpawnEntities or SpawnAllEntities call.
|
||||
InitializeEntityIdMappings(entitiesToSpawn, ticket.m_entityIdReferenceMap, ticket.m_previouslySpawned);
|
||||
|
||||
for (size_t i = 0; i < entitiesToSpawnSize; ++i)
|
||||
{
|
||||
AZ::Entity* clone = CloneSingleEntity(*entitiesToSpawn[i], templateToCloneEntityIdMap, *request.m_serializeContext);
|
||||
// If this entity has previously been spawned, give it a new id in the reference map
|
||||
RefreshEntityIdMapping(entitiesToSpawn[i].get()->GetId(), ticket.m_entityIdReferenceMap, ticket.m_previouslySpawned);
|
||||
|
||||
AZ::Entity* clone = CloneSingleEntity(*entitiesToSpawn[i], ticket.m_entityIdReferenceMap, *request.m_serializeContext);
|
||||
AZ_Assert(clone != nullptr, "Failed to clone spawnable entity.");
|
||||
|
||||
spawnedEntities.emplace_back(clone);
|
||||
@@ -337,21 +380,17 @@ namespace AzFramework
|
||||
const Spawnable::EntityList& entitiesToSpawn = ticket.m_spawnable->GetEntities();
|
||||
size_t entitiesToSpawnSize = request.m_entityIndices.size();
|
||||
|
||||
// Reconstruct the template to entity mapping.
|
||||
EntityIdMap templateToCloneEntityIdMap;
|
||||
if (!request.m_referencePreviouslySpawnedEntities)
|
||||
if (ticket.m_entityIdReferenceMap.empty() || !request.m_referencePreviouslySpawnedEntities)
|
||||
{
|
||||
templateToCloneEntityIdMap.reserve(entitiesToSpawnSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
templateToCloneEntityIdMap.reserve(spawnedEntitiesInitialCount + entitiesToSpawnSize);
|
||||
SpawnableConstIndexEntityContainerView indexEntityView(
|
||||
spawnedEntities.begin(), spawnedEntityIndices.begin(), spawnedEntities.size());
|
||||
for (auto& entry : indexEntityView)
|
||||
{
|
||||
templateToCloneEntityIdMap.insert_or_assign(entitiesToSpawn[entry.GetIndex()]->GetId(), entry.GetEntity()->GetId());
|
||||
}
|
||||
// This map keeps track of ids from template (spawnable) to clone (instance) allowing patch ups of fields referring
|
||||
// to entityIds outside of a given entity.
|
||||
// We pre-generate the full set of entity id to new entity id mappings, so that during the clone operation below,
|
||||
// any entity references that point to a not-yet-cloned entity will still get their ids remapped correctly.
|
||||
// By default, we only initialize this map once because it needs to persist across multiple SpawnEntities calls, so
|
||||
// that reference fixups work even when the entity being referenced is spawned in a different SpawnEntities
|
||||
// (or SpawnAllEntities) call.
|
||||
// However, the caller can also choose to reset the map by passing in "m_referencePreviouslySpawnedEntities = false".
|
||||
InitializeEntityIdMappings(entitiesToSpawn, ticket.m_entityIdReferenceMap, ticket.m_previouslySpawned);
|
||||
}
|
||||
|
||||
spawnedEntities.reserve(spawnedEntities.size() + entitiesToSpawnSize);
|
||||
@@ -361,7 +400,12 @@ namespace AzFramework
|
||||
{
|
||||
if (index < entitiesToSpawn.size())
|
||||
{
|
||||
AZ::Entity* clone = CloneSingleEntity(*entitiesToSpawn[index], templateToCloneEntityIdMap, *request.m_serializeContext);
|
||||
// If this entity has previously been spawned, give it a new id in the reference map
|
||||
RefreshEntityIdMapping(
|
||||
entitiesToSpawn[index].get()->GetId(), ticket.m_entityIdReferenceMap, ticket.m_previouslySpawned);
|
||||
|
||||
AZ::Entity* clone =
|
||||
CloneSingleEntity(*entitiesToSpawn[index], ticket.m_entityIdReferenceMap, *request.m_serializeContext);
|
||||
AZ_Assert(clone != nullptr, "Failed to clone spawnable entity.");
|
||||
|
||||
spawnedEntities.push_back(clone);
|
||||
@@ -451,9 +495,11 @@ namespace AzFramework
|
||||
ticket.m_spawnedEntities.clear();
|
||||
const Spawnable::EntityList& entities = request.m_spawnable->GetEntities();
|
||||
|
||||
// Map keeps track of ids from template (spawnable) to clone (instance)
|
||||
// Allowing patch ups of fields referring to entityIds outside of a given entity
|
||||
EntityIdMap templateToCloneEntityIdMap;
|
||||
// Pre-generate the full set of entity id to new entity id mappings, so that during the clone operation below,
|
||||
// any entity references that point to a not-yet-cloned entity will still get their ids remapped correctly.
|
||||
// This map is intentionally cleared out and regenerated here to ensure that we're starting fresh with mappings that
|
||||
// match the new set of template entities getting spawned.
|
||||
InitializeEntityIdMappings(entities, ticket.m_entityIdReferenceMap, ticket.m_previouslySpawned);
|
||||
|
||||
if (ticket.m_loadAll)
|
||||
{
|
||||
@@ -461,11 +507,13 @@ namespace AzFramework
|
||||
// to spawn every entity, simply start over.
|
||||
ticket.m_spawnedEntityIndices.clear();
|
||||
size_t entitiesToSpawnSize = entities.size();
|
||||
templateToCloneEntityIdMap.reserve(entitiesToSpawnSize);
|
||||
|
||||
for (size_t i = 0; i < entitiesToSpawnSize; ++i)
|
||||
{
|
||||
AZ::Entity* clone = CloneSingleEntity(*entities[i], templateToCloneEntityIdMap, *request.m_serializeContext);
|
||||
// If this entity has previously been spawned, give it a new id in the reference map
|
||||
RefreshEntityIdMapping(entities[i].get()->GetId(), ticket.m_entityIdReferenceMap, ticket.m_previouslySpawned);
|
||||
|
||||
AZ::Entity* clone = CloneSingleEntity(*entities[i], ticket.m_entityIdReferenceMap, *request.m_serializeContext);
|
||||
AZ_Assert(clone != nullptr, "Failed to clone spawnable entity.");
|
||||
|
||||
ticket.m_spawnedEntities.push_back(clone);
|
||||
@@ -475,7 +523,7 @@ namespace AzFramework
|
||||
else
|
||||
{
|
||||
size_t entitiesSize = entities.size();
|
||||
templateToCloneEntityIdMap.reserve(entitiesSize);
|
||||
|
||||
for (size_t index : ticket.m_spawnedEntityIndices)
|
||||
{
|
||||
// It's possible for the new spawnable to have a different number of entities, so guard against this.
|
||||
@@ -483,7 +531,10 @@ namespace AzFramework
|
||||
// detected and will result in the incorrect entities being spawned.
|
||||
if (index < entitiesSize)
|
||||
{
|
||||
AZ::Entity* clone = CloneSingleEntity(*entities[index], templateToCloneEntityIdMap, *request.m_serializeContext);
|
||||
// If this entity has previously been spawned, give it a new id in the reference map
|
||||
RefreshEntityIdMapping(entities[index].get()->GetId(), ticket.m_entityIdReferenceMap, ticket.m_previouslySpawned);
|
||||
|
||||
AZ::Entity* clone = CloneSingleEntity(*entities[index], ticket.m_entityIdReferenceMap, *request.m_serializeContext);
|
||||
AZ_Assert(clone != nullptr, "Failed to clone spawnable entity.");
|
||||
ticket.m_spawnedEntities.push_back(clone);
|
||||
}
|
||||
|
||||
@@ -85,6 +85,22 @@ namespace AzFramework
|
||||
AZ_CLASS_ALLOCATOR(Ticket, AZ::ThreadPoolAllocator, 0);
|
||||
static constexpr uint32_t Processing = AZStd::numeric_limits<uint32_t>::max();
|
||||
|
||||
//! Map of template entity ids to their associated instance ids.
|
||||
//! Tickets can be used to spawn the same template entities multiple times, in any order, across multiple calls.
|
||||
//! Since template entities can reference other entities, this map is used to fix up those references across calls
|
||||
//! using the following policy:
|
||||
//! - Entities referencing an entity that hasn't been spawned yet will get a reference to the id that *will* be used
|
||||
//! the first time that entity will be spawned. The reference will be invalid until that entity is spawned, but
|
||||
//! will be valid if/when it gets spawned.
|
||||
//! - Entities referencing an entity that *has* been spawned will get a reference to the id that was *last* used to
|
||||
//! spawn the entity.
|
||||
//! Note that this implies a certain level of non-determinism when spawning across calls, because the entity references
|
||||
//! will be based on the order in which the SpawnEntity calls occur, which can be affected by things like priority.
|
||||
EntityIdMap m_entityIdReferenceMap;
|
||||
//! For this to work, we also need to keep track of whether or not each entity has been spawned at least once, so we know
|
||||
//! whether or not to replace the id in the map when spawning a new instance of that entity.
|
||||
AZStd::unordered_set<AZ::EntityId> m_previouslySpawned;
|
||||
|
||||
AZStd::vector<AZ::Entity*> m_spawnedEntities;
|
||||
AZStd::vector<size_t> m_spawnedEntityIndices;
|
||||
AZ::Data::Asset<Spawnable> m_spawnable;
|
||||
@@ -194,6 +210,15 @@ namespace AzFramework
|
||||
bool ProcessRequest(BarrierCommand& request);
|
||||
bool ProcessRequest(DestroyTicketCommand& request);
|
||||
|
||||
//! Generate a base set of original-to-new entity ID mappings to use during spawning.
|
||||
//! Since Entity references get fixed up on an entity-by-entity basis while spawning, it's important to have the complete
|
||||
//! set of new IDs available right at the start. This way, entities that refer to other entities that haven't spawned yet
|
||||
//! will still get their references remapped correctly.
|
||||
void InitializeEntityIdMappings(
|
||||
const Spawnable::EntityList& entities, EntityIdMap& idMap, AZStd::unordered_set<AZ::EntityId>& previouslySpawned);
|
||||
void RefreshEntityIdMapping(
|
||||
const AZ::EntityId& entityId, EntityIdMap& idMap, AZStd::unordered_set<AZ::EntityId>& previouslySpawned);
|
||||
|
||||
Queue m_highPriorityQueue;
|
||||
Queue m_regularPriorityQueue;
|
||||
|
||||
|
||||
@@ -32,6 +32,33 @@ namespace UnitTest
|
||||
}
|
||||
};
|
||||
|
||||
// Test component that has a reference to a different entity for use in validating per-instance entity id fixups.
|
||||
class ComponentWithEntityReference : public AZ::Component
|
||||
{
|
||||
public:
|
||||
AZ_COMPONENT(ComponentWithEntityReference, "{CF5FDE59-86E5-40B6-9272-BBC1C4AFD061}");
|
||||
|
||||
void Activate() override
|
||||
{
|
||||
}
|
||||
|
||||
void Deactivate() override
|
||||
{
|
||||
}
|
||||
|
||||
static void Reflect(AZ::ReflectContext* reflection)
|
||||
{
|
||||
if (auto* serializeContext = azrtti_cast<AZ::SerializeContext*>(reflection))
|
||||
{
|
||||
serializeContext->Class<ComponentWithEntityReference, AZ::Component>()
|
||||
->Field("EntityReference", &ComponentWithEntityReference::m_entityReference)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
AZ::EntityId m_entityReference;
|
||||
};
|
||||
|
||||
class SpawnableEntitiesManagerTest : public AllocatorsFixture
|
||||
{
|
||||
public:
|
||||
@@ -42,6 +69,8 @@ namespace UnitTest
|
||||
m_application = new TestApplication();
|
||||
AZ::ComponentApplication::Descriptor descriptor;
|
||||
m_application->Start(descriptor);
|
||||
m_application->RegisterComponentDescriptor(ComponentWithEntityReference::CreateDescriptor());
|
||||
|
||||
// Without this, the user settings component would attempt to save on finalize/shutdown. Since the file is
|
||||
// shared across the whole engine, if multiple tests are run in parallel, the saving could cause a crash
|
||||
// in the unit tests.
|
||||
@@ -80,6 +109,7 @@ namespace UnitTest
|
||||
void FillSpawnable(size_t numElements)
|
||||
{
|
||||
AzFramework::Spawnable::EntityList& entities = m_spawnable->GetEntities();
|
||||
entities.clear();
|
||||
entities.reserve(numElements);
|
||||
for (size_t i=0; i<numElements; ++i)
|
||||
{
|
||||
@@ -123,6 +153,94 @@ namespace UnitTest
|
||||
}
|
||||
}
|
||||
|
||||
enum class EntityReferenceScheme
|
||||
{
|
||||
AllReferenceFirst,
|
||||
AllReferenceLast,
|
||||
AllReferenceThemselves,
|
||||
AllReferenceNextCircular,
|
||||
AllReferencePreviousCircular
|
||||
};
|
||||
|
||||
void CreateEntityReferences(EntityReferenceScheme refScheme)
|
||||
{
|
||||
AzFramework::Spawnable::EntityList& entities = m_spawnable->GetEntities();
|
||||
size_t numElements = entities.size();
|
||||
for (size_t i = 0; i < numElements; ++i)
|
||||
{
|
||||
AZStd::unique_ptr<AZ::Entity>& entity = entities[i];
|
||||
auto component = entity->CreateComponent<ComponentWithEntityReference>();
|
||||
switch (refScheme)
|
||||
{
|
||||
case EntityReferenceScheme::AllReferenceFirst :
|
||||
component->m_entityReference = entities[0]->GetId();
|
||||
break;
|
||||
case EntityReferenceScheme::AllReferenceLast:
|
||||
component->m_entityReference = entities[numElements - 1]->GetId();
|
||||
break;
|
||||
case EntityReferenceScheme::AllReferenceThemselves:
|
||||
component->m_entityReference = entities[i]->GetId();
|
||||
break;
|
||||
case EntityReferenceScheme::AllReferenceNextCircular:
|
||||
component->m_entityReference = entities[(i + 1) % numElements]->GetId();
|
||||
break;
|
||||
case EntityReferenceScheme::AllReferencePreviousCircular:
|
||||
component->m_entityReference = entities[(i + numElements - 1) % numElements]->GetId();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Verify that the entity references are pointing to the correct other entities within the same spawn batch.
|
||||
// A "spawn batch" is the set of entities produced for each SpawnAllEntities command.
|
||||
void ValidateEntityReferences(
|
||||
EntityReferenceScheme refScheme, size_t entitiesPerBatch, AzFramework::SpawnableConstEntityContainerView entities)
|
||||
{
|
||||
size_t numElements = entities.size();
|
||||
|
||||
for (size_t i = 0; i < numElements; ++i)
|
||||
{
|
||||
// Calculate the element offset that's the start of each batch of entities spawned.
|
||||
size_t curSpawnBatch = i / entitiesPerBatch;
|
||||
size_t curBatchOffset = curSpawnBatch * entitiesPerBatch;
|
||||
size_t curBatchIndex = i - curBatchOffset;
|
||||
|
||||
const AZ::Entity* const entity = *(entities.begin() + i);
|
||||
|
||||
auto component = entity->FindComponent<ComponentWithEntityReference>();
|
||||
ASSERT_NE(nullptr, component);
|
||||
AZ::EntityId comparisonId;
|
||||
// Ids should be local to a batch, so each of these will be compared within a batch of entities, not globally across
|
||||
// the entire set.
|
||||
switch (refScheme)
|
||||
{
|
||||
case EntityReferenceScheme::AllReferenceFirst:
|
||||
// Compare against the first entity in each batch
|
||||
comparisonId = (*(entities.begin() + curBatchOffset))->GetId();
|
||||
break;
|
||||
case EntityReferenceScheme::AllReferenceLast:
|
||||
// Compare against the last entity in each batch
|
||||
comparisonId = (*(entities.begin() + curBatchOffset + (entitiesPerBatch - 1)))->GetId();
|
||||
break;
|
||||
case EntityReferenceScheme::AllReferenceThemselves:
|
||||
// Compare against itself
|
||||
comparisonId = entity->GetId();
|
||||
break;
|
||||
case EntityReferenceScheme::AllReferenceNextCircular:
|
||||
// Compare against the next entity in each batch, looping around so that the last entity in the batch should refer
|
||||
// to the first entity in the batch.
|
||||
comparisonId = (*(entities.begin() + curBatchOffset + ((curBatchIndex + 1) % entitiesPerBatch)))->GetId();
|
||||
break;
|
||||
case EntityReferenceScheme::AllReferencePreviousCircular:
|
||||
// Compare against the previous entity in each batch, looping around so that the first entity in the batch should refer
|
||||
// to the last entity in the batch.
|
||||
comparisonId = (*(entities.begin() + curBatchOffset + ((curBatchIndex + numElements - 1) % entitiesPerBatch)))->GetId();
|
||||
break;
|
||||
}
|
||||
EXPECT_EQ(comparisonId, component->m_entityReference);
|
||||
}
|
||||
};
|
||||
|
||||
protected:
|
||||
AZ::Data::Asset<AzFramework::Spawnable>* m_spawnableAsset { nullptr };
|
||||
AzFramework::SpawnableEntitiesManager* m_manager { nullptr };
|
||||
@@ -185,6 +303,73 @@ namespace UnitTest
|
||||
m_manager->ProcessQueue(AzFramework::SpawnableEntitiesManager::CommandQueuePriority::Regular);
|
||||
}
|
||||
|
||||
TEST_F(SpawnableEntitiesManagerTest, SpawnAllEntities_AllEntitiesReferenceOtherEntities_EntityIdsAreMappedCorrectly)
|
||||
{
|
||||
// This tests that entity id references get mapped correctly in a SpawnAllEntities call whether they're forward referencing
|
||||
// in the list, backwards referencing, or self-referencing. The circular tests are to ensure the implementation works regardless
|
||||
// of entity ordering.
|
||||
for (EntityReferenceScheme refScheme : {
|
||||
EntityReferenceScheme::AllReferenceFirst, EntityReferenceScheme::AllReferenceLast,
|
||||
EntityReferenceScheme::AllReferenceThemselves, EntityReferenceScheme::AllReferenceNextCircular,
|
||||
EntityReferenceScheme::AllReferencePreviousCircular })
|
||||
{
|
||||
constexpr size_t NumEntities = 4;
|
||||
FillSpawnable(NumEntities);
|
||||
CreateEntityReferences(refScheme);
|
||||
|
||||
auto callback = [this, refScheme, NumEntities]
|
||||
(AzFramework::EntitySpawnTicket::Id, AzFramework::SpawnableConstEntityContainerView entities)
|
||||
{
|
||||
ValidateEntityReferences(refScheme, NumEntities, entities);
|
||||
};
|
||||
AzFramework::SpawnAllEntitiesOptionalArgs optionalArgs;
|
||||
optionalArgs.m_completionCallback = AZStd::move(callback);
|
||||
m_manager->SpawnAllEntities(*m_ticket, AZStd::move(optionalArgs));
|
||||
m_manager->ProcessQueue(AzFramework::SpawnableEntitiesManager::CommandQueuePriority::Regular);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(SpawnableEntitiesManagerTest, SpawnAllEntities_AllEntitiesReferenceOtherEntities_EntityIdsOnlyReferWithinASingleCall)
|
||||
{
|
||||
// This tests that entity id references get mapped correctly with multiple SpawnAllEntities calls. Each call should only map
|
||||
// the entities to other entities within the same call, regardless of forward or backward mapping.
|
||||
// For example, suppose entities 1, 2, and 3 refer to 4. In the first SpawnAllEntities call, entities 1-3 will refer to 4.
|
||||
// In the second SpawnAllEntities call, entities 1-3 will refer to the second 4, not the previously-spawned 4.
|
||||
for (EntityReferenceScheme refScheme :
|
||||
{ EntityReferenceScheme::AllReferenceFirst, EntityReferenceScheme::AllReferenceLast,
|
||||
EntityReferenceScheme::AllReferenceThemselves, EntityReferenceScheme::AllReferenceNextCircular,
|
||||
EntityReferenceScheme::AllReferencePreviousCircular
|
||||
})
|
||||
{
|
||||
// Make sure we start with a fresh ticket each time, or else each iteration through this loop would continue to build up
|
||||
// more and more entities.
|
||||
delete m_ticket;
|
||||
m_ticket = new AzFramework::EntitySpawnTicket(*m_spawnableAsset);
|
||||
|
||||
constexpr size_t NumEntities = 4;
|
||||
FillSpawnable(NumEntities);
|
||||
CreateEntityReferences(refScheme);
|
||||
|
||||
auto callback = [this, refScheme, NumEntities]
|
||||
(AzFramework::EntitySpawnTicket::Id, AzFramework::SpawnableConstEntityContainerView entities)
|
||||
{
|
||||
ValidateEntityReferences(refScheme, NumEntities, entities);
|
||||
};
|
||||
|
||||
// Spawn twice.
|
||||
constexpr size_t NumSpawnAllCalls = 2;
|
||||
for (int spawns = 0; spawns < NumSpawnAllCalls; spawns++)
|
||||
{
|
||||
AzFramework::SpawnAllEntitiesOptionalArgs optionalArgs;
|
||||
optionalArgs.m_completionCallback = AZStd::move(callback);
|
||||
m_manager->SpawnAllEntities(*m_ticket, AZStd::move(optionalArgs));
|
||||
}
|
||||
|
||||
m_manager->ListEntities(*m_ticket, callback);
|
||||
m_manager->ProcessQueue(AzFramework::SpawnableEntitiesManager::CommandQueuePriority::Regular);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(SpawnableEntitiesManagerTest, SpawnAllEntities_DeleteTicketBeforeCall_NoCrash)
|
||||
{
|
||||
{
|
||||
@@ -363,6 +548,180 @@ namespace UnitTest
|
||||
m_manager->ProcessQueue(AzFramework::SpawnableEntitiesManager::CommandQueuePriority::Regular);
|
||||
}
|
||||
|
||||
TEST_F(SpawnableEntitiesManagerTest, SpawnEntities_AllEntitiesReferenceOtherEntities_ForwardReferencesWorkInSingleCall)
|
||||
{
|
||||
constexpr EntityReferenceScheme refScheme = EntityReferenceScheme::AllReferenceNextCircular;
|
||||
constexpr size_t NumEntities = 4;
|
||||
FillSpawnable(NumEntities);
|
||||
CreateEntityReferences(refScheme);
|
||||
|
||||
auto callback =
|
||||
[this, refScheme, NumEntities](AzFramework::EntitySpawnTicket::Id, AzFramework::SpawnableConstEntityContainerView entities)
|
||||
{
|
||||
ValidateEntityReferences(refScheme, NumEntities, entities);
|
||||
};
|
||||
|
||||
// Verify that by default, entities that refer to other entities that haven't been spawned yet have the correct references
|
||||
// when the spawning all occurs in the same call
|
||||
m_manager->SpawnEntities(*m_ticket, { 0, 1, 2, 3 });
|
||||
m_manager->ListEntities(*m_ticket, callback);
|
||||
m_manager->ProcessQueue(AzFramework::SpawnableEntitiesManager::CommandQueuePriority::Regular);
|
||||
}
|
||||
|
||||
TEST_F(SpawnableEntitiesManagerTest, SpawnEntities_AllEntitiesReferenceOtherEntities_ForwardReferencesWorkAcrossCalls)
|
||||
{
|
||||
constexpr EntityReferenceScheme refScheme = EntityReferenceScheme::AllReferenceNextCircular;
|
||||
constexpr size_t NumEntities = 4;
|
||||
FillSpawnable(NumEntities);
|
||||
CreateEntityReferences(refScheme);
|
||||
|
||||
auto callback =
|
||||
[this, refScheme, NumEntities](AzFramework::EntitySpawnTicket::Id, AzFramework::SpawnableConstEntityContainerView entities)
|
||||
{
|
||||
ValidateEntityReferences(refScheme, NumEntities, entities);
|
||||
};
|
||||
|
||||
// Verify that by default, entities that refer to other entities that haven't been spawned yet have the correct references
|
||||
// even when the spawning is across multiple calls
|
||||
m_manager->SpawnEntities(*m_ticket, { 0 });
|
||||
m_manager->SpawnEntities(*m_ticket, { 1 });
|
||||
m_manager->SpawnEntities(*m_ticket, { 2 });
|
||||
m_manager->SpawnEntities(*m_ticket, { 3 });
|
||||
m_manager->ListEntities(*m_ticket, callback);
|
||||
m_manager->ProcessQueue(AzFramework::SpawnableEntitiesManager::CommandQueuePriority::Regular);
|
||||
}
|
||||
|
||||
TEST_F(SpawnableEntitiesManagerTest, SpawnEntities_AllEntitiesReferenceOtherEntities_ReferencesPointToFirstOrLatest)
|
||||
{
|
||||
// With SpawnEntities, entity references should either refer to the first entity that *will* be spawned, or the last entity
|
||||
// that *has* been spawned. This test will create entities 0 1 2 3 that all refer to entity 3, and it will create two batches
|
||||
// of those. In the first batch, they'll forward-reference. In the second batch, they should backward-reference, except for
|
||||
// the second entity 3, which will now refer to itself as the last one that's been spawned.
|
||||
constexpr EntityReferenceScheme refScheme = EntityReferenceScheme::AllReferenceLast;
|
||||
constexpr size_t NumEntities = 4;
|
||||
FillSpawnable(NumEntities);
|
||||
CreateEntityReferences(refScheme);
|
||||
|
||||
auto callback =
|
||||
[this, refScheme, NumEntities](AzFramework::EntitySpawnTicket::Id, AzFramework::SpawnableConstEntityContainerView entities)
|
||||
{
|
||||
size_t numElements = entities.size();
|
||||
|
||||
for (size_t i = 0; i < numElements; ++i)
|
||||
{
|
||||
const AZ::Entity* const entity = *(entities.begin() + i);
|
||||
|
||||
auto component = entity->FindComponent<ComponentWithEntityReference>();
|
||||
ASSERT_NE(nullptr, component);
|
||||
AZ::EntityId comparisonId;
|
||||
if (i < (numElements - 1))
|
||||
{
|
||||
// There are two batches of NumEntities elements. Every entity should either forward-reference or backward-reference
|
||||
// to the last entity of the first batch, except for the very last entity of the second batch, which should reference
|
||||
// itself.
|
||||
comparisonId = (*(entities.begin() + (NumEntities- 1)))->GetId();
|
||||
}
|
||||
else
|
||||
{
|
||||
// The very last entity of the second batch should reference itself because it's now the latest instance of that
|
||||
// entity to be spawned.
|
||||
comparisonId = entity->GetId();
|
||||
}
|
||||
|
||||
EXPECT_EQ(comparisonId, component->m_entityReference);
|
||||
}
|
||||
};
|
||||
|
||||
// Create 2 batches of forward references. In the first batch, entities 0 1 2 will point forward to 3. In the second batch,
|
||||
// entities 0 1 2 will point *backward* to the first 3, and the second entity 3 will point to itself.
|
||||
m_manager->SpawnEntities(*m_ticket, { 0, 1, 2, 3 });
|
||||
m_manager->SpawnEntities(*m_ticket, { 0, 1, 2, 3 });
|
||||
m_manager->ListEntities(*m_ticket, callback);
|
||||
m_manager->ProcessQueue(AzFramework::SpawnableEntitiesManager::CommandQueuePriority::Regular);
|
||||
}
|
||||
|
||||
TEST_F(SpawnableEntitiesManagerTest, SpawnEntities_AllEntitiesReferenceOtherEntities_MultipleSpawnsInSameCallReferenceCorrectly)
|
||||
{
|
||||
// With SpawnEntities, entity references should either refer to the first entity that *will* be spawned, or the last entity
|
||||
// that *has* been spawned. This test will create entities 0 1 2 3 that all refer to entity 3, and it will create three sets
|
||||
// of those in the same call, with the following results:
|
||||
// - The first 0 1 2 will forward-reference to the first 3
|
||||
// - The first 3 will reference itself
|
||||
// - The second 0 1 2 will backwards-reference to the first 3
|
||||
// - The second 3 will reference itself
|
||||
// - The third 0 1 2 will backwards-reference to the second 3
|
||||
// - The third 3 will reference itself
|
||||
constexpr EntityReferenceScheme refScheme = EntityReferenceScheme::AllReferenceLast;
|
||||
constexpr size_t NumEntities = 4;
|
||||
FillSpawnable(NumEntities);
|
||||
CreateEntityReferences(refScheme);
|
||||
|
||||
auto callback =
|
||||
[this, refScheme, NumEntities](AzFramework::EntitySpawnTicket::Id, AzFramework::SpawnableConstEntityContainerView entities)
|
||||
{
|
||||
size_t numElements = entities.size();
|
||||
|
||||
for (size_t i = 0; i < numElements; ++i)
|
||||
{
|
||||
const AZ::Entity* const entity = *(entities.begin() + i);
|
||||
|
||||
auto component = entity->FindComponent<ComponentWithEntityReference>();
|
||||
ASSERT_NE(nullptr, component);
|
||||
AZ::EntityId comparisonId;
|
||||
|
||||
if (i < ((NumEntities * 2) - 1))
|
||||
{
|
||||
// The first 7 entities (0 1 2 3 0 1 2) will all refer to the 4th one (1st '3').
|
||||
comparisonId = (*(entities.begin() + (NumEntities - 1)))->GetId();
|
||||
}
|
||||
else if (i < (numElements - 1))
|
||||
{
|
||||
// The next 4 entities (3 0 1 2) will all refer to the 8th one (2nd '3').
|
||||
comparisonId = (*(entities.begin() + ((NumEntities * 2) - 1)))->GetId();
|
||||
}
|
||||
else
|
||||
{
|
||||
// The very last entity (3) will reference itself (3rd '3').
|
||||
comparisonId = entity->GetId();
|
||||
}
|
||||
|
||||
EXPECT_EQ(comparisonId, component->m_entityReference);
|
||||
}
|
||||
};
|
||||
|
||||
// Create the 3 batches of entities 0, 1, 2, 3. The entity references should work as described at the top of the test.
|
||||
m_manager->SpawnEntities(*m_ticket, { 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3 });
|
||||
m_manager->ListEntities(*m_ticket, callback);
|
||||
m_manager->ProcessQueue(AzFramework::SpawnableEntitiesManager::CommandQueuePriority::Regular);
|
||||
}
|
||||
|
||||
TEST_F(SpawnableEntitiesManagerTest, SpawnEntities_AllEntitiesReferenceOtherEntities_OptionalFlagClearsReferenceMap)
|
||||
{
|
||||
constexpr EntityReferenceScheme refScheme = EntityReferenceScheme::AllReferenceLast;
|
||||
constexpr size_t NumEntities = 4;
|
||||
FillSpawnable(NumEntities);
|
||||
CreateEntityReferences(refScheme);
|
||||
|
||||
auto callback =
|
||||
[this, refScheme, NumEntities](AzFramework::EntitySpawnTicket::Id, AzFramework::SpawnableConstEntityContainerView entities)
|
||||
{
|
||||
ValidateEntityReferences(refScheme, NumEntities, entities);
|
||||
};
|
||||
|
||||
// By setting the "referencePreviouslySpawnedEntities" flag to false, the map will get cleared on each call, so in both batches
|
||||
// the entities will forward-reference to the last entity in the batch. If the flag were true, entities 0 1 2 in the second
|
||||
// batch would refer backwards to the first entity 3.
|
||||
|
||||
AzFramework::SpawnEntitiesOptionalArgs optionalArgsSecondBatch;
|
||||
optionalArgsSecondBatch.m_completionCallback = AZStd::move(callback);
|
||||
optionalArgsSecondBatch.m_referencePreviouslySpawnedEntities = false;
|
||||
|
||||
m_manager->SpawnEntities(*m_ticket, { 0, 1, 2, 3 }, optionalArgsSecondBatch);
|
||||
m_manager->SpawnEntities(*m_ticket, { 0, 1, 2, 3 }, AZStd::move(optionalArgsSecondBatch));
|
||||
m_manager->ListEntities(*m_ticket, callback);
|
||||
m_manager->ProcessQueue(AzFramework::SpawnableEntitiesManager::CommandQueuePriority::Regular);
|
||||
}
|
||||
|
||||
TEST_F(SpawnableEntitiesManagerTest, SpawnEntities_DeleteTicketBeforeCall_NoCrash)
|
||||
{
|
||||
{
|
||||
|
||||
@@ -82,11 +82,11 @@ namespace AZ
|
||||
RPI::Cullable m_cullable;
|
||||
MaterialAssignmentMap m_materialAssignments;
|
||||
|
||||
MeshHandleDescriptor m_descriptor;
|
||||
Data::Instance<RPI::Model> m_model;
|
||||
|
||||
//! A reference to the original model asset in case it got cloned before creating the model instance.
|
||||
Data::Asset<RPI::ModelAsset> m_originalModelAsset;
|
||||
MeshFeatureProcessorInterface::RequiresCloneCallback m_requiresCloningCallback;
|
||||
|
||||
Data::Instance<RPI::ShaderResourceGroup> m_shaderResourceGroup;
|
||||
AZStd::unique_ptr<MeshLoader> m_meshLoader;
|
||||
@@ -99,10 +99,7 @@ namespace AZ
|
||||
bool m_cullableNeedsRebuild = false;
|
||||
bool m_objectSrgNeedsUpdate = true;
|
||||
bool m_excludeFromReflectionCubeMaps = false;
|
||||
bool m_skinnedMeshWithMotion = false;
|
||||
bool m_rayTracingEnabled = true;
|
||||
bool m_visible = true;
|
||||
bool m_useForwardPassIblSpecular = false;
|
||||
bool m_hasForwardPassIblSpecularMaterial = false;
|
||||
};
|
||||
|
||||
@@ -132,17 +129,11 @@ namespace AZ
|
||||
void OnEndPrepareRender() override;
|
||||
|
||||
MeshHandle AcquireMesh(
|
||||
const Data::Asset<RPI::ModelAsset>& modelAsset,
|
||||
const MaterialAssignmentMap& materials = {},
|
||||
bool skinnedMeshWithMotion = false,
|
||||
bool rayTracingEnabled = true,
|
||||
RequiresCloneCallback requiresCloneCallback = {}) override;
|
||||
const MeshHandleDescriptor& descriptor,
|
||||
const MaterialAssignmentMap& materials = {}) override;
|
||||
MeshHandle AcquireMesh(
|
||||
const Data::Asset<RPI::ModelAsset> &modelAsset,
|
||||
const Data::Instance<RPI::Material>& material,
|
||||
bool skinnedMeshWithMotion = false,
|
||||
bool rayTracingEnabled = true,
|
||||
RequiresCloneCallback requiresCloneCallback = {}) override;
|
||||
const MeshHandleDescriptor& descriptor,
|
||||
const Data::Instance<RPI::Material>& material) override;
|
||||
bool ReleaseMesh(MeshHandle& meshHandle) override;
|
||||
MeshHandle CloneMesh(const MeshHandle& meshHandle) override;
|
||||
|
||||
|
||||
+16
-11
@@ -26,6 +26,18 @@ namespace AZ
|
||||
{
|
||||
class MeshDataInstance;
|
||||
|
||||
//! Settings to apply to a mesh handle when acquiring it for the first time
|
||||
struct MeshHandleDescriptor
|
||||
{
|
||||
using RequiresCloneCallback = AZStd::function<bool(const Data::Asset<RPI::ModelAsset>& modelAsset)>;
|
||||
|
||||
Data::Asset<RPI::ModelAsset> m_modelAsset;
|
||||
bool m_isSkinnedMeshWithMotion = false;
|
||||
bool m_isRayTracingEnabled = true;
|
||||
bool m_useForwardPassIblSpecular = false;
|
||||
RequiresCloneCallback m_requiresCloneCallback = {};
|
||||
};
|
||||
|
||||
//! MeshFeatureProcessorInterface provides an interface to acquire and release a MeshHandle from the underlying MeshFeatureProcessor
|
||||
class MeshFeatureProcessorInterface
|
||||
: public RPI::FeatureProcessor
|
||||
@@ -35,23 +47,16 @@ namespace AZ
|
||||
|
||||
using MeshHandle = StableDynamicArrayHandle<MeshDataInstance>;
|
||||
using ModelChangedEvent = Event<const Data::Instance<RPI::Model>>;
|
||||
using RequiresCloneCallback = AZStd::function<bool(const Data::Asset<RPI::ModelAsset>& modelAsset)>;
|
||||
|
||||
//! Acquires a model with an optional collection of material assignments.
|
||||
//! @param requiresCloneCallback The callback indicates whether cloning is required for a given model asset.
|
||||
virtual MeshHandle AcquireMesh(
|
||||
const Data::Asset<RPI::ModelAsset>& modelAsset,
|
||||
const MaterialAssignmentMap& materials = {},
|
||||
bool skinnedMeshWithMotion = false,
|
||||
bool rayTracingEnabled = true,
|
||||
RequiresCloneCallback requiresCloneCallback = {}) = 0;
|
||||
const MeshHandleDescriptor& descriptor,
|
||||
const MaterialAssignmentMap& materials = {}) = 0;
|
||||
//! Acquires a model with a single material applied to all its meshes.
|
||||
virtual MeshHandle AcquireMesh(
|
||||
const Data::Asset<RPI::ModelAsset>& modelAsset,
|
||||
const Data::Instance<RPI::Material>& material,
|
||||
bool skinnedMeshWithMotion = false,
|
||||
bool rayTracingEnabled = true,
|
||||
RequiresCloneCallback requiresCloneCallback = {}) = 0;
|
||||
const MeshHandleDescriptor& descriptor,
|
||||
const Data::Instance<RPI::Material>& material) = 0;
|
||||
//! Releases the mesh handle
|
||||
virtual bool ReleaseMesh(MeshHandle& meshHandle) = 0;
|
||||
//! Creates a new instance and handle of a mesh using an existing MeshId. Currently, this will reset the new mesh to default materials.
|
||||
|
||||
@@ -37,8 +37,8 @@ namespace UnitTest
|
||||
MOCK_METHOD1(GetSortKey, AZ::RHI::DrawItemSortKey(const MeshHandle&));
|
||||
MOCK_METHOD2(SetLodOverride, void(const MeshHandle&, AZ::RPI::Cullable::LodOverride));
|
||||
MOCK_METHOD1(GetLodOverride, AZ::RPI::Cullable::LodOverride(const MeshHandle&));
|
||||
MOCK_METHOD5(AcquireMesh, MeshHandle (const AZ::Data::Asset<AZ::RPI::ModelAsset>&, const AZ::Render::MaterialAssignmentMap&, bool, bool, AZ::Render::MeshFeatureProcessorInterface::RequiresCloneCallback));
|
||||
MOCK_METHOD5(AcquireMesh, MeshHandle (const AZ::Data::Asset<AZ::RPI::ModelAsset>&, const AZ::Data::Instance<AZ::RPI::Material>&, bool, bool, AZ::Render::MeshFeatureProcessorInterface::RequiresCloneCallback));
|
||||
MOCK_METHOD2(AcquireMesh, MeshHandle (const AZ::Render::MeshHandleDescriptor&, const AZ::Render::MaterialAssignmentMap&));
|
||||
MOCK_METHOD2(AcquireMesh, MeshHandle (const AZ::Render::MeshHandleDescriptor&, const AZ::Data::Instance<AZ::RPI::Material>&));
|
||||
MOCK_METHOD2(SetRayTracingEnabled, void (const MeshHandle&, bool));
|
||||
MOCK_METHOD2(SetVisible, void (const MeshHandle&, bool));
|
||||
MOCK_METHOD2(SetUseForwardPassIblSpecular, void (const MeshHandle&, bool));
|
||||
|
||||
@@ -149,46 +149,38 @@ namespace AZ
|
||||
}
|
||||
|
||||
MeshFeatureProcessor::MeshHandle MeshFeatureProcessor::AcquireMesh(
|
||||
const Data::Asset<RPI::ModelAsset>& modelAsset,
|
||||
const MaterialAssignmentMap& materials,
|
||||
bool skinnedMeshWithMotion,
|
||||
bool rayTracingEnabled,
|
||||
RequiresCloneCallback requiresCloneCallback)
|
||||
const MeshHandleDescriptor& descriptor,
|
||||
const MaterialAssignmentMap& materials)
|
||||
{
|
||||
AZ_PROFILE_FUNCTION(Debug::ProfileCategory::AzRender);
|
||||
|
||||
// don't need to check the concurrency during emplace() because the StableDynamicArray won't move the other elements during insertion
|
||||
MeshHandle meshDataHandle = m_meshData.emplace();
|
||||
|
||||
// Mark skinned meshes to enable special processes to generate motion vector
|
||||
meshDataHandle->m_skinnedMeshWithMotion = skinnedMeshWithMotion;
|
||||
meshDataHandle->m_descriptor = descriptor;
|
||||
|
||||
// set ray tracing flag, but always disable on skinned meshes
|
||||
// Always disable ray tracing flag on skinned meshes
|
||||
// [GFX TODO][ATOM-13067] Enable raytracing on skinned meshes
|
||||
meshDataHandle->m_rayTracingEnabled = rayTracingEnabled && (skinnedMeshWithMotion == false);
|
||||
meshDataHandle->m_descriptor.m_isRayTracingEnabled &= !descriptor.m_isSkinnedMeshWithMotion;
|
||||
|
||||
meshDataHandle->m_scene = GetParentScene();
|
||||
meshDataHandle->m_materialAssignments = materials;
|
||||
meshDataHandle->m_objectId = m_transformService->ReserveObjectId();
|
||||
meshDataHandle->m_originalModelAsset = modelAsset;
|
||||
meshDataHandle->m_requiresCloningCallback = requiresCloneCallback;
|
||||
meshDataHandle->m_meshLoader = AZStd::make_unique<MeshDataInstance::MeshLoader>(modelAsset, &*meshDataHandle);
|
||||
meshDataHandle->m_originalModelAsset = descriptor.m_modelAsset;
|
||||
meshDataHandle->m_meshLoader = AZStd::make_unique<MeshDataInstance::MeshLoader>(descriptor.m_modelAsset, &*meshDataHandle);
|
||||
|
||||
return meshDataHandle;
|
||||
}
|
||||
|
||||
MeshFeatureProcessor::MeshHandle MeshFeatureProcessor::AcquireMesh(
|
||||
const Data::Asset<RPI::ModelAsset>& modelAsset,
|
||||
const Data::Instance<RPI::Material>& material,
|
||||
bool skinnedMeshWithMotion,
|
||||
bool rayTracingEnabled,
|
||||
RequiresCloneCallback requiresCloneCallback)
|
||||
const MeshHandleDescriptor& descriptor,
|
||||
const Data::Instance<RPI::Material>& material)
|
||||
{
|
||||
Render::MaterialAssignmentMap materials;
|
||||
Render::MaterialAssignment& defaultMaterial = materials[AZ::Render::DefaultMaterialAssignmentId];
|
||||
defaultMaterial.m_materialInstance = material;
|
||||
|
||||
return AcquireMesh(modelAsset, materials, skinnedMeshWithMotion, rayTracingEnabled, requiresCloneCallback);
|
||||
return AcquireMesh(descriptor, materials);
|
||||
}
|
||||
|
||||
bool MeshFeatureProcessor::ReleaseMesh(MeshHandle& meshHandle)
|
||||
@@ -210,7 +202,7 @@ namespace AZ
|
||||
{
|
||||
if (meshHandle.IsValid())
|
||||
{
|
||||
MeshHandle clone = AcquireMesh(meshHandle->m_originalModelAsset, meshHandle->m_materialAssignments);
|
||||
MeshHandle clone = AcquireMesh(meshHandle->m_descriptor, meshHandle->m_materialAssignments);
|
||||
return clone;
|
||||
}
|
||||
return MeshFeatureProcessor::MeshHandle();
|
||||
@@ -377,6 +369,14 @@ namespace AZ
|
||||
if (meshHandle.IsValid())
|
||||
{
|
||||
meshHandle->m_excludeFromReflectionCubeMaps = excludeFromReflectionCubeMaps;
|
||||
if (excludeFromReflectionCubeMaps)
|
||||
{
|
||||
meshHandle->m_cullable.m_cullData.m_hideFlags |= RPI::View::UsageReflectiveCubeMap;
|
||||
}
|
||||
else
|
||||
{
|
||||
meshHandle->m_cullable.m_cullData.m_hideFlags &= ~RPI::View::UsageReflectiveCubeMap;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -385,12 +385,12 @@ namespace AZ
|
||||
if (meshHandle.IsValid())
|
||||
{
|
||||
// update the ray tracing data based on the current state and the new state
|
||||
if (rayTracingEnabled && !meshHandle->m_rayTracingEnabled)
|
||||
if (rayTracingEnabled && !meshHandle->m_descriptor.m_isRayTracingEnabled)
|
||||
{
|
||||
// add to ray tracing
|
||||
meshHandle->SetRayTracingData();
|
||||
}
|
||||
else if (!rayTracingEnabled && meshHandle->m_rayTracingEnabled)
|
||||
else if (!rayTracingEnabled && meshHandle->m_descriptor.m_isRayTracingEnabled)
|
||||
{
|
||||
// remove from ray tracing
|
||||
if (m_rayTracingFeatureProcessor)
|
||||
@@ -400,7 +400,7 @@ namespace AZ
|
||||
}
|
||||
|
||||
// set new state
|
||||
meshHandle->m_rayTracingEnabled = rayTracingEnabled;
|
||||
meshHandle->m_descriptor.m_isRayTracingEnabled = rayTracingEnabled;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -416,7 +416,7 @@ namespace AZ
|
||||
{
|
||||
if (meshHandle.IsValid())
|
||||
{
|
||||
meshHandle->m_useForwardPassIblSpecular = useForwardPassIblSpecular;
|
||||
meshHandle->m_descriptor.m_useForwardPassIblSpecular = useForwardPassIblSpecular;
|
||||
meshHandle->m_objectSrgNeedsUpdate = true;
|
||||
|
||||
if (meshHandle->m_model)
|
||||
@@ -450,7 +450,7 @@ namespace AZ
|
||||
// we need to rebuild the Srg for any meshes that are using the forward pass IBL specular option
|
||||
for (auto& meshInstance : m_meshData)
|
||||
{
|
||||
if (meshInstance.m_useForwardPassIblSpecular)
|
||||
if (meshInstance.m_descriptor.m_useForwardPassIblSpecular)
|
||||
{
|
||||
meshInstance.m_objectSrgNeedsUpdate = true;
|
||||
}
|
||||
@@ -507,8 +507,8 @@ namespace AZ
|
||||
|
||||
Data::Instance<RPI::Model> model;
|
||||
// Check if a requires cloning callback got set and if so check if cloning the model asset is requested.
|
||||
if (m_parent->m_requiresCloningCallback &&
|
||||
m_parent->m_requiresCloningCallback(modelAsset))
|
||||
if (m_parent->m_descriptor.m_requiresCloneCallback &&
|
||||
m_parent->m_descriptor.m_requiresCloneCallback(modelAsset))
|
||||
{
|
||||
// Clone the model asset to force create another model instance.
|
||||
AZ::Data::AssetId newId(AZ::Uuid::CreateRandom(), /*subId=*/0);
|
||||
@@ -598,7 +598,7 @@ namespace AZ
|
||||
objectIdIndex.AssertValid();
|
||||
}
|
||||
|
||||
if (m_rayTracingEnabled)
|
||||
if (m_descriptor.m_isRayTracingEnabled)
|
||||
{
|
||||
SetRayTracingData();
|
||||
}
|
||||
@@ -671,7 +671,7 @@ namespace AZ
|
||||
RPI::MeshDrawPacket drawPacket(modelLod, meshIndex, material, m_shaderResourceGroup, materialAssignment.m_matModUvOverrides);
|
||||
|
||||
// set the shader option to select forward pass IBL specular if necessary
|
||||
if (!drawPacket.SetShaderOption(AZ::Name("o_meshUseForwardPassIBLSpecular"), AZ::RPI::ShaderOptionValue{ m_useForwardPassIblSpecular }))
|
||||
if (!drawPacket.SetShaderOption(AZ::Name("o_meshUseForwardPassIBLSpecular"), AZ::RPI::ShaderOptionValue{ m_descriptor.m_useForwardPassIblSpecular }))
|
||||
{
|
||||
AZ_Warning("MeshDrawPacket", false, "Failed to set o_meshUseForwardPassIBLSpecular on mesh draw packet");
|
||||
}
|
||||
@@ -682,7 +682,7 @@ namespace AZ
|
||||
m_hasForwardPassIblSpecularMaterial |= materialRequiresForwardPassIblSpecular;
|
||||
|
||||
// stencil bits
|
||||
uint8_t stencilRef = m_useForwardPassIblSpecular || materialRequiresForwardPassIblSpecular ? Render::StencilRefs::None : Render::StencilRefs::UseIBLSpecularPass;
|
||||
uint8_t stencilRef = m_descriptor.m_useForwardPassIblSpecular || materialRequiresForwardPassIblSpecular ? Render::StencilRefs::None : Render::StencilRefs::UseIBLSpecularPass;
|
||||
stencilRef |= Render::StencilRefs::UseDiffuseGIPass;
|
||||
|
||||
drawPacket.SetStencilRef(stencilRef);
|
||||
@@ -1102,12 +1102,12 @@ namespace AZ
|
||||
//[GFX TODO][ATOM-4726] Replace this with a "isSkinnedMesh" external material property and a functor that enables/disables the appropriate shader
|
||||
for (auto& shaderItem : material->GetShaderCollection())
|
||||
{
|
||||
if (shaderItem.GetShaderAsset()->GetName() == Name{ "StaticMeshMotionVector" } && m_skinnedMeshWithMotion)
|
||||
if (shaderItem.GetShaderAsset()->GetName() == Name{ "StaticMeshMotionVector" } && m_descriptor.m_isSkinnedMeshWithMotion)
|
||||
{
|
||||
shaderItem.SetEnabled(false);
|
||||
}
|
||||
|
||||
if (shaderItem.GetShaderAsset()->GetName() == Name{ "SkinnedMeshMotionVector" } && (!m_skinnedMeshWithMotion))
|
||||
if (shaderItem.GetShaderAsset()->GetName() == Name{ "SkinnedMeshMotionVector" } && (!m_descriptor.m_isSkinnedMeshWithMotion))
|
||||
{
|
||||
shaderItem.SetEnabled(false);
|
||||
}
|
||||
@@ -1123,7 +1123,7 @@ namespace AZ
|
||||
|
||||
ReflectionProbeFeatureProcessor* reflectionProbeFeatureProcessor = m_scene->GetFeatureProcessor<ReflectionProbeFeatureProcessor>();
|
||||
|
||||
if (reflectionProbeFeatureProcessor && (m_useForwardPassIblSpecular || m_hasForwardPassIblSpecularMaterial))
|
||||
if (reflectionProbeFeatureProcessor && (m_descriptor.m_useForwardPassIblSpecular || m_hasForwardPassIblSpecularMaterial))
|
||||
{
|
||||
// retrieve probe constant indices
|
||||
AZ::RHI::ShaderInputConstantIndex posConstantIndex = m_shaderResourceGroup->FindShaderInputConstantIndex(Name("m_reflectionProbeData.m_aabbPos"));
|
||||
|
||||
+1
-1
@@ -39,7 +39,7 @@ namespace AZ
|
||||
"Models/OcclusionCullingPlane.azmodel",
|
||||
AZ::RPI::AssetUtils::TraceLevel::Assert);
|
||||
|
||||
m_visualizationMeshHandle = m_meshFeatureProcessor->AcquireMesh(m_visualizationModelAsset);
|
||||
m_visualizationMeshHandle = m_meshFeatureProcessor->AcquireMesh(MeshHandleDescriptor{ m_visualizationModelAsset });
|
||||
m_meshFeatureProcessor->SetExcludeFromReflectionCubeMaps(m_visualizationMeshHandle, true);
|
||||
m_meshFeatureProcessor->SetRayTracingEnabled(m_visualizationMeshHandle, false);
|
||||
m_meshFeatureProcessor->SetTransform(m_visualizationMeshHandle, AZ::Transform::CreateIdentity());
|
||||
|
||||
@@ -67,7 +67,7 @@ namespace AZ
|
||||
"Models/ReflectionProbeSphere.azmodel",
|
||||
AZ::RPI::AssetUtils::TraceLevel::Assert);
|
||||
|
||||
m_visualizationMeshHandle = m_meshFeatureProcessor->AcquireMesh(m_visualizationModelAsset);
|
||||
m_visualizationMeshHandle = m_meshFeatureProcessor->AcquireMesh(MeshHandleDescriptor{ m_visualizationModelAsset });
|
||||
m_meshFeatureProcessor->SetExcludeFromReflectionCubeMaps(m_visualizationMeshHandle, true);
|
||||
m_meshFeatureProcessor->SetRayTracingEnabled(m_visualizationMeshHandle, false);
|
||||
m_meshFeatureProcessor->SetTransform(m_visualizationMeshHandle, AZ::Transform::CreateIdentity());
|
||||
|
||||
@@ -160,13 +160,19 @@ namespace AZ
|
||||
0,0,1,0,
|
||||
0,0,0,1 };
|
||||
yUpWorld.StoreToRowMajorFloat12(viewToWorldMatrixRaw);
|
||||
const AZ::Matrix4x4 prevViewToWorldMatrix = m_viewToWorldMatrix;
|
||||
m_viewToWorldMatrix = AZ::Matrix4x4::CreateFromRowMajorFloat16(viewToWorldMatrixRaw);
|
||||
|
||||
m_worldToViewMatrix = m_viewToWorldMatrix.GetInverseFast();
|
||||
|
||||
m_worldToClipMatrix = m_viewToClipMatrix * m_worldToViewMatrix;
|
||||
|
||||
m_onWorldToViewMatrixChange.Signal(m_worldToViewMatrix);
|
||||
// Only signal an update when there is a change, otherwise this might block
|
||||
// user input from changing the value.
|
||||
if (!prevViewToWorldMatrix.IsClose(m_viewToWorldMatrix))
|
||||
{
|
||||
m_onWorldToViewMatrixChange.Signal(m_worldToViewMatrix);
|
||||
}
|
||||
m_onWorldToClipMatrixChange.Signal(m_worldToClipMatrix);
|
||||
|
||||
InvalidateSrg();
|
||||
|
||||
@@ -317,8 +317,11 @@ namespace AZ
|
||||
MaterialComponentRequestBus::EventResult(materials, entityId, &MaterialComponentRequests::GetMaterialOverrides);
|
||||
|
||||
m_meshFeatureProcessor->ReleaseMesh(m_meshHandle);
|
||||
m_meshHandle = m_meshFeatureProcessor->AcquireMesh(m_configuration.m_modelAsset, materials,
|
||||
/*skinnedMeshWithMotion=*/false, /*rayTracingEnabled=*/true, RequiresCloning);
|
||||
MeshHandleDescriptor meshDescriptor;
|
||||
meshDescriptor.m_modelAsset = m_configuration.m_modelAsset;
|
||||
meshDescriptor.m_useForwardPassIblSpecular = m_configuration.m_useForwardPassIblSpecular;
|
||||
meshDescriptor.m_requiresCloneCallback = RequiresCloning;
|
||||
m_meshHandle = m_meshFeatureProcessor->AcquireMesh(meshDescriptor, materials);
|
||||
m_meshFeatureProcessor->ConnectModelChangeEventHandler(m_meshHandle, m_changeEventHandler);
|
||||
|
||||
const AZ::Transform& transform = m_transformInterface ? m_transformInterface->GetWorldTM() : AZ::Transform::CreateIdentity();
|
||||
@@ -327,7 +330,6 @@ namespace AZ
|
||||
m_meshFeatureProcessor->SetSortKey(m_meshHandle, m_configuration.m_sortKey);
|
||||
m_meshFeatureProcessor->SetLodOverride(m_meshHandle, m_configuration.m_lodOverride);
|
||||
m_meshFeatureProcessor->SetExcludeFromReflectionCubeMaps(m_meshHandle, m_configuration.m_excludeFromReflectionCubeMaps);
|
||||
m_meshFeatureProcessor->SetUseForwardPassIblSpecular(m_meshHandle, m_configuration.m_useForwardPassIblSpecular);
|
||||
|
||||
// [GFX TODO] This should happen automatically. m_changeEventHandler should be passed to AcquireMesh
|
||||
// If the model instance or asset already exists, announce a model change to let others know it's loaded.
|
||||
|
||||
@@ -626,9 +626,11 @@ namespace AZ
|
||||
AZ_Error("ActorComponentController", meshFeatureProcessor, "Unable to find a MeshFeatureProcessorInterface on the entityId.");
|
||||
if (meshFeatureProcessor)
|
||||
{
|
||||
// Last boolean parameter indicates if motion vector is enabled
|
||||
MeshHandleDescriptor meshDescriptor;
|
||||
meshDescriptor.m_modelAsset = m_skinnedMeshInstance->m_model->GetModelAsset();
|
||||
meshDescriptor.m_isSkinnedMeshWithMotion = true;
|
||||
m_meshHandle = AZStd::make_shared<MeshFeatureProcessorInterface::MeshHandle>(
|
||||
m_meshFeatureProcessor->AcquireMesh(m_skinnedMeshInstance->m_model->GetModelAsset(), materials, /*skinnedMeshWithMotion=*/true));
|
||||
m_meshFeatureProcessor->AcquireMesh(meshDescriptor, materials));
|
||||
}
|
||||
|
||||
// If render proxies already exist, they will be auto-freed
|
||||
|
||||
@@ -187,7 +187,7 @@ namespace Blast
|
||||
materials, GetEntityId(), &AZ::Render::MaterialComponentRequests::GetMaterialOverrides);
|
||||
|
||||
m_meshFeatureProcessor->ReleaseMesh(m_meshHandle);
|
||||
m_meshHandle = m_meshFeatureProcessor->AcquireMesh(m_meshAssets[0], materials);
|
||||
m_meshHandle = m_meshFeatureProcessor->AcquireMesh(AZ::Render::MeshHandleDescriptor{ m_meshAssets[0] }, materials);
|
||||
m_meshFeatureProcessor->ConnectModelChangeEventHandler(m_meshHandle, m_changeEventHandler);
|
||||
|
||||
HandleModelChange(m_meshFeatureProcessor->GetModel(m_meshHandle));
|
||||
|
||||
@@ -47,7 +47,7 @@ namespace Blast
|
||||
{
|
||||
m_chunkActors[chunkId] = &actor;
|
||||
m_chunkMeshHandles[chunkId] =
|
||||
m_meshFeatureProcessor->AcquireMesh(m_meshData->GetMeshAsset(chunkId), m_materialMap);
|
||||
m_meshFeatureProcessor->AcquireMesh(AZ::Render::MeshHandleDescriptor{ m_meshData->GetMeshAsset(chunkId) }, m_materialMap);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -98,7 +98,7 @@ namespace Blast
|
||||
// ActorRenderManager::OnActorCreated
|
||||
{
|
||||
EXPECT_CALL(
|
||||
*m_mockMeshFeatureProcessor, AcquireMesh(_, testing::A<const AZ::Render::MaterialAssignmentMap&>(), _, _, _))
|
||||
*m_mockMeshFeatureProcessor, AcquireMesh(_, testing::A<const AZ::Render::MaterialAssignmentMap&>()))
|
||||
.Times(aznumeric_cast<int>(m_actorFactory->m_mockActors[0]->GetChunkIndices().size()))
|
||||
.WillOnce(Return(testing::ByMove(AZ::Render::MeshFeatureProcessorInterface::MeshHandle())))
|
||||
.WillOnce(Return(testing::ByMove(AZ::Render::MeshFeatureProcessorInterface::MeshHandle())));
|
||||
|
||||
@@ -300,7 +300,7 @@ namespace GraphModel
|
||||
// Slot
|
||||
|
||||
AZ::JsonSerializationResult::Result JsonSlotSerializer::Load(
|
||||
void* outputValue, const AZ::Uuid& outputValueTypeId, const rapidjson::Value& inputValue,
|
||||
void* outputValue, [[maybe_unused]] const AZ::Uuid& outputValueTypeId, const rapidjson::Value& inputValue,
|
||||
AZ::JsonDeserializerContext& context)
|
||||
{
|
||||
namespace JSR = AZ::JsonSerializationResult;
|
||||
@@ -343,12 +343,12 @@ namespace GraphModel
|
||||
|
||||
return context.Report(
|
||||
result,
|
||||
result.GetProcessing() != JSR::Processing::Halted ? "Succesfully loaded Slot information."
|
||||
result.GetProcessing() != JSR::Processing::Halted ? "Successfully loaded Slot information."
|
||||
: "Failed to load Slot information.");
|
||||
}
|
||||
|
||||
AZ::JsonSerializationResult::Result JsonSlotSerializer::Store(
|
||||
rapidjson::Value& outputValue, const void* inputValue, [[maybe_unused]] const void* defaultValue, const AZ::Uuid& valueTypeId,
|
||||
rapidjson::Value& outputValue, const void* inputValue, [[maybe_unused]] const void* defaultValue, [[maybe_unused]] const AZ::Uuid& valueTypeId,
|
||||
AZ::JsonSerializerContext& context)
|
||||
{
|
||||
namespace JSR = AZ::JsonSerializationResult;
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
#include <GradientSignal/Editor/EditorGradientComponentBase.h>
|
||||
#include <Vegetation/Editor/EditorVegetationComponentTypeIds.h>
|
||||
#include <LmbrCentral/Component/EditorWrappedComponentBase.h>
|
||||
#include <CrySystemBus.h>
|
||||
|
||||
namespace Vegetation
|
||||
{
|
||||
@@ -28,7 +27,6 @@ namespace Vegetation
|
||||
template<typename TComponent, typename TConfiguration>
|
||||
class EditorVegetationComponentBase
|
||||
: public LmbrCentral::EditorWrappedComponentBase<TComponent, TConfiguration>
|
||||
, private CrySystemEventBus::Handler
|
||||
{
|
||||
public:
|
||||
using BaseClassType = LmbrCentral::EditorWrappedComponentBase<TComponent, TConfiguration>;
|
||||
@@ -48,11 +46,6 @@ namespace Vegetation
|
||||
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// CrySystemEvents
|
||||
void OnCryEditorBeginLevelExport() override;
|
||||
void OnCryEditorEndLevelExport(bool /*success*/) override;
|
||||
|
||||
protected:
|
||||
using BaseClassType::m_configuration;
|
||||
using BaseClassType::m_component;
|
||||
|
||||
@@ -12,24 +12,6 @@
|
||||
|
||||
namespace Vegetation
|
||||
{
|
||||
template<typename TComponent, typename TConfiguration>
|
||||
void EditorVegetationComponentBase<TComponent, TConfiguration>::OnCryEditorEndLevelExport(bool /*success*/)
|
||||
{
|
||||
// Restore the activation state of our components after the export is complete.
|
||||
if (m_visible)
|
||||
{
|
||||
m_component.Activate();
|
||||
}
|
||||
}
|
||||
|
||||
template<typename TComponent, typename TConfiguration>
|
||||
void EditorVegetationComponentBase<TComponent, TConfiguration>::OnCryEditorBeginLevelExport()
|
||||
{
|
||||
// We need to deactivate our game components at the start of level exports because any vegetation meshes that are loaded
|
||||
// or instances that are spawned can end up in our static vegetation level data.
|
||||
m_component.Deactivate();
|
||||
}
|
||||
|
||||
template<typename TComponent, typename TConfiguration>
|
||||
AZ::u32 EditorVegetationComponentBase<TComponent, TConfiguration>::ConfigurationChanged()
|
||||
{
|
||||
@@ -69,13 +51,11 @@ namespace Vegetation
|
||||
{
|
||||
GradientSignal::SetSamplerOwnerEntity(m_configuration, GetEntityId());
|
||||
BaseClassType::Activate();
|
||||
CrySystemEventBus::Handler::BusConnect();
|
||||
}
|
||||
|
||||
template<typename TComponent, typename TConfiguration>
|
||||
void EditorVegetationComponentBase<TComponent, TConfiguration>::Deactivate()
|
||||
{
|
||||
CrySystemEventBus::Handler::BusDisconnect();
|
||||
BaseClassType::Deactivate();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:f2a70cf9523c07263261bb2a912f656609419318e680611ccc8e2652c2f5ec0a
|
||||
size 410840
|
||||
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:69c699ebfb1f4ffe241b047499d0f52292112b38783d08eb50ccfeb97f76c91a
|
||||
size 3145784
|
||||
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:e2519313a259f6df040e17ce27cffc3c96a2c8616aeeffd3899481ab52efd41f
|
||||
size 3145784
|
||||
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:9d76c75c2b18850a091f9787ee4ac684a648d8dea0bcc8141f4e895942428fd4
|
||||
size 3145784
|
||||
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:3c22f26d5921218882dbe7d55deb9f4e33744a34eb02804efb44998f7299afb6
|
||||
size 3145784
|
||||
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:3841e927bb9a411af5287e1f69c68ad6fbcfefc4ed4696ee58ab80f6554e4b3e
|
||||
size 12602708
|
||||
-1
@@ -1 +0,0 @@
|
||||
/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=Albedo /reduce=0
|
||||
-16
@@ -1,16 +0,0 @@
|
||||
<Material MtlFlags="524544" vertModifType="0">
|
||||
<SubMaterials>
|
||||
<Material Name="AM_Barrel_01_M" MtlFlags="524416" Shader="Illum" GenMask="4001010000001" StringGenMask="%ALLOW_SILHOUETTE_POM%NORMAL_MAP%SPECULAR_MAP%SUBSURFACE_SCATTERING" SurfaceType="mat_metal" Diffuse="1,1,1,1" Specular="1,1,1,1" Opacity="1" Shininess="255" vertModifType="0" LayerAct="1">
|
||||
<Textures>
|
||||
<Texture Map="Diffuse" File="Objects/ManMade/Props/Barrel/AM_Barrel_01_Diff.tif"/>
|
||||
<Texture Map="Bumpmap" File="objects/manmade/props/barrel/am_barrel_01_ddna.dds"/>
|
||||
<Texture Map="Specular" File="objects/manmade/props/barrel/am_barrel_01_spec.dds"/>
|
||||
</Textures>
|
||||
<PublicParams EmittanceMapGamma="1" SSSIndex="0" IndirectColor="0.25,0.25,0.25"/>
|
||||
</Material>
|
||||
<Material Name="Proxy_COL" MtlFlags="525440" Shader="Nodraw" GenMask="0" StringGenMask="" SurfaceType="mat_metal" Diffuse="0.5,0.5,0.5,1" Specular="0,0,0,1" Opacity="1" Shininess="10" vertModifType="0" LayerAct="1">
|
||||
<Textures />
|
||||
</Material>
|
||||
</SubMaterials>
|
||||
<PublicParams EmittanceMapGamma="1" SSSIndex="0" IndirectColor="0.25,0.25,0.25"/>
|
||||
</Material>
|
||||
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:c318de8b5e831429c0852043df2b496ea360f7e7a16a09728057e936b5f9d82f
|
||||
size 16797014
|
||||
-1
@@ -1 +0,0 @@
|
||||
/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=NormalsWithSmoothness /reduce=0
|
||||
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:7a64b6827e7f837f35d802433419ad88b196ea99ed97215cdee4d77009584152
|
||||
size 3157332
|
||||
-1
@@ -1 +0,0 @@
|
||||
/autooptimizefile=0 /preset=Reflectance /reduce=0
|
||||
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:45ab25afac85d92c63c939cea3086545975412a81d2c1d03210a9c4c0a57b8ab
|
||||
size 12602708
|
||||
-1
@@ -1 +0,0 @@
|
||||
/autooptimizefile=0 /preset=Albedo /reduce=0
|
||||
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:f582c61b53f2bde096345e6a1dbbfb70fabbe05aaa96f5f560885acbc2ecb76c
|
||||
size 111276
|
||||
-16
@@ -1,16 +0,0 @@
|
||||
<Material MtlFlags="524544" vertModifType="0">
|
||||
<SubMaterials>
|
||||
<Material Name="AM_Barrel_01_M" MtlFlags="524416" Shader="Illum" GenMask="4001010000001" StringGenMask="%ALLOW_SILHOUETTE_POM%NORMAL_MAP%SPECULAR_MAP%SUBSURFACE_SCATTERING" SurfaceType="mat_metal" Diffuse="1,1,1,1" Specular="1,1,1,1" Opacity="1" Shininess="255" vertModifType="0" LayerAct="1">
|
||||
<Textures>
|
||||
<Texture Map="Diffuse" File="objects/manmade/props/barrel/am_barrel_02_diff.dds"/>
|
||||
<Texture Map="Bumpmap" File="objects/manmade/props/barrel/am_barrel_01_ddna.dds"/>
|
||||
<Texture Map="Specular" File="objects/manmade/props/barrel/am_barrel_01_spec.dds"/>
|
||||
</Textures>
|
||||
<PublicParams EmittanceMapGamma="1" SSSIndex="0" IndirectColor="0.25,0.25,0.25"/>
|
||||
</Material>
|
||||
<Material Name="Proxy_COL" MtlFlags="525440" Shader="Nodraw" GenMask="0" StringGenMask="" SurfaceType="mat_metal" Diffuse="0.5,0.5,0.5,1" Specular="0,0,0,1" Opacity="1" Shininess="10" vertModifType="0" LayerAct="1">
|
||||
<Textures />
|
||||
</Material>
|
||||
</SubMaterials>
|
||||
<PublicParams EmittanceMapGamma="1" SSSIndex="0" IndirectColor="0.25,0.25,0.25"/>
|
||||
</Material>
|
||||
-18
@@ -1,18 +0,0 @@
|
||||
<Material MtlFlags="524544" vertModifType="0">
|
||||
<SubMaterials>
|
||||
<Material Name="AM_Rock_Boulder_01_Mat" MtlFlags="524416" Shader="Illum" GenMask="4000010000041" StringGenMask="%ALLOW_SILHOUETTE_POM%DETAIL_MAPPING%NORMAL_MAP%SUBSURFACE_SCATTERING" SurfaceType="mat_rock" Diffuse="1,1,1,1" Specular="0.03954624,0.03954624,0.03954624,1" Opacity="1" Shininess="255" vertModifType="0" LayerAct="1">
|
||||
<Textures>
|
||||
<Texture Map="Diffuse" File="Objects/Natural/Rocks/AM_Rock_Boulder_01_diff.tif"/>
|
||||
<Texture Map="Bumpmap" File="objects/natural/rocks/am_rock_boulder_01_ddna.dds"/>
|
||||
<Texture Map="Detail" File="objects/natural/rocks/rock03_detail.dds">
|
||||
<TexMod TexMod_RotateType="0" TexMod_TexGenType="0" TexMod_bTexGenProjected="0" TileU="4" TileV="4"/>
|
||||
</Texture>
|
||||
</Textures>
|
||||
<PublicParams EmittanceMapGamma="1" DetailDiffuseScale="0.5" SSSIndex="0" DetailBumpScale="0" DetailGlossScale="0.5" IndirectColor="0.25,0.25,0.25"/>
|
||||
</Material>
|
||||
<Material Name="AM_Rock_Boulder_01_Proxy_Mat" MtlFlags="525440" Shader="Nodraw" GenMask="0" StringGenMask="" SurfaceType="mat_rock" Diffuse="0.5,0.5,0.5,1" Specular="0,0,0,1" Opacity="1" Shininess="10" vertModifType="0" LayerAct="1">
|
||||
<Textures />
|
||||
</Material>
|
||||
</SubMaterials>
|
||||
<PublicParams EmittanceMapGamma="1" SSSIndex="0" IndirectColor="0.25,0.25,0.25"/>
|
||||
</Material>
|
||||
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:70148ec39ccbbb05bc3c5df8857fbbdc1ee455574b4a141e4d6ceb78aacd6c76
|
||||
size 16797012
|
||||
-1
@@ -1 +0,0 @@
|
||||
/autooptimizefile=0 /preset=NormalsWithSmoothness /reduce=0
|
||||
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:7da1eab71d64b032264f1cb3b1b8b768496c56c90d057e42183b6dcfe9d1ada9
|
||||
size 12602706
|
||||
-1
@@ -1 +0,0 @@
|
||||
/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=AlbedoWithGenericAlpha /reduce=0
|
||||
-3
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:26c78881443d317e708efaa2266fe6c0e2a52d04109887c408cf539e31a3aed2
|
||||
size 16797018
|
||||
-1
@@ -1 +0,0 @@
|
||||
/autooptimizefile=0 /preset=NormalsWithSmoothness /reduce=0
|
||||
-18
@@ -1,18 +0,0 @@
|
||||
<Material MtlFlags="524544" vertModifType="0">
|
||||
<SubMaterials>
|
||||
<Material Name="AM_Rock_Cliff_01_mat" MtlFlags="524416" Shader="Illum" GenMask="4000010000045" StringGenMask="%ALLOW_SILHOUETTE_POM%ALPHAMASK_DETAILMAP%DETAIL_MAPPING%NORMAL_MAP%SUBSURFACE_SCATTERING" SurfaceType="mat_rock" Diffuse="0.83879912,0.79910284,0.76052463,1" Specular="0.03954624,0.03954624,0.03954624,1" Opacity="1" Shininess="255" vertModifType="0" LayerAct="1">
|
||||
<Textures>
|
||||
<Texture Map="Diffuse" File="Objects/Natural/Rocks/Rock_Cliff_01_diff.tif"/>
|
||||
<Texture Map="Bumpmap" File="objects/natural/rocks/rock_cliff_01_ddna.dds"/>
|
||||
<Texture Map="Detail" File="objects/natural/rocks/rock03_detail.dds">
|
||||
<TexMod TexMod_RotateType="0" TexMod_TexGenType="0" TexMod_bTexGenProjected="0" TileU="16" TileV="16"/>
|
||||
</Texture>
|
||||
</Textures>
|
||||
<PublicParams EmittanceMapGamma="1" DetailDiffuseScale="0.5" SSSIndex="0" DetailBumpScale="0" DetailGlossScale="0" IndirectColor="0.25,0.25,0.25"/>
|
||||
</Material>
|
||||
<Material Name="AM_Rock_Cliff_01_Proxy_mat" MtlFlags="525440" Shader="Nodraw" GenMask="0" StringGenMask="" SurfaceType="mat_rock" Diffuse="0.5,0.5,0.5,1" Specular="0,0,0,1" Opacity="1" Shininess="10" vertModifType="0" LayerAct="1">
|
||||
<Textures />
|
||||
</Material>
|
||||
</SubMaterials>
|
||||
<PublicParams EmittanceMapGamma="1" SSSIndex="0" IndirectColor="0.25,0.25,0.25"/>
|
||||
</Material>
|
||||
-18
@@ -1,18 +0,0 @@
|
||||
<Material MtlFlags="524544" vertModifType="0">
|
||||
<SubMaterials>
|
||||
<Material Name="AM_Rock_Cliff_02_Mat" MtlFlags="524416" Shader="Illum" GenMask="4000010000045" StringGenMask="%ALLOW_SILHOUETTE_POM%ALPHAMASK_DETAILMAP%DETAIL_MAPPING%NORMAL_MAP%SUBSURFACE_SCATTERING" SurfaceType="mat_rock" Diffuse="0.83879912,0.79910284,0.76052463,1" Specular="0.03954624,0.03954624,0.03954624,1" Opacity="1" Shininess="255" vertModifType="0" LayerAct="1">
|
||||
<Textures>
|
||||
<Texture Map="Diffuse" File="objects/natural/rocks/am_rock_cliff_02_diff.dds"/>
|
||||
<Texture Map="Bumpmap" File="objects/natural/rocks/am_rock_cliff_02_ddna.dds"/>
|
||||
<Texture Map="Detail" File="objects/natural/rocks/rock03_detail.dds">
|
||||
<TexMod TexMod_RotateType="0" TexMod_TexGenType="0" TexMod_bTexGenProjected="0" TileU="16" TileV="16"/>
|
||||
</Texture>
|
||||
</Textures>
|
||||
<PublicParams EmittanceMapGamma="1" DetailDiffuseScale="0.5" SSSIndex="0" DetailBumpScale="0" DetailGlossScale="0" IndirectColor="0.25,0.25,0.25"/>
|
||||
</Material>
|
||||
<Material Name="AM_Rock_Cliff_02_proxy_Mat" MtlFlags="525440" Shader="Nodraw" GenMask="0" StringGenMask="" SurfaceType="mat_rock" Diffuse="0.5,0.5,0.5,1" Specular="0.5,0.5,0.5,1" Opacity="1" Shininess="10" vertModifType="0" LayerAct="1">
|
||||
<Textures />
|
||||
</Material>
|
||||
</SubMaterials>
|
||||
<PublicParams EmittanceMapGamma="1" SSSIndex="0" IndirectColor="0.25,0.25,0.25"/>
|
||||
</Material>
|
||||
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:960fcf7aa076eae6578e40bd566b0bc978f77899f87de2b3a4306568e9eb5f10
|
||||
size 67145042
|
||||
-1
@@ -1 +0,0 @@
|
||||
/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=NormalsWithSmoothness /reduce=0
|
||||
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:bb9f5e3093ee1e19dc4bae286d4e34ae2095a3e70dbd02b64343fdb7e75ff897
|
||||
size 67145042
|
||||
-1
@@ -1 +0,0 @@
|
||||
/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=AlbedoWithGenericAlpha /reduce=0
|
||||
-3
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:c484e208ee7bdda60ef6ffeba1e6c523596ad9fd36cf24ac424baaf06c57cca9
|
||||
size 67145048
|
||||
-1
@@ -1 +0,0 @@
|
||||
/autooptimizefile=0 /preset=NormalsWithSmoothness /reduce=0
|
||||
-3
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:046b2105e45016bad314e8ad4ed3800018f60ea218bf33b2637554c0efd1c0b5
|
||||
size 16797016
|
||||
-1
@@ -1 +0,0 @@
|
||||
/autooptimizefile=0 /preset=NormalsWithSmoothness /reduce=0
|
||||
-3
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:a4285c8231bde77d1dbc9cbce60ee4a35a566f75cb96cb4279f1c1098a6fd5c3
|
||||
size 67145054
|
||||
-1
@@ -1 +0,0 @@
|
||||
/autooptimizefile=0 /preset=NormalsWithSmoothness /reduce=0
|
||||
-3
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:fd21e1c93650c69e841a5a87812a6937f77d9ae44c7f28bf37567a314e27d7d6
|
||||
size 67145058
|
||||
-1
@@ -1 +0,0 @@
|
||||
/autooptimizefile=0 /preset=NormalsWithSmoothness /reduce=0
|
||||
-3
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:45630fa430865bea236013ea2c6c91966ced24d51bdf791d04a5ba71d76dae69
|
||||
size 67145058
|
||||
-1
@@ -1 +0,0 @@
|
||||
/autooptimizefile=0 /preset=AlbedoWithGenericAlpha /reduce=0
|
||||
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:cecb571c673a412031a64e704122ac6eef77bd66005e26b767edd8c28037e11e
|
||||
size 67145048
|
||||
-1
@@ -1 +0,0 @@
|
||||
/autooptimizefile=0 /M=50,50,0,50,0,50 /preset=NormalsWithSmoothness /reduce=0
|
||||
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:0e0da4f69d5496bb3329b4bd4e5e32bceacf98d6e2eb6af1771812a225b241a7
|
||||
size 67145048
|
||||
-1
@@ -1 +0,0 @@
|
||||
/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=AlbedoWithGenericAlpha /reduce=0
|
||||
-18
@@ -1,18 +0,0 @@
|
||||
<Material MtlFlags="524544" vertModifType="0">
|
||||
<SubMaterials>
|
||||
<Material Name="AM_Rock_Flat_Multi_01_mat" MtlFlags="524416" Shader="Illum" GenMask="4000010000045" StringGenMask="%ALLOW_SILHOUETTE_POM%ALPHAMASK_DETAILMAP%DETAIL_MAPPING%NORMAL_MAP%SUBSURFACE_SCATTERING" SurfaceType="mat_rock" Diffuse="0.83879912,0.79910284,0.76052463,1" Specular="0.03954624,0.03954624,0.03954624,1" Opacity="1" Shininess="255" vertModifType="0" LayerAct="1">
|
||||
<Textures>
|
||||
<Texture Map="Diffuse" File="objects/natural/rocks/am_rock_flat_multi_01_diff.dds"/>
|
||||
<Texture Map="Bumpmap" File="objects/natural/rocks/am_rock_flat_multi_01_ddna.dds"/>
|
||||
<Texture Map="Detail" File="objects/natural/rocks/rock03_detail.dds">
|
||||
<TexMod TexMod_RotateType="0" TexMod_TexGenType="0" TexMod_bTexGenProjected="0" TileU="12" TileV="12"/>
|
||||
</Texture>
|
||||
</Textures>
|
||||
<PublicParams EmittanceMapGamma="1" DetailDiffuseScale="0.5" SSSIndex="0" DetailBumpScale="0" DetailGlossScale="0" IndirectColor="0.24620135,0.24620135,0.24620135"/>
|
||||
</Material>
|
||||
<Material Name="AM_Rock_Flat_01_proxy_mat" MtlFlags="525440" Shader="Nodraw" GenMask="0" StringGenMask="" SurfaceType="mat_rock" Diffuse="0.5,0.5,0.5,1" Specular="0.5,0.5,0.5,1" Opacity="1" Shininess="10" vertModifType="0" LayerAct="1">
|
||||
<Textures />
|
||||
</Material>
|
||||
</SubMaterials>
|
||||
<PublicParams EmittanceMapGamma="1" SSSIndex="0" IndirectColor="0.25,0.25,0.25"/>
|
||||
</Material>
|
||||
-18
@@ -1,18 +0,0 @@
|
||||
<Material MtlFlags="524544" vertModifType="0">
|
||||
<SubMaterials>
|
||||
<Material Name="AM_Rock_Flat_Multi_02_M" MtlFlags="524416" Shader="Illum" GenMask="4000010000041" StringGenMask="%ALLOW_SILHOUETTE_POM%DETAIL_MAPPING%NORMAL_MAP%SUBSURFACE_SCATTERING" SurfaceType="mat_rock" Diffuse="0.85499275,0.81484669,0.78353792,1" Specular="0.03954624,0.03954624,0.03954624,1" Opacity="1" Shininess="255" vertModifType="0" LayerAct="1">
|
||||
<Textures>
|
||||
<Texture Map="Diffuse" File="objects/natural/rocks/am_rock_flat_multi_02_diff.dds"/>
|
||||
<Texture Map="Bumpmap" File="objects/natural/rocks/am_rock_flat_multi_02_ddna.dds"/>
|
||||
<Texture Map="Detail" File="objects/natural/rocks/rock03_detail.dds">
|
||||
<TexMod TexMod_RotateType="0" TexMod_TexGenType="0" TexMod_bTexGenProjected="0" TileU="4" TileV="4"/>
|
||||
</Texture>
|
||||
</Textures>
|
||||
<PublicParams EmittanceMapGamma="1" DetailDiffuseScale="0.72500002" SSSIndex="0" DetailBumpScale="0" DetailGlossScale="0.5" IndirectColor="0.25,0.25,0.25"/>
|
||||
</Material>
|
||||
<Material Name="COL_Proxy" MtlFlags="525440" Shader="Nodraw" GenMask="0" StringGenMask="" SurfaceType="mat_rock" Diffuse="0.5,0.5,0.5,1" Specular="0.5,0.5,0.5,1" Opacity="1" Shininess="10" vertModifType="0" LayerAct="1">
|
||||
<Textures />
|
||||
</Material>
|
||||
</SubMaterials>
|
||||
<PublicParams EmittanceMapGamma="1" SSSIndex="0" IndirectColor="0.25,0.25,0.25"/>
|
||||
</Material>
|
||||
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:dfce23f8a59c8ef97dc9d8bdeb81072fc5300bff3c11735f65b7f78652f93cd4
|
||||
size 16797016
|
||||
-1
@@ -1 +0,0 @@
|
||||
/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=NormalsWithSmoothness /reduce=0
|
||||
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:b157eab497ef89c8f575f039b6da5b3c43a9fea06b2e6c2335ee1347357b49e3
|
||||
size 12602710
|
||||
-1
@@ -1 +0,0 @@
|
||||
/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=Albedo /reduce=0
|
||||
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:0f9378510d3f75fa80a5ca5884f1ad9e20852c5eb88d6e10d74238c89dbda208
|
||||
size 16797012
|
||||
-1
@@ -1 +0,0 @@
|
||||
/autooptimizefile=0 /M=50,0,50,0,0,50 /preset=NormalsWithSmoothness /reduce=0
|
||||
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:117d37d86b808768d74f70a522e66a76a6ffc71ceb5858e901a3f5191994d92b
|
||||
size 12602706
|
||||
-1
@@ -1 +0,0 @@
|
||||
/autooptimizefile=0 /M=50,0,0,50,50,50 /preset=AlbedoWithGenericAlpha /reduce=0
|
||||
-18
@@ -1,18 +0,0 @@
|
||||
<Material MtlFlags="524544" vertModifType="0">
|
||||
<SubMaterials>
|
||||
<Material Name="AM_Rock_Square_01_mat" MtlFlags="524416" Shader="Illum" GenMask="4000010000041" StringGenMask="%ALLOW_SILHOUETTE_POM%DETAIL_MAPPING%NORMAL_MAP%SUBSURFACE_SCATTERING" SurfaceType="mat_rock" Diffuse="1,1,1,1" Specular="0.03954624,0.03954624,0.03954624,1" Opacity="1" Shininess="180" vertModifType="0" LayerAct="1">
|
||||
<Textures>
|
||||
<Texture Map="Diffuse" File="objects/natural/rocks/am_rock_square_01_diff.dds"/>
|
||||
<Texture Map="Bumpmap" File="objects/natural/rocks/am_rock_square_01_ddna.dds"/>
|
||||
<Texture Map="Detail" File="objects/natural/rocks/rock03_detail.dds">
|
||||
<TexMod TexMod_RotateType="0" TexMod_TexGenType="0" TexMod_bTexGenProjected="0" TileU="8" TileV="8"/>
|
||||
</Texture>
|
||||
</Textures>
|
||||
<PublicParams EmittanceMapGamma="1" DetailDiffuseScale="0.5" SSSIndex="0" DetailBumpScale="0" DetailGlossScale="0.5" IndirectColor="0.25,0.25,0.25"/>
|
||||
</Material>
|
||||
<Material Name="AM_Rock_Square_01_proxy_mat" MtlFlags="525440" Shader="Nodraw" GenMask="0" StringGenMask="" SurfaceType="mat_rock" Diffuse="0.5,0.5,0.5,1" Specular="0.5,0.5,0.5,1" Opacity="1" Shininess="10" vertModifType="0" LayerAct="1">
|
||||
<Textures />
|
||||
</Material>
|
||||
</SubMaterials>
|
||||
<PublicParams EmittanceMapGamma="1" SSSIndex="0" IndirectColor="0.25,0.25,0.25"/>
|
||||
</Material>
|
||||
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:10b24991a5042c283f7af1a75360d0d9ad78384c6c4eadf99340506e253c8762
|
||||
size 16797012
|
||||
-1
@@ -1 +0,0 @@
|
||||
/autooptimizefile=0 /M=50,0,0,0,0,50 /preset=NormalsWithSmoothness /reduce=0
|
||||
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:6909db9fd61da354c863b1f8d6abb6f504f47b79515410b4c1337d5d5c06a69b
|
||||
size 12602706
|
||||
-1
@@ -1 +0,0 @@
|
||||
/autooptimizefile=0 /M=50,0,0,50,50,50 /preset=Albedo /reduce=0
|
||||
-18
@@ -1,18 +0,0 @@
|
||||
<Material MtlFlags="524544" vertModifType="0">
|
||||
<SubMaterials>
|
||||
<Material Name="AM_Rock_Square_02_mat" MtlFlags="524416" Shader="Illum" GenMask="4000010000041" StringGenMask="%ALLOW_SILHOUETTE_POM%DETAIL_MAPPING%NORMAL_MAP%SUBSURFACE_SCATTERING" SurfaceType="mat_rock" Diffuse="0.86315733,0.82278591,0.80695242,1" Specular="0.03954624,0.03954624,0.03954624,1" Opacity="1" Shininess="120" vertModifType="0" LayerAct="1">
|
||||
<Textures>
|
||||
<Texture Map="Diffuse" File="objects/natural/rocks/am_rock_square_02_diff.dds"/>
|
||||
<Texture Map="Bumpmap" File="objects/natural/rocks/am_rock_square_02_ddna.dds"/>
|
||||
<Texture Map="Detail" File="objects/natural/rocks/rock03_detail.dds">
|
||||
<TexMod TexMod_RotateType="0" TexMod_TexGenType="0" TexMod_bTexGenProjected="0" TileU="6" TileV="6"/>
|
||||
</Texture>
|
||||
</Textures>
|
||||
<PublicParams EmittanceMapGamma="1" DetailDiffuseScale="0.5" SSSIndex="0" DetailBumpScale="0" DetailGlossScale="0.5" IndirectColor="0.25,0.25,0.25"/>
|
||||
</Material>
|
||||
<Material Name="AM_Rock_Square_02_proxy_mat" MtlFlags="525440" Shader="Nodraw" GenMask="0" StringGenMask="" SurfaceType="mat_rock" Diffuse="0.5,0.5,0.5,1" Specular="0.5,0.5,0.5,1" Opacity="1" Shininess="10" vertModifType="0" LayerAct="1">
|
||||
<Textures />
|
||||
</Material>
|
||||
</SubMaterials>
|
||||
<PublicParams EmittanceMapGamma="1" SSSIndex="0" IndirectColor="0.25,0.25,0.25"/>
|
||||
</Material>
|
||||
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:94e30359c97338d4edeaeab700596993f20fa434606af4fcaa29d8ae1be7c781
|
||||
size 852132
|
||||
@@ -1,24 +0,0 @@
|
||||
<Material MtlFlags="524544" >
|
||||
<SubMaterials>
|
||||
<Material Name="AM_Rock_Square_01_mat" MtlFlags="524416" Shader="Illum" GenMask="4000010000041" StringGenMask="%ALLOW_SILHOUETTE_POM%DETAIL_MAPPING%NORMAL_MAP%SUBSURFACE_SCATTERING" SurfaceType="mat_rock" Diffuse="1,1,1,1" Specular="0.03954624,0.03954624,0.03954624,1" Opacity="1" Shininess="180" vertModifType="0" LayerAct="1">
|
||||
<Textures>
|
||||
<Texture Map="Diffuse" File="objects/natural/rocks/am_rock_square_01_diff.dds"/>
|
||||
<Texture Map="Bumpmap" File="objects/natural/rocks/am_rock_square_01_ddna.dds"/>
|
||||
<Texture Map="Detail" File="objects/natural/rocks/rock03_detail.dds">
|
||||
<TexMod TexMod_RotateType="0" TexMod_TexGenType="0" TexMod_bTexGenProjected="0" TileU="8" TileV="8"/>
|
||||
</Texture>
|
||||
</Textures>
|
||||
<PublicParams EmittanceMapGamma="1" DetailDiffuseScale="0.5" SSSIndex="0" DetailBumpScale="0" DetailGlossScale="0.5" IndirectColor="0.25,0.25,0.25"/>
|
||||
</Material>
|
||||
<Material Name="AM_Rock_Square_02_mat" MtlFlags="524416" Shader="Illum" GenMask="4000010000041" StringGenMask="%ALLOW_SILHOUETTE_POM%DETAIL_MAPPING%NORMAL_MAP%SUBSURFACE_SCATTERING" SurfaceType="mat_rock" Diffuse="0.86315733,0.82278591,0.80695242,1" Specular="0.03954624,0.03954624,0.03954624,1" Opacity="1" Shininess="120" vertModifType="0" LayerAct="1">
|
||||
<Textures>
|
||||
<Texture Map="Diffuse" File="objects/natural/rocks/am_rock_square_02_diff.dds"/>
|
||||
<Texture Map="Bumpmap" File="objects/natural/rocks/am_rock_square_02_ddna.dds"/>
|
||||
<Texture Map="Detail" File="objects/natural/rocks/rock03_detail.dds">
|
||||
<TexMod TexMod_RotateType="0" TexMod_TexGenType="0" TexMod_bTexGenProjected="0" TileU="6" TileV="6"/>
|
||||
</Texture>
|
||||
</Textures>
|
||||
<PublicParams EmittanceMapGamma="1" DetailDiffuseScale="0.5" SSSIndex="0" DetailBumpScale="0" DetailGlossScale="0.5" IndirectColor="0.25,0.25,0.25"/>
|
||||
</Material>
|
||||
</SubMaterials>
|
||||
</Material>
|
||||
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:20545079f3e0a61cc144a161999753996797a090f285d63f1c6b1ac1a050729b
|
||||
size 24956
|
||||
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:2cb13a66c6d06e7cd5f06eb05f45c817db0dc76c64afde5225213f742bc0cf40
|
||||
size 1056084
|
||||
-1
@@ -1 +0,0 @@
|
||||
/autooptimizefile=0 /preset=NormalsWithSmoothness /reduce=0
|
||||
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:de80f21e0f6d48e3894fcf309f2564e1b74be0a65e415506034ff144b051bc74
|
||||
size 3157330
|
||||
-1
@@ -1 +0,0 @@
|
||||
/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=Albedo /reduce=0
|
||||
-12
@@ -1,12 +0,0 @@
|
||||
<Material MtlFlags="524544" vertModifType="0">
|
||||
<SubMaterials>
|
||||
<Material Name="AM_Rocks_Small_02_Mat" MtlFlags="524416" Shader="Illum" GenMask="4000010000001" StringGenMask="%ALLOW_SILHOUETTE_POM%NORMAL_MAP%SUBSURFACE_SCATTERING" SurfaceType="mat_rock" Diffuse="1,1,1,1" Specular="0.03954624,0.03954624,0.03954624,1" Opacity="1" Shininess="255" vertModifType="0" LayerAct="1">
|
||||
<Textures>
|
||||
<Texture Map="Diffuse" File="objects/natural/rocks/am_rocks_small_02_diff.dds"/>
|
||||
<Texture Map="Bumpmap" File="objects/natural/rocks/am_rocks_small_02_ddna.dds"/>
|
||||
</Textures>
|
||||
<PublicParams EmittanceMapGamma="1" SSSIndex="0" IndirectColor="0.25,0.25,0.25"/>
|
||||
</Material>
|
||||
</SubMaterials>
|
||||
<PublicParams EmittanceMapGamma="1" SSSIndex="0" IndirectColor="0.25,0.25,0.25"/>
|
||||
</Material>
|
||||
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:c2c2f43f48f2b661f69b955e7009006a6aa616a25131b4b5e9a5017ac6b18193
|
||||
size 1056084
|
||||
-1
@@ -1 +0,0 @@
|
||||
/autooptimizefile=0 /preset=NormalsWithSmoothness /reduce=0
|
||||
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:51ba30ea6a9749edf269e3d22a0eb73ebc4589f87f1d207166cb0f5ad1201a45
|
||||
size 793938
|
||||
-1
@@ -1 +0,0 @@
|
||||
/autooptimizefile=0 /preset=Albedo /reduce=0
|
||||
-12
@@ -1,12 +0,0 @@
|
||||
<Material MtlFlags="524544" vertModifType="0">
|
||||
<SubMaterials>
|
||||
<Material Name="AM_Rocks_Small_02" MtlFlags="524416" Shader="Illum" GenMask="4000010000001" StringGenMask="%ALLOW_SILHOUETTE_POM%NORMAL_MAP%SUBSURFACE_SCATTERING" SurfaceType="mat_rock" Diffuse="1,1,1,1" Specular="0.03954624,0.03954624,0.03954624,1" Opacity="1" Shininess="255" vertModifType="0" LayerAct="1">
|
||||
<Textures>
|
||||
<Texture Map="Diffuse" File="objects/natural/rocks/am_rocks_small_01_diff.dds"/>
|
||||
<Texture Map="Bumpmap" File="objects/natural/rocks/am_rocks_small_01_ddna.dds"/>
|
||||
</Textures>
|
||||
<PublicParams EmittanceMapGamma="1" SSSIndex="0" IndirectColor="0.25,0.25,0.25"/>
|
||||
</Material>
|
||||
</SubMaterials>
|
||||
<PublicParams EmittanceMapGamma="1" SSSIndex="0" IndirectColor="0.25,0.25,0.25"/>
|
||||
</Material>
|
||||
-17
@@ -1,17 +0,0 @@
|
||||
<Material MtlFlags="524544" vertModifType="0">
|
||||
<SubMaterials>
|
||||
<Material Name="AM_Rocks_Small_ShinyM" MtlFlags="524416" Shader="Illum" GenMask="12000020040002" StringGenMask="%ALLOW_SPECULAR_ANTIALIASING%EMITTANCE_MAP%NORMAL_MAP%SPECULAR_MAP%SUBSURFACE_SCATTERING" SurfaceType="mat_default" Diffuse="0.39157251,0.3467041,0.31398875,1" Specular="0.65140575,0.5332765,0.49102089,1" Opacity="1" Shininess="255" vertModifType="0" LayerAct="1">
|
||||
<Textures>
|
||||
<Texture Map="Diffuse" File="objects/natural/rocks/am_rocks_small_02_diff.dds"/>
|
||||
<Texture Map="Bumpmap" File="objects/natural/rocks/am_rocks_small_shiny_ddna.dds"/>
|
||||
<Texture Map="Specular" File="objects/natural/rocks/am_rocks_small_shiny_diff.dds" Filter="0" IsTileU="0" IsTileV="0" TexType="0"/>
|
||||
<Texture Map="Smoothness" File="objects/natural/rocks/am_rocks_small_shiny_ddna.dds"/>
|
||||
<Texture Map="Heightmap" File="textures/natural/terrain/am_rockground_displ.dds">
|
||||
<TexMod TexMod_RotateType="0" TexMod_TexGenType="0" TexMod_bTexGenProjected="0" TileU="0.25" TileV="0.25"/>
|
||||
</Texture>
|
||||
</Textures>
|
||||
<PublicParams EmittanceMapGamma="1" SSSIndex="0" IndirectColor="0.25,0.25,0.25"/>
|
||||
</Material>
|
||||
</SubMaterials>
|
||||
<PublicParams EmittanceMapGamma="1" SSSIndex="0" IndirectColor="0.25,0.25,0.25"/>
|
||||
</Material>
|
||||
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:dda8085556f470dc023e20f6d26c7ea4a5a47ed486db90050e31dfe7838d18dd
|
||||
size 1056058
|
||||
-1
@@ -1 +0,0 @@
|
||||
/autooptimizefile=0 /preset=NormalsWithSmoothness /reduce=0
|
||||
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:37866b8a07a89274c76b53a545076fa0be9071b2fea21787b3c7890f8fa6d303
|
||||
size 793912
|
||||
-1
@@ -1 +0,0 @@
|
||||
/autooptimizefile=0 /preset=Albedo /reduce=0
|
||||
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:21cde0da4644e3153946411ea409e4632ba523b69b0fc681a3b09f523089181e
|
||||
size 12602664
|
||||
-1
@@ -1 +0,0 @@
|
||||
/autooptimizefile=0 /M=50,50,0,50,50,50 /mipgentype=sigma-six /preset=Detail_MergedAlbedoNormalsSmoothness /reduce=0
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user