diff --git a/trinity/Eve/SpaceObject/Children/EveChildMesh.cpp b/trinity/Eve/SpaceObject/Children/EveChildMesh.cpp index e9c32a282..a8d8aa20f 100644 --- a/trinity/Eve/SpaceObject/Children/EveChildMesh.cpp +++ b/trinity/Eve/SpaceObject/Children/EveChildMesh.cpp @@ -2104,6 +2104,16 @@ EveDamageOverlayPtr EveChildMesh::EnsureDamageOverlay() return m_damageOverlay; } +void EveChildMesh::SetArmorDamageShaderEffect( Tr2Effect* effect ) +{ + m_armorDamageShader = effect; +} + +Tr2Effect* EveChildMesh::GetArmorDamageShaderEffect() const +{ + return m_armorDamageShader; +} + const LocatorStructureList* EveChildMesh::GetOwnedDamageLocators() const { for( const auto& sets : m_ownedLocatorSets ) diff --git a/trinity/Eve/SpaceObject/Children/EveChildMesh.h b/trinity/Eve/SpaceObject/Children/EveChildMesh.h index 3bc5fd0ea..3ebd33dd5 100644 --- a/trinity/Eve/SpaceObject/Children/EveChildMesh.h +++ b/trinity/Eve/SpaceObject/Children/EveChildMesh.h @@ -28,6 +28,7 @@ BLUE_DECLARE( TriFrustum ); BLUE_DECLARE( Tr2MeshBase ); BLUE_DECLARE( EveSpaceObject2 ); BLUE_DECLARE( Tr2GpuBufferWrapper ); +BLUE_DECLARE( Tr2Effect ); extern Tr2SuballocatedBuffer g_bakedMorphTargetBuffer; @@ -204,6 +205,8 @@ BLUE_CLASS( EveChildMesh ) : EveDamageOverlayPtr GetDamageOverlay() const; EveDamageOverlayPtr EnsureDamageOverlay(); + void SetArmorDamageShaderEffect( Tr2Effect * effect ); + Tr2Effect* GetArmorDamageShaderEffect() const; bool GetDamageLocatorBindPositionLocal( int index, Vector3& out ) const; bool GetDamageLocatorAnimatedLocal( int index, Vector3& position, Vector3& direction ) const; @@ -325,6 +328,7 @@ BLUE_CLASS( EveChildMesh ) : // armor/hull damage owned by this part, renders whether or not it is attached to a ship EveDamageOverlayPtr m_damageOverlay; + Tr2EffectPtr m_armorDamageShader; }; TYPEDEF_BLUECLASS( EveChildMesh ); diff --git a/trinity/Eve/SpaceObject/Children/EveModularObjectModifier.cpp b/trinity/Eve/SpaceObject/Children/EveModularObjectModifier.cpp index 9214693e2..df2a907e2 100644 --- a/trinity/Eve/SpaceObject/Children/EveModularObjectModifier.cpp +++ b/trinity/Eve/SpaceObject/Children/EveModularObjectModifier.cpp @@ -95,7 +95,7 @@ EveSpaceObjectChild::PartTag EveModularObjectModifier::AddHull( const char* hull auto id = AllocatePartId(); auto size = m_object->GetEffectChildren().size(); auto dna = std::string( hullName ) + ":" + ( factionName[0] ? factionName : m_data->m_faction.c_str() ) + ":" + ( raceName[0] ? raceName : m_data->m_race.c_str() ); - if( !m_sof->BuildChild( m_object, dna.c_str(), id, TransformationMatrix( scale, rotation, position ) ) ) + if( !m_sof->BuildChild( m_object, dna.c_str(), id, TransformationMatrix( scale, rotation, position ), m_armorDamageEffectCache ) ) { return INVALID_PART_TAG; } diff --git a/trinity/Eve/SpaceObject/Children/EveModularObjectModifier.h b/trinity/Eve/SpaceObject/Children/EveModularObjectModifier.h index 53bdc6fc7..2d423131c 100644 --- a/trinity/Eve/SpaceObject/Children/EveModularObjectModifier.h +++ b/trinity/Eve/SpaceObject/Children/EveModularObjectModifier.h @@ -60,6 +60,7 @@ class EveModularObjectModifier : public IRoot EveChildPartDataPtr m_data; EveChildInstancedMeshesPtr m_instancedMeshes; EveSOFPtr m_sof; + EveSOF::ArmorDamageEffectCache m_armorDamageEffectCache; }; TYPEDEF_BLUECLASS( EveModularObjectModifier ); diff --git a/trinity/Eve/SpaceObject/EveSpaceObject2.cpp b/trinity/Eve/SpaceObject/EveSpaceObject2.cpp index 3ac83d052..f31588f6d 100644 --- a/trinity/Eve/SpaceObject/EveSpaceObject2.cpp +++ b/trinity/Eve/SpaceObject/EveSpaceObject2.cpp @@ -3526,7 +3526,7 @@ EveDamageOverlayPtr EveSpaceObject2::EnsureChildDamageOverlay( const LocatorSour if( !overlay ) { overlay = const_cast( range.owner )->EnsureDamageOverlay(); - overlay->SetArmorDamageShaderEffect( m_impactOverlay->GetArmorDamageShaderEffect() ); + overlay->SetArmorDamageShaderEffect( range.owner->GetArmorDamageShaderEffect() ); // each part gets its own flicker curve instance, the async child updates must not share one if( TriPerlinCurve* flickerCurve = m_impactOverlay->GetHullDamageFlickerCurve() ) { diff --git a/trinity/Eve/SpaceObjectFactory/EveSOF.cpp b/trinity/Eve/SpaceObjectFactory/EveSOF.cpp index dfc0b3840..dd57f96c3 100644 --- a/trinity/Eve/SpaceObjectFactory/EveSOF.cpp +++ b/trinity/Eve/SpaceObjectFactory/EveSOF.cpp @@ -198,6 +198,7 @@ IRootPtr EveSOF::BuildFromDNA( const char* dnaString ) SetupConsts( newObj, dna ); int partTag = 1; // we start at 1 because NO_PART_TAG is 0 + ArmorDamageEffectCache armorDamageEffectCache; auto centerOffset = std::vector( 1, IdentityMatrix() ); if( dna->GetBuildClass() == EveSOFDataHull::BUILDCLASS_EXTENSION ) @@ -226,7 +227,7 @@ IRootPtr EveSOF::BuildFromDNA( const char* dnaString ) extensionContainer->SetIsPlacementRoot( true ); EveChildInstancedMeshesPtr sharedMeshes; - CreatePlacement( newObj, sharedMeshes, dna, dna, fakePlacement, std::vector( 1, center ), centerOffset, extensionContainer, partTag, true ); + CreatePlacement( newObj, sharedMeshes, armorDamageEffectCache, dna, dna, fakePlacement, std::vector( 1, center ), centerOffset, extensionContainer, partTag, true ); newObj->AddToEffectChildrenList( extensionContainer ); // create an empty mesh... @@ -256,7 +257,7 @@ IRootPtr EveSOF::BuildFromDNA( const char* dnaString ) // Attachments SetupAttachments( BlueCastPtr( newObj->GetRawRoot() ), dna, centerOffset, EveSOFDataHullBuildFilter::STANDALONE ); - SetupImpactEffects( newObj, dna ); + SetupImpactEffects( newObj, dna, armorDamageEffectCache ); // Effects SetupEffects( newObj, BlueCastPtr( newObj->GetRawRoot() ), dna, centerOffset, EveSOFDataHullBuildFilter::STANDALONE ); @@ -280,7 +281,7 @@ IRootPtr EveSOF::BuildFromDNA( const char* dnaString ) layoutContainer->SetOrigin( EveSpaceObjectChild::SOF ); layoutContainer->SetIsPlacementRoot( true ); layoutContainer->SetAlwaysOn( true ); - SetupLayout( newObj, layoutContainer, sharedMeshes, dna, centerOffset, partTag, true ); + SetupLayout( newObj, layoutContainer, sharedMeshes, armorDamageEffectCache, dna, centerOffset, partTag, true ); if( layoutContainer->m_objects.size() != 0 ) { @@ -308,7 +309,7 @@ IRootPtr EveSOF::BuildFromDNA( const char* dnaString ) return newObj->GetRawRoot(); } -bool EveSOF::BuildChild( EveSpaceObject2* newObj, const char* dnaString, uint32_t partTag, const Matrix& transform ) +bool EveSOF::BuildChild( EveSpaceObject2* newObj, const char* dnaString, uint32_t partTag, const Matrix& transform, ArmorDamageEffectCache& armorDamageEffectCache ) { std::string s = "BuildChild "; s += std::string( dnaString ); @@ -500,12 +501,12 @@ bool EveSOF::BuildChild( EveSpaceObject2* newObj, const char* dnaString, uint32_ if( !newObj->GetImpactOverlay() ) { - SetupImpactEffects( newObj, dna ); + SetupImpactEffects( newObj, dna, armorDamageEffectCache ); } SetupLocatorSets( newObj, dna, placementOffsets, partTag ); // setup nested layout int layoutPartTag = static_cast( partTag ); - SetupLayout( newObj, placementContainer, sharedMeshes, dna, placementOffsets, layoutPartTag, false ); + SetupLayout( newObj, placementContainer, sharedMeshes, armorDamageEffectCache, dna, placementOffsets, layoutPartTag, false ); return true; } @@ -2572,11 +2573,62 @@ void EveSOF::SetupCustomMask( EveSpaceObject2Ptr obj, const EveSOFDNAPtr dna ) c } } +// -------------------------------------------------------------------------------- +// Description: +// Build the armor damage shader effect +// -------------------------------------------------------------------------------- +static Tr2EffectPtr CreateArmorDamageEffect( const EveSOFDNAPtr& dna ) +{ + const EveSOFDataMgr::GenericDamageData* genericDamageData = dna->GetGenericDamageData(); + const EveSOFDataMgr::RaceDamageData* raceDamageData = dna->GetRaceDamageData(); + + Tr2EffectPtr armorDamageShader; + if( !genericDamageData || !raceDamageData ) + { + return armorDamageShader; + } + + armorDamageShader.CreateInstance(); + armorDamageShader->StartUpdate(); + armorDamageShader->SetEffectPathName( dna->GetCompleteShaderPath( genericDamageData->armorShader.c_str() ).c_str() ); + for( const auto& param : raceDamageData->armorDamageParameters ) + { + armorDamageShader->AddParameterVector4( param.first, ¶m.second ); + } + for( const auto& texture : raceDamageData->armorDamageTextures ) + { + armorDamageShader->AddResourceTexture2D( texture.first, texture.second.resFilePath.c_str() ); + } + armorDamageShader->EndUpdate(); + return armorDamageShader; +} + +// -------------------------------------------------------------------------------- +// Description: +// Armor damage effect for a hull or layout part. +// -------------------------------------------------------------------------------- +Tr2EffectPtr EveSOF::GetOrCreateArmorDamageEffect( ArmorDamageEffectCache& cache, const EveSOFDNAPtr& dna ) const +{ + auto key = std::make_pair( dna->GetRaceName(), dna->IsHullAnimated() ); + auto found = cache.find( key ); + if( found != cache.end() ) + { + return found->second; + } + + Tr2EffectPtr armorDamageShader = CreateArmorDamageEffect( dna ); + if( armorDamageShader ) + { + cache[key] = armorDamageShader; + } + return armorDamageShader; +} + // -------------------------------------------------------------------------------- // Description: // Add all kinds of effects to the ship // -------------------------------------------------------------------------------- -void EveSOF::SetupImpactEffects( EveSpaceObject2Ptr obj, const EveSOFDNAPtr dna ) const +void EveSOF::SetupImpactEffects( EveSpaceObject2Ptr obj, const EveSOFDNAPtr dna, ArmorDamageEffectCache& armorDamageEffectCache ) const { EveSOFDataHull::ImpactEffectType impactType = dna->GetImpactEffectType(); // todo - how do we create impact effects for instanced objects? @@ -2640,19 +2692,7 @@ void EveSOF::SetupImpactEffects( EveSpaceObject2Ptr obj, const EveSOFDNAPtr dna } // armor damage impact via shader - Tr2EffectPtr armorDamageShader; - armorDamageShader.CreateInstance(); - armorDamageShader->StartUpdate(); - armorDamageShader->SetEffectPathName( dna->GetCompleteShaderPath( genericDamageData->armorShader.c_str() ).c_str() ); - for( auto it = raceDamageData->armorDamageParameters.begin(); it != raceDamageData->armorDamageParameters.end(); ++it ) - { - armorDamageShader->AddParameterVector4( it->first, &it->second ); - } - for( auto it = raceDamageData->armorDamageTextures.begin(); it != raceDamageData->armorDamageTextures.end(); ++it ) - { - armorDamageShader->AddResourceTexture2D( it->first, it->second.resFilePath.c_str() ); - } - armorDamageShader->EndUpdate(); + Tr2EffectPtr armorDamageShader = GetOrCreateArmorDamageEffect( armorDamageEffectCache, dna ); // armor damage impact via particlesystem Tr2GpuParticleSystem::Emitter psEmitter; @@ -3393,7 +3433,7 @@ std::vector EveSOF::BuildHullLocalLocatorSets( const EveSOFDN return result; } -void EveSOF::SetupLayout( EveSpaceObject2Ptr obj, EveChildContainerPtr layoutContainer, EveChildInstancedMeshesPtr& sharedMeshes, const EveSOFDNAPtr dna, const std::vector& offsets, int& partTag, bool perPlacementTags, uint32_t seedOverwrite ) +void EveSOF::SetupLayout( EveSpaceObject2Ptr obj, EveChildContainerPtr layoutContainer, EveChildInstancedMeshesPtr& sharedMeshes, ArmorDamageEffectCache& armorDamageEffectCache, const EveSOFDNAPtr dna, const std::vector& offsets, int& partTag, bool perPlacementTags, uint32_t seedOverwrite ) { CCP_STATS_ZONE( __FUNCTION__ ); @@ -3447,7 +3487,7 @@ void EveSOF::SetupLayout( EveSpaceObject2Ptr obj, EveChildContainerPtr layoutCon // Go over all the placements (each layout can have multiple mesh attachments) for( auto placement : layout->placements ) { - ProcessPlacementDistributionOrGroup( placement, obj, sharedMeshes, dna, locatorSets, layoutIdx, placementIdx, offsets, layoutContainer, partTag, perPlacementTags ); + ProcessPlacementDistributionOrGroup( placement, obj, sharedMeshes, armorDamageEffectCache, dna, locatorSets, layoutIdx, placementIdx, offsets, layoutContainer, partTag, perPlacementTags ); } if( layout->scrambleSeed ) @@ -3460,6 +3500,7 @@ void EveSOF::SetupLayout( EveSpaceObject2Ptr obj, EveChildContainerPtr layoutCon void EveSOF::ProcessPlacementDistributionOrGroup( EveSOFDataMgr::ExtensionPlacementData& placement, EveSpaceObject2Ptr obj, EveChildInstancedMeshesPtr& sharedMeshes, + ArmorDamageEffectCache& armorDamageEffectCache, const EveSOFDNAPtr dna, std::map>& managedLocatorSets, size_t& layoutIdx, @@ -3486,7 +3527,7 @@ void EveSOF::ProcessPlacementDistributionOrGroup( EveSOFDataMgr::ExtensionPlacem // Go over all the placements (each layout can have multiple mesh attachments) for( auto& placement : placement.placements ) { - ProcessPlacementDistributionOrGroup( placement, obj, sharedMeshes, dna, managedLocatorSets, layoutIdx, placementIdx, offsets, layoutContainer, partTag, perPlacementTags ); + ProcessPlacementDistributionOrGroup( placement, obj, sharedMeshes, armorDamageEffectCache, dna, managedLocatorSets, layoutIdx, placementIdx, offsets, layoutContainer, partTag, perPlacementTags ); } return; } @@ -3590,12 +3631,12 @@ void EveSOF::ProcessPlacementDistributionOrGroup( EveSOFDataMgr::ExtensionPlacem for( auto& locator : locators ) { singleLocator[0] = locator; - CreatePlacement( obj, sharedMeshes, placementDna, dna, placement, singleLocator, offsets, layoutContainer, partTag, perPlacementTags ); + CreatePlacement( obj, sharedMeshes, armorDamageEffectCache, placementDna, dna, placement, singleLocator, offsets, layoutContainer, partTag, perPlacementTags ); } } else { - CreatePlacement( obj, sharedMeshes, placementDna, dna, placement, locators, offsets, layoutContainer, partTag, perPlacementTags ); + CreatePlacement( obj, sharedMeshes, armorDamageEffectCache, placementDna, dna, placement, locators, offsets, layoutContainer, partTag, perPlacementTags ); } } @@ -3815,6 +3856,7 @@ void EveSOF::ProcessLayoutDistributionDistribute( EveSOFDataMgr::ExtensionPlacem void EveSOF::CreatePlacement( EveSpaceObject2Ptr parent, EveChildInstancedMeshesPtr& sharedMeshes, + ArmorDamageEffectCache& armorDamageEffectCache, EveSOFDNAPtr extensionDna, const EveSOFDNAPtr& parentDna, EveSOFDataMgr::ExtensionPlacementData& placement, @@ -3856,9 +3898,14 @@ void EveSOF::CreatePlacement( bool needsPlacementContainer = hasControllers || hasAnimation; std::vector childLocatorSets; + Tr2EffectPtr partArmorDamageShader; if( !placement.isInstanced ) { childLocatorSets = BuildHullLocalLocatorSets( extensionDna ); + if( extensionDna->GetLocatorCount( DAMAGE_LOCATOR_SET_NAME.c_str() ) > 0 ) + { + partArmorDamageShader = GetOrCreateArmorDamageEffect( armorDamageEffectCache, extensionDna ); + } } for( auto& offset : nestedOffsets ) @@ -3923,6 +3970,7 @@ void EveSOF::CreatePlacement( child->SetName( "Hull" ); child->SetupWithStaticTransform( &randomScale, &rotation, &translation, Tr2Lod::TR2_LOD_LOW ); child->SetOwnedLocatorSets( childLocatorSets ); + child->SetArmorDamageShaderEffect( partArmorDamageShader ); child->SetPartTag( perPlacementTags ? partTag++ : partTag ); if( m_editorMode ) @@ -4126,7 +4174,7 @@ void EveSOF::CreatePlacement( SetupLocatorSets( parent, extensionDna, placementOffsets ); } // setup nested layout - SetupLayout( parent, layoutContainer, sharedMeshes, extensionDna, placementOffsets, partTag, perPlacementTags ); + SetupLayout( parent, layoutContainer, sharedMeshes, armorDamageEffectCache, extensionDna, placementOffsets, partTag, perPlacementTags ); CCP_LOGNOTICE( "Creating %s extensions on %zu places", placement.isInstanced ? " instanced" : "", locators.size() ); } diff --git a/trinity/Eve/SpaceObjectFactory/EveSOF.h b/trinity/Eve/SpaceObjectFactory/EveSOF.h index 03e3052c3..59a276da8 100644 --- a/trinity/Eve/SpaceObjectFactory/EveSOF.h +++ b/trinity/Eve/SpaceObjectFactory/EveSOF.h @@ -41,6 +41,8 @@ class EveSOF : public IRoot EveSOF( IRoot* lockobj = NULL ); ~EveSOF(); + using ArmorDamageEffectCache = std::map, Tr2EffectPtr>; + // build a spaceship and return a EveShip2 object IRootPtr Build( const char* hullName, const char* factionName, const char* raceName ); // build a spaceship from a dns string and return a EveShip2 object @@ -50,7 +52,7 @@ class EveSOF : public IRoot * modular object, stamping partTag on every child, locator and mesh instance it creates. * @return False if the DNA did not resolve to a buildable hull. */ - bool BuildChild( EveSpaceObject2* owner, const char* dnaString, uint32_t partTag, const Matrix& transform ); + bool BuildChild( EveSpaceObject2* owner, const char* dnaString, uint32_t partTag, const Matrix& transform, ArmorDamageEffectCache& armorDamageEffectCache ); // validate a dna string (slow!) bool ValidateDNA( const char* dnaString ); @@ -112,9 +114,9 @@ class EveSOF : public IRoot void SetupLocators( EveSpaceObject2Ptr obj, const EveSOFDNAPtr dna ) const; std::vector BuildHullLocalLocatorSets( const EveSOFDNAPtr dna ) const; void SetupLocatorSets( EveSpaceObject2Ptr obj, const EveSOFDNAPtr dna, const std::vector& offsets, EveSpaceObjectChild::PartTag partTag = EveSpaceObjectChild::NO_PART_TAG ); - void SetupImpactEffects( EveSpaceObject2Ptr obj, const EveSOFDNAPtr dna ) const; + void SetupImpactEffects( EveSpaceObject2Ptr obj, const EveSOFDNAPtr dna, ArmorDamageEffectCache& armorDamageEffectCache ) const; void SetupLights( ITr2LightOwnerPtr obj, const EveSOFDNAPtr dna, const std::vector& offsets ) const; - void SetupLayout( EveSpaceObject2Ptr obj, EveChildContainerPtr layoutContainer, EveChildInstancedMeshesPtr& sharedMeshes, const EveSOFDNAPtr dna, const std::vector& offsets, int& partTag, bool perPlacementTags, uint32_t seedOverwrite = 0 ); + void SetupLayout( EveSpaceObject2Ptr obj, EveChildContainerPtr layoutContainer, EveChildInstancedMeshesPtr& sharedMeshes, ArmorDamageEffectCache& armorDamageEffectCache, const EveSOFDNAPtr dna, const std::vector& offsets, int& partTag, bool perPlacementTags, uint32_t seedOverwrite = 0 ); Tr2MeshPtr CreateMesh( const EveSOFDNAPtr dna ) const; @@ -124,6 +126,7 @@ class EveSOF : public IRoot void CreatePlacement( EveSpaceObject2Ptr parent, EveChildInstancedMeshesPtr& sharedMeshes, + ArmorDamageEffectCache& armorDamageEffectCache, EveSOFDNAPtr extensionDna, const EveSOFDNAPtr& parentDna, EveSOFDataMgr::ExtensionPlacementData& placement, @@ -141,9 +144,11 @@ class EveSOF : public IRoot Tr2EffectPtr CreateBoosterEffect( const EveSOFDataMgr::RaceBoosterData* rdata, const BlueSharedString& lodOption, const std::string& effectPath = "res:/Graphics/Effect/Managed/Space/Booster/BoosterVolumetric.fx", const std::map& parameters = {} ) const; + Tr2EffectPtr GetOrCreateArmorDamageEffect( ArmorDamageEffectCache& cache, const EveSOFDNAPtr& dna ) const; + bool ProcessLayoutDistributionConditions( EveSOFDataMgr::ExtensionPlacementData& placement, const EveSOFDNAPtr dna ); void ProcessLayoutDistributionDistribute( EveSOFDataMgr::ExtensionPlacementDistribution& distributionData, const EveSOFDNAPtr dna, std::vector& placementSet, std::vector& managedLocatorSet ); - void ProcessPlacementDistributionOrGroup( EveSOFDataMgr::ExtensionPlacementData& distributionData, EveSpaceObject2Ptr obj, EveChildInstancedMeshesPtr& sharedMeshes, const EveSOFDNAPtr dna, std::map>& managedLocatorSet, size_t& layoutIdx, size_t& placementIdx, const std::vector& offsets, EveChildContainerPtr childContainer, int& partTag, bool perPlacementTags ); + void ProcessPlacementDistributionOrGroup( EveSOFDataMgr::ExtensionPlacementData& distributionData, EveSpaceObject2Ptr obj, EveChildInstancedMeshesPtr& sharedMeshes, ArmorDamageEffectCache& armorDamageEffectCache, const EveSOFDNAPtr dna, std::map>& managedLocatorSet, size_t& layoutIdx, size_t& placementIdx, const std::vector& offsets, EveChildContainerPtr childContainer, int& partTag, bool perPlacementTags ); // helper functions size_t FillMeshAreaVector( Tr2MeshAreaVector* meshAreaVector, TriBatchType areaType, const EveSOFDNAPtr dna, size_t hullIdx, size_t meshIndexOffset ) const;