├── .gitignore ├── .gitmodules ├── Config ├── DefaultEditor.ini ├── DefaultEditorPerProjectUserSettings.ini ├── DefaultEngine.ini └── DefaultGame.ini ├── Content ├── ExampleMap.umap ├── ExampleMap_BuiltData.uasset ├── Examples │ ├── BranchingLines1_BP.uasset │ ├── BranchingLines2_BP.uasset │ ├── BranchingLines3_BP.uasset │ ├── CylinderStrip_BP.uasset │ ├── HeightFieldAnimated_BP.uasset │ ├── HeightFieldNoise_BP.uasset │ ├── SierpinskiLines_BP.uasset │ ├── SierpinskiTetrahedron_BP.uasset │ ├── SimpleCube_BP.uasset │ └── SimpleCylinder_BP.uasset └── Materials │ ├── UVChecker_M.uasset │ └── custom_uv_diag.uasset ├── LICENSE ├── Plugins ├── ProceduralMeshes │ ├── .gitignore │ ├── LICENSE │ ├── ProceduralMeshes.uplugin │ ├── README.md │ ├── Resources │ │ └── Icon128.png │ └── Source │ │ └── ProceduralMeshes │ │ ├── Private │ │ ├── BranchingLinesActor.cpp │ │ ├── CylinderStripActor.cpp │ │ ├── HeightFieldAnimatedActor.cpp │ │ ├── HeightFieldNoiseActor.cpp │ │ ├── ProceduralMeshes.cpp │ │ ├── SierpinskiLineActor.cpp │ │ ├── SierpinskiTetrahedron.cpp │ │ ├── SimpleCubeActor.cpp │ │ └── SimpleCylinderActor.cpp │ │ ├── ProceduralMeshes.Build.cs │ │ └── Public │ │ ├── BranchingLinesActor.h │ │ ├── CylinderStripActor.h │ │ ├── HeightFieldAnimatedActor.h │ │ ├── HeightFieldNoiseActor.h │ │ ├── ProceduralMeshes.h │ │ ├── SierpinskiLineActor.h │ │ ├── SierpinskiTetrahedron.h │ │ ├── SimpleCubeActor.h │ │ └── SimpleCylinderActor.h └── RuntimeMeshComponent │ ├── .gitignore │ ├── CREDITS.md │ ├── Config │ └── FilterPlugin.ini │ ├── LICENSE │ ├── LICENSE.txt │ ├── README.md │ ├── Resources │ └── Icon128.png │ ├── RuntimeMeshComponent.uplugin │ └── Source │ ├── RuntimeMeshComponent │ ├── Private │ │ ├── Components │ │ │ └── RuntimeMeshComponentStatic.cpp │ │ ├── Modifiers │ │ │ ├── RuntimeMeshModifierAdjacency.cpp │ │ │ └── RuntimeMeshModifierNormals.cpp │ │ ├── Providers │ │ │ ├── RuntimeMeshProviderBox.cpp │ │ │ ├── RuntimeMeshProviderCollision.cpp │ │ │ ├── RuntimeMeshProviderMemoryCache.cpp │ │ │ ├── RuntimeMeshProviderModifiers.cpp │ │ │ ├── RuntimeMeshProviderPlane.cpp │ │ │ ├── RuntimeMeshProviderSphere.cpp │ │ │ ├── RuntimeMeshProviderStatic.cpp │ │ │ └── RuntimeMeshProviderStaticMesh.cpp │ │ ├── RuntimeMesh.cpp │ │ ├── RuntimeMeshActor.cpp │ │ ├── RuntimeMeshBlueprintFunctions.cpp │ │ ├── RuntimeMeshComponent.cpp │ │ ├── RuntimeMeshComponentEngineSubsystem.cpp │ │ ├── RuntimeMeshComponentPlugin.cpp │ │ ├── RuntimeMeshComponentProxy.cpp │ │ ├── RuntimeMeshComponentProxy.h │ │ ├── RuntimeMeshComponentSettings.cpp │ │ ├── RuntimeMeshCore.cpp │ │ ├── RuntimeMeshModifier.cpp │ │ ├── RuntimeMeshProvider.cpp │ │ ├── RuntimeMeshProviderTargetInterface.cpp │ │ ├── RuntimeMeshProxy.cpp │ │ ├── RuntimeMeshProxy.h │ │ ├── RuntimeMeshQuickHull.h │ │ ├── RuntimeMeshRendering.cpp │ │ ├── RuntimeMeshRendering.h │ │ ├── RuntimeMeshSectionProxy.cpp │ │ ├── RuntimeMeshSectionProxy.h │ │ ├── RuntimeMeshSlicer.cpp │ │ └── RuntimeMeshStaticMeshConverter.cpp │ ├── Public │ │ ├── Components │ │ │ └── RuntimeMeshComponentStatic.h │ │ ├── Modifiers │ │ │ ├── RuntimeMeshModifierAdjacency.h │ │ │ └── RuntimeMeshModifierNormals.h │ │ ├── Providers │ │ │ ├── RuntimeMeshProviderBox.h │ │ │ ├── RuntimeMeshProviderCollision.h │ │ │ ├── RuntimeMeshProviderMemoryCache.h │ │ │ ├── RuntimeMeshProviderModifiers.h │ │ │ ├── RuntimeMeshProviderPlane.h │ │ │ ├── RuntimeMeshProviderSphere.h │ │ │ ├── RuntimeMeshProviderStatic.h │ │ │ └── RuntimeMeshProviderStaticMesh.h │ │ ├── RuntimeMesh.h │ │ ├── RuntimeMeshActor.h │ │ ├── RuntimeMeshBlueprintFunctions.h │ │ ├── RuntimeMeshCollision.h │ │ ├── RuntimeMeshComponent.h │ │ ├── RuntimeMeshComponentEngineSubsystem.h │ │ ├── RuntimeMeshComponentPlugin.h │ │ ├── RuntimeMeshComponentSettings.h │ │ ├── RuntimeMeshCore.h │ │ ├── RuntimeMeshModifier.h │ │ ├── RuntimeMeshProvider.h │ │ ├── RuntimeMeshProviderTargetInterface.h │ │ ├── RuntimeMeshReference.h │ │ ├── RuntimeMeshRenderable.h │ │ ├── RuntimeMeshSlicer.h │ │ └── RuntimeMeshStaticMeshConverter.h │ ├── RuntimeMeshComponent.Build.cs │ └── RuntimeMeshComponent.natvis │ └── RuntimeMeshComponentEditor │ ├── Private │ ├── RuntimeMeshComponentDetails.cpp │ ├── RuntimeMeshComponentDetails.h │ ├── RuntimeMeshComponentEditorCommands.cpp │ ├── RuntimeMeshComponentEditorPlugin.cpp │ └── RuntimeMeshComponentEditorStyle.cpp │ ├── Public │ ├── IRuntimeMeshComponentEditorPlugin.h │ ├── RuntimeMeshComponentEditorCommands.h │ └── RuntimeMeshComponentEditorStyle.h │ └── RuntimeMeshComponentEditor.Build.cs ├── ProceduralMeshDemos.uproject ├── README.md └── Source ├── ProceduralMeshDemos.Target.cs ├── ProceduralMeshDemos ├── ProceduralMeshDemos.Build.cs ├── ProceduralMeshDemos.cpp ├── ProceduralMeshDemos.h ├── ProceduralMeshDemosGameMode.cpp └── ProceduralMeshDemosGameMode.h └── ProceduralMeshDemosEditor.Target.cs /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | *.obj 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Compiled Dynamic libraries 12 | *.so 13 | *.dylib 14 | *.dll 15 | 16 | # Fortran module files 17 | *.mod 18 | 19 | # Compiled Static libraries 20 | *.lai 21 | *.la 22 | *.a 23 | *.lib 24 | 25 | # Executables 26 | *.exe 27 | *.out 28 | *.app 29 | *.ipa 30 | 31 | # These project files can be generated by the engine 32 | *.xcodeproj 33 | *.sln 34 | *.suo 35 | *.opensdf 36 | *.sdf 37 | *.VC.db 38 | *.opendb 39 | 40 | # Precompiled Assets 41 | SourceArt/**/*.png 42 | SourceArt/**/*.tga 43 | 44 | # Binary Files 45 | Binaries/* 46 | Plugins**/Binaries/* 47 | 48 | # Builds 49 | Build/* 50 | 51 | # Don't ignore icon files in Build 52 | !Build/**/*.ico 53 | 54 | # Configuration files generated by the Editor 55 | Saved/* 56 | 57 | # Compiled source files for the engine to use 58 | Intermediate/* 59 | Plugins**/Intermediate/* 60 | 61 | # Cache files for the editor to use 62 | DerivedDataCache/* 63 | 64 | # Misc 65 | .vs/**/* 66 | .idea/**.* 67 | .DS_Store -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SiggiG/ProceduralMeshDemos/4e2b2949523329cdf4d7d86bd0e5f7fc58821039/.gitmodules -------------------------------------------------------------------------------- /Config/DefaultEditor.ini: -------------------------------------------------------------------------------- 1 | [EditoronlyBP] 2 | bAllowClassAndBlueprintPinMatching=true 3 | bReplaceBlueprintWithClass=true 4 | bDontLoadBlueprintOutsideEditor=true 5 | bBlueprintIsNotBlueprintType=true 6 | -------------------------------------------------------------------------------- /Config/DefaultEditorPerProjectUserSettings.ini: -------------------------------------------------------------------------------- 1 | 2 | 3 | [/Script/SourceCodeAccess.SourceCodeAccessSettings] 4 | PreferredAccessor=VisualStudio2017 5 | 6 | -------------------------------------------------------------------------------- /Config/DefaultEngine.ini: -------------------------------------------------------------------------------- 1 | [URL] 2 | 3 | [/Script/HardwareTargeting.HardwareTargetingSettings] 4 | TargetedHardwareClass=Desktop 5 | AppliedTargetedHardwareClass=Desktop 6 | DefaultGraphicsPerformance=Maximum 7 | AppliedDefaultGraphicsPerformance=Maximum 8 | 9 | [/Script/EngineSettings.GameMapsSettings] 10 | EditorStartupMap=/Game/ExampleMap.ExampleMap 11 | GameDefaultMap=/Game/ExampleMap.ExampleMap 12 | 13 | [/Script/Engine.RendererSettings] 14 | r.DefaultFeature.MotionBlur=False 15 | r.DefaultFeature.AntiAliasing=1 16 | 17 | [/Script/Engine.UserInterfaceSettings] 18 | RenderFocusRule=NavigationOnly 19 | DefaultCursor=None 20 | TextEditBeamCursor=None 21 | CrosshairsCursor=None 22 | GrabHandCursor=None 23 | GrabHandClosedCursor=None 24 | SlashedCircleCursor=None 25 | ApplicationScale=1.000000 26 | UIScaleRule=ShortestSide 27 | CustomScalingRuleClass=None 28 | UIScaleCurve=(EditorCurveData=(PreInfinityExtrap=RCCE_Constant,PostInfinityExtrap=RCCE_Constant,Keys=((Time=480.000000,Value=0.444000),(Time=720.000000,Value=0.666000),(Time=1080.000000,Value=1.000000),(Time=8640.000000,Value=8.000000)),DefaultValue=340282346638528859811704183484516925440.000000),ExternalCurve=None) 29 | 30 | [/Script/Engine.PhysicsSettings] 31 | DefaultGravityZ=-980.000000 32 | DefaultTerminalVelocity=4000.000000 33 | DefaultFluidFriction=0.300000 34 | SimulateScratchMemorySize=262144 35 | RagdollAggregateThreshold=4 36 | TriangleMeshTriangleMinAreaThreshold=5.000000 37 | bEnableAsyncScene=False 38 | bEnableShapeSharing=False 39 | bEnablePCM=True 40 | bEnableStabilization=False 41 | bWarnMissingLocks=True 42 | bEnable2DPhysics=False 43 | LockedAxis=Invalid 44 | DefaultDegreesOfFreedom=Full3D 45 | BounceThresholdVelocity=200.000000 46 | FrictionCombineMode=Average 47 | RestitutionCombineMode=Average 48 | MaxAngularVelocity=3600.000000 49 | MaxDepenetrationVelocity=0.000000 50 | ContactOffsetMultiplier=0.010000 51 | MinContactOffset=0.000100 52 | MaxContactOffset=1.000000 53 | bSimulateSkeletalMeshOnDedicatedServer=True 54 | DefaultShapeComplexity=CTF_UseSimpleAndComplex 55 | bDefaultHasComplexCollision=True 56 | bSuppressFaceRemapTable=False 57 | bSupportUVFromHitResults=False 58 | bDisableActiveActors=False 59 | bDisableCCD=False 60 | MaxPhysicsDeltaTime=0.033333 61 | bSubstepping=False 62 | bSubsteppingAsync=False 63 | MaxSubstepDeltaTime=0.016667 64 | MaxSubsteps=6 65 | SyncSceneSmoothingFactor=0.000000 66 | AsyncSceneSmoothingFactor=0.990000 67 | InitialAverageFrameRate=0.016667 68 | 69 | 70 | -------------------------------------------------------------------------------- /Config/DefaultGame.ini: -------------------------------------------------------------------------------- 1 | [/Script/EngineSettings.GeneralProjectSettings] 2 | ProjectID=397121CB4660605F6EC1319C29D35F94 3 | -------------------------------------------------------------------------------- /Content/ExampleMap.umap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SiggiG/ProceduralMeshDemos/4e2b2949523329cdf4d7d86bd0e5f7fc58821039/Content/ExampleMap.umap -------------------------------------------------------------------------------- /Content/ExampleMap_BuiltData.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SiggiG/ProceduralMeshDemos/4e2b2949523329cdf4d7d86bd0e5f7fc58821039/Content/ExampleMap_BuiltData.uasset -------------------------------------------------------------------------------- /Content/Examples/BranchingLines1_BP.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SiggiG/ProceduralMeshDemos/4e2b2949523329cdf4d7d86bd0e5f7fc58821039/Content/Examples/BranchingLines1_BP.uasset -------------------------------------------------------------------------------- /Content/Examples/BranchingLines2_BP.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SiggiG/ProceduralMeshDemos/4e2b2949523329cdf4d7d86bd0e5f7fc58821039/Content/Examples/BranchingLines2_BP.uasset -------------------------------------------------------------------------------- /Content/Examples/BranchingLines3_BP.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SiggiG/ProceduralMeshDemos/4e2b2949523329cdf4d7d86bd0e5f7fc58821039/Content/Examples/BranchingLines3_BP.uasset -------------------------------------------------------------------------------- /Content/Examples/CylinderStrip_BP.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SiggiG/ProceduralMeshDemos/4e2b2949523329cdf4d7d86bd0e5f7fc58821039/Content/Examples/CylinderStrip_BP.uasset -------------------------------------------------------------------------------- /Content/Examples/HeightFieldAnimated_BP.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SiggiG/ProceduralMeshDemos/4e2b2949523329cdf4d7d86bd0e5f7fc58821039/Content/Examples/HeightFieldAnimated_BP.uasset -------------------------------------------------------------------------------- /Content/Examples/HeightFieldNoise_BP.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SiggiG/ProceduralMeshDemos/4e2b2949523329cdf4d7d86bd0e5f7fc58821039/Content/Examples/HeightFieldNoise_BP.uasset -------------------------------------------------------------------------------- /Content/Examples/SierpinskiLines_BP.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SiggiG/ProceduralMeshDemos/4e2b2949523329cdf4d7d86bd0e5f7fc58821039/Content/Examples/SierpinskiLines_BP.uasset -------------------------------------------------------------------------------- /Content/Examples/SierpinskiTetrahedron_BP.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SiggiG/ProceduralMeshDemos/4e2b2949523329cdf4d7d86bd0e5f7fc58821039/Content/Examples/SierpinskiTetrahedron_BP.uasset -------------------------------------------------------------------------------- /Content/Examples/SimpleCube_BP.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SiggiG/ProceduralMeshDemos/4e2b2949523329cdf4d7d86bd0e5f7fc58821039/Content/Examples/SimpleCube_BP.uasset -------------------------------------------------------------------------------- /Content/Examples/SimpleCylinder_BP.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SiggiG/ProceduralMeshDemos/4e2b2949523329cdf4d7d86bd0e5f7fc58821039/Content/Examples/SimpleCylinder_BP.uasset -------------------------------------------------------------------------------- /Content/Materials/UVChecker_M.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SiggiG/ProceduralMeshDemos/4e2b2949523329cdf4d7d86bd0e5f7fc58821039/Content/Materials/UVChecker_M.uasset -------------------------------------------------------------------------------- /Content/Materials/custom_uv_diag.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SiggiG/ProceduralMeshDemos/4e2b2949523329cdf4d7d86bd0e5f7fc58821039/Content/Materials/custom_uv_diag.uasset -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Sigurdur Gunnarsson 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Plugins/ProceduralMeshes/.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | *.obj 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Compiled Dynamic libraries 12 | *.so 13 | *.dylib 14 | *.dll 15 | 16 | # Fortran module files 17 | *.mod 18 | 19 | # Compiled Static libraries 20 | *.lai 21 | *.la 22 | *.a 23 | *.lib 24 | 25 | # Executables 26 | *.exe 27 | *.out 28 | *.app 29 | *.ipa 30 | 31 | # These project files can be generated by the engine 32 | *.xcodeproj 33 | *.sln 34 | *.suo 35 | *.opensdf 36 | *.sdf 37 | *.VC.db 38 | *.opendb 39 | 40 | # Precompiled Assets 41 | SourceArt/**/*.png 42 | SourceArt/**/*.tga 43 | 44 | # Binary Files 45 | Binaries/* 46 | 47 | # Builds 48 | Build/* 49 | 50 | # Don't ignore icon files in Build 51 | !Build/**/*.ico 52 | 53 | # Configuration files generated by the Editor 54 | Saved/* 55 | 56 | # Compiled source files for the engine to use 57 | Intermediate/* 58 | 59 | # Cache files for the editor to use 60 | DerivedDataCache/* 61 | -------------------------------------------------------------------------------- /Plugins/ProceduralMeshes/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Sigurdur Gunnarsson 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Plugins/ProceduralMeshes/ProceduralMeshes.uplugin: -------------------------------------------------------------------------------- 1 | { 2 | "FileVersion": 3, 3 | "Version": 1, 4 | "VersionName": "1.0", 5 | "FriendlyName": "Procedural Mesh Examples", 6 | "Description": "Examples of procedurally generated meshes", 7 | "Category": "SiggiG", 8 | "CreatedBy": "Sigurdur Gunnarsson", 9 | "CreatedByURL": "https://github.com/SiggiG", 10 | "DocsURL": "https://github.com/SiggiG/ProceduralMeshes", 11 | "MarketplaceURL": "", 12 | "SupportURL": "", 13 | "EnabledByDefault": true, 14 | "CanContainContent": false, 15 | "IsBetaVersion": false, 16 | "Installed": false, 17 | "Modules": [ 18 | { 19 | "Name": "ProceduralMeshes", 20 | "Type": "Runtime", 21 | "LoadingPhase": "Default" 22 | } 23 | ], 24 | "Plugins": [ 25 | { 26 | "Name": "RuntimeMeshComponent", 27 | "Enabled": true 28 | } 29 | ] 30 | } -------------------------------------------------------------------------------- /Plugins/ProceduralMeshes/Resources/Icon128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SiggiG/ProceduralMeshDemos/4e2b2949523329cdf4d7d86bd0e5f7fc58821039/Plugins/ProceduralMeshes/Resources/Icon128.png -------------------------------------------------------------------------------- /Plugins/ProceduralMeshes/Source/ProceduralMeshes/Private/HeightFieldAnimatedActor.cpp: -------------------------------------------------------------------------------- 1 | // Copyright Sigurdur Gunnarsson. All Rights Reserved. 2 | // Licensed under the MIT License. See LICENSE file in the project root for full license information. 3 | // Example heightfield grid animated with sine and cosine waves 4 | 5 | #include "HeightFieldAnimatedActor.h" 6 | #include "Providers/RuntimeMeshProviderStatic.h" 7 | 8 | AHeightFieldAnimatedActor::AHeightFieldAnimatedActor() 9 | { 10 | PrimaryActorTick.bCanEverTick = true; 11 | StaticProvider = CreateDefaultSubobject(TEXT("RuntimeMeshProvider-Static")); 12 | StaticProvider->SetShouldSerializeMeshData(false); 13 | } 14 | 15 | void AHeightFieldAnimatedActor::OnConstruction(const FTransform& Transform) 16 | { 17 | Super::OnConstruction(Transform); 18 | GenerateMesh(); 19 | } 20 | 21 | // This is called when actor is already in level and map is opened 22 | void AHeightFieldAnimatedActor::PostLoad() 23 | { 24 | Super::PostLoad(); 25 | GenerateMesh(); 26 | } 27 | 28 | void AHeightFieldAnimatedActor::SetupMeshBuffers() 29 | { 30 | const int32 NumberOfPoints = (LengthSections + 1) * (WidthSections + 1); 31 | const int32 VertexCount = (LengthSections + 1) * (WidthSections + 1); 32 | const int32 TriangleCount = LengthSections * WidthSections * 2 * 3; // 2x3 vertex indexes per quad 33 | 34 | if (VertexCount != Positions.Num()) 35 | { 36 | Positions.Empty(); 37 | Positions.AddUninitialized(VertexCount); 38 | Normals.Empty(); 39 | Normals.AddUninitialized(VertexCount); 40 | TexCoords.Empty(); 41 | TexCoords.AddUninitialized(VertexCount); 42 | } 43 | 44 | if (TriangleCount != Triangles.Num()) 45 | { 46 | Triangles.Empty(); 47 | Triangles.AddUninitialized(TriangleCount); 48 | } 49 | 50 | if (NumberOfPoints != HeightValues.Num()) 51 | { 52 | HeightValues.Empty(); 53 | HeightValues.AddUninitialized(NumberOfPoints); 54 | } 55 | } 56 | 57 | void AHeightFieldAnimatedActor::GeneratePoints() 58 | { 59 | // Setup example height data 60 | // Combine variations of sine and cosine to create some variable waves 61 | // TODO Convert this to use a parallel for 62 | int32 PointIndex = 0; 63 | 64 | for (int32 X = 0; X < LengthSections + 1; X++) 65 | { 66 | for (int32 Y = 0; Y < WidthSections + 1; Y++) 67 | { 68 | // Just some quick hardcoded offset numbers in there 69 | const float ValueOne = FMath::Cos((X + CurrentAnimationFrameX)*ScaleFactor) * FMath::Sin((Y + CurrentAnimationFrameY)*ScaleFactor); 70 | const float ValueTwo = FMath::Cos((X + CurrentAnimationFrameX*0.7f)*ScaleFactor*2.5f) * FMath::Sin((Y - CurrentAnimationFrameY*0.7f)*ScaleFactor*2.5f); 71 | const float AvgValue = ((ValueOne + ValueTwo) / 2) * Size.Z; 72 | HeightValues[PointIndex++] = AvgValue; 73 | 74 | if (AvgValue > MaxHeightValue) 75 | { 76 | MaxHeightValue = AvgValue; 77 | } 78 | } 79 | } 80 | } 81 | 82 | void AHeightFieldAnimatedActor::Tick(float DeltaSeconds) 83 | { 84 | if (AnimateMesh) 85 | { 86 | CurrentAnimationFrameX += DeltaSeconds * AnimationSpeedX; 87 | CurrentAnimationFrameY += DeltaSeconds * AnimationSpeedY; 88 | GenerateMesh(); 89 | } 90 | } 91 | 92 | void AHeightFieldAnimatedActor::GenerateMesh() 93 | { 94 | GetRuntimeMeshComponent()->Initialize(StaticProvider); 95 | StaticProvider->ClearSection(0, 0); 96 | 97 | if (Size.X < 1 || Size.Y < 1 || LengthSections < 1 || WidthSections < 1) 98 | { 99 | return; 100 | } 101 | 102 | SetupMeshBuffers(); 103 | GeneratePoints(); 104 | 105 | // TODO Convert this to use fast-past updates instead of regenerating the mesh every frame 106 | GenerateGrid(Positions, Triangles, Normals, TexCoords, FVector2D(Size.X, Size.Y), LengthSections, WidthSections, HeightValues); 107 | const TArray EmptyColors{}; 108 | const TArray EmptyTangents; 109 | StaticProvider->CreateSectionFromComponents(0, 0, 0, Positions, Triangles, Normals, TexCoords, EmptyColors, EmptyTangents, ERuntimeMeshUpdateFrequency::Infrequent, false); 110 | StaticProvider->SetupMaterialSlot(0, TEXT("CylinderMaterial"), Material); 111 | } 112 | 113 | void AHeightFieldAnimatedActor::GenerateGrid(TArray& InVertices, TArray& InTriangles, TArray& InNormals, TArray& InTexCoords, const FVector2D InSize, const int32 InLengthSections, const int32 InWidthSections, const TArray& InHeightValues) 114 | { 115 | // Note the coordinates are a bit weird here since I aligned it to the transform (X is forwards or "up", which Y is to the right) 116 | // Should really fix this up and use standard X, Y coords then transform into object space? 117 | const FVector2D SectionSize = FVector2D(InSize.X / InLengthSections, InSize.Y / InWidthSections); 118 | int32 VertexIndex = 0; 119 | int32 TriangleIndex = 0; 120 | 121 | const float LengthSectionsAsFloat = static_cast(InLengthSections); 122 | const float WidthSectionsAsFloat = static_cast(InWidthSections); 123 | 124 | for (int32 X = 0; X < InLengthSections + 1; X++) 125 | { 126 | for (int32 Y = 0; Y < InWidthSections + 1; Y++) 127 | { 128 | // Create a new vertex 129 | const int32 NewVertIndex = VertexIndex++; 130 | const FVector NewVertex = FVector(X * SectionSize.X, Y * SectionSize.Y, InHeightValues[NewVertIndex]); 131 | InVertices[NewVertIndex] = NewVertex; 132 | 133 | // Note that Unreal UV origin (0,0) is top left 134 | const float U = static_cast(X) / LengthSectionsAsFloat; 135 | const float V = static_cast(Y) / WidthSectionsAsFloat; 136 | InTexCoords[NewVertIndex] = FVector2D(U, V); 137 | 138 | // Once we've created enough verts we can start adding polygons 139 | if (X > 0 && Y > 0) 140 | { 141 | // Each row is InWidthSections+1 number of points. 142 | // And we have InLength+1 rows 143 | // Index of current vertex in position is thus: (X * (InWidthSections + 1)) + Y; 144 | const int32 TopRightIndex = (X * (InWidthSections + 1)) + Y; // Should be same as VertIndex1! 145 | const int32 TopLeftIndex = TopRightIndex - 1; 146 | const int32 BottomRightIndex = ((X - 1) * (InWidthSections + 1)) + Y; 147 | const int32 BottomLeftIndex = BottomRightIndex - 1; 148 | 149 | // Now create two triangles from those four vertices 150 | // The order of these (clockwise/counter-clockwise) dictates which way the normal will face. 151 | InTriangles[TriangleIndex++] = BottomLeftIndex; 152 | InTriangles[TriangleIndex++] = TopRightIndex; 153 | InTriangles[TriangleIndex++] = TopLeftIndex; 154 | 155 | InTriangles[TriangleIndex++] = BottomLeftIndex; 156 | InTriangles[TriangleIndex++] = BottomRightIndex; 157 | InTriangles[TriangleIndex++] = TopRightIndex; 158 | 159 | // Normals 160 | const FVector NormalCurrent = FVector::CrossProduct(InVertices[BottomLeftIndex] - InVertices[TopLeftIndex], InVertices[TopLeftIndex] - InVertices[TopRightIndex]).GetSafeNormal(); 161 | InNormals[BottomLeftIndex] = InNormals[BottomRightIndex] = InNormals[TopRightIndex] = InNormals[TopLeftIndex] = NormalCurrent; 162 | } 163 | } 164 | } 165 | } 166 | -------------------------------------------------------------------------------- /Plugins/ProceduralMeshes/Source/ProceduralMeshes/Private/HeightFieldNoiseActor.cpp: -------------------------------------------------------------------------------- 1 | // Copyright Sigurdur Gunnarsson. All Rights Reserved. 2 | // Licensed under the MIT License. See LICENSE file in the project root for full license information. 3 | // Example heightfield generated with noise 4 | 5 | #include "HeightFieldNoiseActor.h" 6 | #include "Providers/RuntimeMeshProviderStatic.h" 7 | 8 | AHeightFieldNoiseActor::AHeightFieldNoiseActor() 9 | { 10 | PrimaryActorTick.bCanEverTick = false; 11 | StaticProvider = CreateDefaultSubobject(TEXT("RuntimeMeshProvider-Static")); 12 | StaticProvider->SetShouldSerializeMeshData(false); 13 | } 14 | 15 | void AHeightFieldNoiseActor::OnConstruction(const FTransform& Transform) 16 | { 17 | Super::OnConstruction(Transform); 18 | GenerateMesh(); 19 | } 20 | 21 | // This is called when actor is already in level and map is opened 22 | void AHeightFieldNoiseActor::PostLoad() 23 | { 24 | Super::PostLoad(); 25 | GenerateMesh(); 26 | } 27 | 28 | void AHeightFieldNoiseActor::SetupMeshBuffers() 29 | { 30 | const int32 NumberOfPoints = (LengthSections + 1) * (WidthSections + 1); 31 | const int32 VertexCount = LengthSections * WidthSections * 4; // 4x vertices per quad/section 32 | const int32 TriangleCount = LengthSections * WidthSections * 2 * 3; // 2x3 vertex indexes per quad 33 | 34 | if (VertexCount != Positions.Num()) 35 | { 36 | Positions.Empty(); 37 | Positions.AddUninitialized(VertexCount); 38 | Normals.Empty(); 39 | Normals.AddUninitialized(VertexCount); 40 | Tangents.Empty(); 41 | Tangents.AddUninitialized(VertexCount); 42 | TexCoords.Empty(); 43 | TexCoords.AddUninitialized(VertexCount); 44 | } 45 | 46 | if (TriangleCount != Triangles.Num()) 47 | { 48 | Triangles.Empty(); 49 | Triangles.AddUninitialized(TriangleCount); 50 | } 51 | 52 | if (NumberOfPoints != HeightValues.Num()) 53 | { 54 | HeightValues.Empty(); 55 | HeightValues.AddUninitialized(NumberOfPoints); 56 | } 57 | } 58 | 59 | void AHeightFieldNoiseActor::GeneratePoints() 60 | { 61 | RngStream.Initialize(RandomSeed); 62 | 63 | // Setup example height data 64 | const int32 NumberOfPoints = (LengthSections + 1) * (WidthSections + 1); 65 | 66 | // Fill height data with random values 67 | for (int32 i = 0; i < NumberOfPoints; i++) 68 | { 69 | HeightValues[i] = RngStream.FRandRange(0, Size.Z); 70 | } 71 | } 72 | 73 | void AHeightFieldNoiseActor::GenerateMesh() 74 | { 75 | GetRuntimeMeshComponent()->Initialize(StaticProvider); 76 | StaticProvider->ClearSection(0, 0); 77 | 78 | if (Size.X < 1 || Size.Y < 1 || LengthSections < 1 || WidthSections < 1) 79 | { 80 | return; 81 | } 82 | 83 | SetupMeshBuffers(); 84 | GeneratePoints(); 85 | GenerateGrid(Positions, Triangles, Normals, Tangents, TexCoords, FVector2D(Size.X, Size.Y), LengthSections, WidthSections, HeightValues); 86 | 87 | const TArray EmptyColors{}; 88 | StaticProvider->CreateSectionFromComponents(0, 0, 0, Positions, Triangles, Normals, TexCoords, EmptyColors, Tangents, ERuntimeMeshUpdateFrequency::Infrequent, false); 89 | StaticProvider->SetupMaterialSlot(0, TEXT("CylinderMaterial"), Material); 90 | } 91 | 92 | void AHeightFieldNoiseActor::GenerateGrid(TArray& InVertices, TArray& InTriangles, TArray& InNormals, TArray& InTangents, TArray& InTexCoords, const FVector2D InSize, const int32 InLengthSections, const int32 InWidthSections, const TArray& InHeightValues) 93 | { 94 | // Note the coordinates are a bit weird here since I aligned it to the transform (X is forwards or "up", which Y is to the right) 95 | // Should really fix this up and use standard X, Y coords then transform into object space? 96 | const FVector2D SectionSize = FVector2D(InSize.X / InLengthSections, InSize.Y / InWidthSections); 97 | int32 VertexIndex = 0; 98 | int32 TriangleIndex = 0; 99 | 100 | for (int32 X = 0; X < InLengthSections; X++) 101 | { 102 | for (int32 Y = 0; Y < InWidthSections; Y++) 103 | { 104 | // Setup a quad 105 | const int32 BottomLeftIndex = VertexIndex++; 106 | const int32 BottomRightIndex = VertexIndex++; 107 | const int32 TopRightIndex = VertexIndex++; 108 | const int32 TopLeftIndex = VertexIndex++; 109 | 110 | const int32 NoiseIndex_BottomLeft = (X * InWidthSections) + Y; 111 | const int32 NoiseIndex_BottomRight = NoiseIndex_BottomLeft + 1; 112 | const int32 NoiseIndex_TopLeft = ((X+1) * InWidthSections) + Y; 113 | const int32 NoiseIndex_TopRight = NoiseIndex_TopLeft + 1; 114 | 115 | const FVector PBottomLeft = FVector(X * SectionSize.X, Y * SectionSize.Y, InHeightValues[NoiseIndex_BottomLeft]); 116 | const FVector PBottomRight = FVector(X * SectionSize.X, (Y+1) * SectionSize.Y, InHeightValues[NoiseIndex_BottomRight]); 117 | const FVector PTopRight = FVector((X + 1) * SectionSize.X, (Y + 1) * SectionSize.Y, InHeightValues[NoiseIndex_TopRight]); 118 | const FVector PTopLeft = FVector((X+1) * SectionSize.X, Y * SectionSize.Y, InHeightValues[NoiseIndex_TopLeft]); 119 | 120 | InVertices[BottomLeftIndex] = PBottomLeft; 121 | InVertices[BottomRightIndex] = PBottomRight; 122 | InVertices[TopRightIndex] = PTopRight; 123 | InVertices[TopLeftIndex] = PTopLeft; 124 | 125 | // Note that Unreal UV origin (0,0) is top left 126 | InTexCoords[BottomLeftIndex] = FVector2D(static_cast(X) / static_cast(InLengthSections), static_cast(Y) / static_cast(InWidthSections)); 127 | InTexCoords[BottomRightIndex] = FVector2D(static_cast(X) / static_cast(InLengthSections), static_cast(Y + 1) / static_cast(InWidthSections)); 128 | InTexCoords[TopRightIndex] = FVector2D(static_cast(X + 1) / static_cast(InLengthSections), static_cast(Y + 1) / static_cast(InWidthSections)); 129 | InTexCoords[TopLeftIndex] = FVector2D(static_cast(X + 1) / static_cast(InLengthSections), static_cast(Y) / static_cast(InWidthSections)); 130 | 131 | // Now create two triangles from those four vertices 132 | // The order of these (clockwise/counter-clockwise) dictates which way the normal will face. 133 | InTriangles[TriangleIndex++] = BottomLeftIndex; 134 | InTriangles[TriangleIndex++] = TopRightIndex; 135 | InTriangles[TriangleIndex++] = TopLeftIndex; 136 | 137 | InTriangles[TriangleIndex++] = BottomLeftIndex; 138 | InTriangles[TriangleIndex++] = BottomRightIndex; 139 | InTriangles[TriangleIndex++] = TopRightIndex; 140 | 141 | // Normals 142 | const FVector NormalCurrent = FVector::CrossProduct(InVertices[BottomLeftIndex] - InVertices[TopLeftIndex], InVertices[TopLeftIndex] - InVertices[TopRightIndex]).GetSafeNormal(); 143 | 144 | // If not smoothing we just set the vertex normal to the same normal as the polygon they belong to 145 | InNormals[BottomLeftIndex] = InNormals[BottomRightIndex] = InNormals[TopRightIndex] = InNormals[TopLeftIndex] = NormalCurrent; 146 | 147 | // Tangents (perpendicular to the surface) 148 | const FVector SurfaceTangent = (PBottomLeft - PBottomRight).GetSafeNormal(); 149 | InTangents[BottomLeftIndex] = InTangents[BottomRightIndex] = InTangents[TopRightIndex] = InTangents[TopLeftIndex] = SurfaceTangent; 150 | } 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /Plugins/ProceduralMeshes/Source/ProceduralMeshes/Private/ProceduralMeshes.cpp: -------------------------------------------------------------------------------- 1 | // Copyright Sigurdur Gunnarsson. All Rights Reserved. 2 | // Licensed under the MIT License. See LICENSE file in the project root for full license information. 3 | 4 | #include "ProceduralMeshes.h" 5 | #include "Modules/ModuleManager.h" 6 | 7 | #define LOCTEXT_NAMESPACE "FProceduralMeshesModule" 8 | 9 | void FProceduralMeshesModule::StartupModule() 10 | { 11 | // This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module 12 | } 13 | 14 | void FProceduralMeshesModule::ShutdownModule() 15 | { 16 | // This function may be called during shutdown to clean up your module. For modules that support dynamic reloading, 17 | // we call this function before unloading the module. 18 | } 19 | 20 | #undef LOCTEXT_NAMESPACE 21 | 22 | IMPLEMENT_MODULE(FProceduralMeshesModule, ProceduralMeshes) -------------------------------------------------------------------------------- /Plugins/ProceduralMeshes/Source/ProceduralMeshes/Private/SimpleCubeActor.cpp: -------------------------------------------------------------------------------- 1 | // Copyright Sigurdur Gunnarsson. All Rights Reserved. 2 | // Licensed under the MIT License. See LICENSE file in the project root for full license information. 3 | // Example cube mesh 4 | 5 | #include "SimpleCubeActor.h" 6 | #include "Providers/RuntimeMeshProviderStatic.h" 7 | 8 | ASimpleCubeActor::ASimpleCubeActor() 9 | { 10 | PrimaryActorTick.bCanEverTick = false; 11 | StaticProvider = CreateDefaultSubobject(TEXT("RuntimeMeshProvider-Static")); 12 | StaticProvider->SetShouldSerializeMeshData(false); 13 | } 14 | 15 | void ASimpleCubeActor::OnConstruction(const FTransform& Transform) 16 | { 17 | Super::OnConstruction(Transform); 18 | GenerateMesh(); 19 | } 20 | 21 | // This is called when actor is already in level and map is opened 22 | void ASimpleCubeActor::PostLoad() 23 | { 24 | Super::PostLoad(); 25 | GenerateMesh(); 26 | } 27 | 28 | void ASimpleCubeActor::SetupMeshBuffers() 29 | { 30 | const int32 VertexCount = 6 * 4; // 6 sides on a cube, 4 verts each 31 | const int32 TriangleCount = 6 * 2 * 3; // 2x triangles per cube side, 3 verts each 32 | 33 | if (VertexCount != Positions.Num()) 34 | { 35 | Positions.Empty(); 36 | Positions.AddUninitialized(VertexCount); 37 | Normals.Empty(); 38 | Normals.AddUninitialized(VertexCount); 39 | Tangents.Empty(); 40 | Tangents.AddUninitialized(VertexCount); 41 | TexCoords.Empty(); 42 | TexCoords.AddUninitialized(VertexCount); 43 | } 44 | 45 | if (TriangleCount != Triangles.Num()) 46 | { 47 | Triangles.Empty(); 48 | Triangles.AddUninitialized(TriangleCount); 49 | } 50 | } 51 | 52 | void ASimpleCubeActor::GenerateMesh() 53 | { 54 | GetRuntimeMeshComponent()->Initialize(StaticProvider); 55 | StaticProvider->ClearSection(0, 0); 56 | SetupMeshBuffers(); 57 | GenerateCube(Positions, Triangles, Normals, Tangents, TexCoords, Size); 58 | 59 | const TArray EmptyColors{}; 60 | StaticProvider->CreateSectionFromComponents(0, 0, 0, Positions, Triangles, Normals, TexCoords, EmptyColors, Tangents, ERuntimeMeshUpdateFrequency::Infrequent, false); 61 | StaticProvider->SetupMaterialSlot(0, TEXT("CubeMaterial"), Material); 62 | } 63 | 64 | void ASimpleCubeActor::GenerateCube(TArray& InVertices, TArray& InTriangles, TArray& InNormals, TArray& InTangents, TArray& InTexCoords, const FVector InSize) 65 | { 66 | // NOTE: Unreal uses an upper-left origin UV 67 | // NOTE: This sample uses a simple UV mapping scheme where each face is the same 68 | // NOTE: For a normal facing towards us, be build the polygon CCW in the order 0-1-2 then 0-2-3 to complete the quad. 69 | // Remember in Unreal, X is forwards, Y is to your right and Z is up. 70 | 71 | // Calculate a half offset so we get correct center of object 72 | const float OffsetX = InSize.X / 2.0f; 73 | const float OffsetY = InSize.Y / 2.0f; 74 | const float OffsetZ = InSize.Z / 2.0f; 75 | 76 | // Define the 8 corners of the cube 77 | const FVector P0 = FVector(OffsetX, OffsetY, -OffsetZ); 78 | const FVector P1 = FVector(OffsetX, -OffsetY, -OffsetZ); 79 | const FVector P2 = FVector(OffsetX, -OffsetY, OffsetZ); 80 | const FVector P3 = FVector(OffsetX, OffsetY, OffsetZ); 81 | const FVector P4 = FVector(-OffsetX, OffsetY, -OffsetZ); 82 | const FVector P5 = FVector(-OffsetX, -OffsetY, -OffsetZ); 83 | const FVector P6 = FVector(-OffsetX, -OffsetY, OffsetZ); 84 | const FVector P7 = FVector(-OffsetX, OffsetY, OffsetZ); 85 | 86 | // Now we create 6x faces, 4 vertices each 87 | int32 VertexOffset = 0; 88 | int32 TriangleOffset = 0; 89 | FVector Normal; 90 | FRuntimeMeshTangent Tangent; 91 | 92 | // Front (+X) face: 0-1-2-3 93 | Normal = FVector(1, 0, 0); 94 | Tangent = FVector(0, 1, 0); 95 | BuildQuad(InVertices, InTriangles, InNormals, InTangents, InTexCoords, P0, P1, P2, P3, VertexOffset, TriangleOffset, Normal, Tangent); 96 | 97 | // Back (-X) face: 5-4-7-6 98 | Normal = FVector(-1, 0, 0); 99 | Tangent = FVector(0, -1, 0); 100 | BuildQuad(InVertices, InTriangles, InNormals, InTangents, InTexCoords, P5, P4, P7, P6, VertexOffset, TriangleOffset, Normal, Tangent); 101 | 102 | // Left (-Y) face: 1-5-6-2 103 | Normal = FVector(0, -1, 0); 104 | Tangent = FVector(1, 0, 0); 105 | BuildQuad(InVertices, InTriangles, InNormals, InTangents, InTexCoords, P1, P5, P6, P2, VertexOffset, TriangleOffset, Normal, Tangent); 106 | 107 | // Right (+Y) face: 4-0-3-7 108 | Normal = FVector(0, 1, 0); 109 | Tangent = FVector(-1, 0, 0); 110 | BuildQuad(InVertices, InTriangles, InNormals, InTangents, InTexCoords, P4, P0, P3, P7, VertexOffset, TriangleOffset, Normal, Tangent); 111 | 112 | // Top (+Z) face: 6-7-3-2 113 | Normal = FVector(0, 0, 1); 114 | Tangent = FVector(0, 1, 0); 115 | BuildQuad(InVertices, InTriangles, InNormals, InTangents, InTexCoords, P6, P7, P3, P2, VertexOffset, TriangleOffset, Normal, Tangent); 116 | 117 | // Bottom (-Z) face: 1-0-4-5 118 | Normal = FVector(0, 0, -1); 119 | Tangent = FVector(0, -1, 0); 120 | BuildQuad(InVertices, InTriangles, InNormals, InTangents, InTexCoords, P1, P0, P4, P5, VertexOffset, TriangleOffset, Normal, Tangent); 121 | } 122 | 123 | void ASimpleCubeActor::BuildQuad(TArray& InVertices, TArray& InTriangles, TArray& InNormals, TArray& InTangents, TArray& InTexCoords, const FVector BottomLeft, const FVector BottomRight, const FVector TopRight, const FVector TopLeft, int32& VertexOffset, int32& TriangleOffset, const FVector Normal, const FRuntimeMeshTangent Tangent) 124 | { 125 | const int32 Index1 = VertexOffset++; 126 | const int32 Index2 = VertexOffset++; 127 | const int32 Index3 = VertexOffset++; 128 | const int32 Index4 = VertexOffset++; 129 | InVertices[Index1] = BottomLeft; 130 | InVertices[Index2] = BottomRight; 131 | InVertices[Index3] = TopRight; 132 | InVertices[Index4] = TopLeft; 133 | InTexCoords[Index1] = FVector2D(0.0f, 1.0f); 134 | InTexCoords[Index2] = FVector2D(1.0f, 1.0f); 135 | InTexCoords[Index3] = FVector2D(1.0f, 0.0f); 136 | InTexCoords[Index4] = FVector2D(0.0f, 0.0f); 137 | InTriangles[TriangleOffset++] = Index1; 138 | InTriangles[TriangleOffset++] = Index2; 139 | InTriangles[TriangleOffset++] = Index3; 140 | InTriangles[TriangleOffset++] = Index1; 141 | InTriangles[TriangleOffset++] = Index3; 142 | InTriangles[TriangleOffset++] = Index4; 143 | // On a cube side, all the vertex normals face the same way 144 | InNormals[Index1] = InNormals[Index2] = InNormals[Index3] = InNormals[Index4] = Normal; 145 | InTangents[Index1] = InTangents[Index2] = InTangents[Index3] = InTangents[Index4] = Tangent; 146 | } 147 | -------------------------------------------------------------------------------- /Plugins/ProceduralMeshes/Source/ProceduralMeshes/ProceduralMeshes.Build.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2016, Sigurdur Gunnarsson. All Rights Reserved. 2 | 3 | using UnrealBuildTool; 4 | 5 | public class ProceduralMeshes : ModuleRules 6 | { 7 | public ProceduralMeshes(ReadOnlyTargetRules Target) : base(Target) 8 | { 9 | PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; 10 | 11 | PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "RuntimeMeshComponent" }); 12 | 13 | PrivateDependencyModuleNames.AddRange( 14 | new string[] 15 | { 16 | "CoreUObject", 17 | "Engine", 18 | }); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Plugins/ProceduralMeshes/Source/ProceduralMeshes/Public/BranchingLinesActor.h: -------------------------------------------------------------------------------- 1 | // Copyright Sigurdur Gunnarsson. All Rights Reserved. 2 | // Licensed under the MIT License. See LICENSE file in the project root for full license information. 3 | // Example branching lines using cylinder strips 4 | 5 | #pragma once 6 | 7 | #include "CoreMinimal.h" 8 | #include "RuntimeMeshActor.h" 9 | #include "BranchingLinesActor.generated.h" 10 | 11 | // A simple struct to keep some data together 12 | USTRUCT() 13 | struct FBranchSegment 14 | { 15 | GENERATED_BODY() 16 | 17 | UPROPERTY() 18 | FVector Start; 19 | 20 | UPROPERTY() 21 | FVector End; 22 | 23 | UPROPERTY() 24 | float Width; 25 | 26 | UPROPERTY() 27 | int8 ForkGeneration; 28 | 29 | FBranchSegment() 30 | { 31 | Start = FVector::ZeroVector; 32 | End = FVector::ZeroVector; 33 | Width = 1.f; 34 | ForkGeneration = 0; 35 | } 36 | 37 | FBranchSegment(FVector start, FVector end) 38 | { 39 | Start = start; 40 | End = end; 41 | Width = 1.f; 42 | ForkGeneration = 0; 43 | } 44 | 45 | FBranchSegment(FVector start, FVector end, float width) 46 | { 47 | Start = start; 48 | End = end; 49 | Width = width; 50 | ForkGeneration = 0; 51 | } 52 | 53 | FBranchSegment(FVector start, FVector end, float width, int8 forkGeneration) 54 | { 55 | Start = start; 56 | End = end; 57 | Width = width; 58 | ForkGeneration = forkGeneration; 59 | } 60 | }; 61 | 62 | UCLASS() 63 | class PROCEDURALMESHES_API ABranchingLinesActor : public ARuntimeMeshActor 64 | { 65 | GENERATED_BODY() 66 | 67 | public: 68 | ABranchingLinesActor(); 69 | 70 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Procedural Parameters", meta = (MakeEditWidget)) 71 | FVector Start; 72 | 73 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Procedural Parameters", meta = (MakeEditWidget)) 74 | FVector End = FVector(0, 0, 300); 75 | 76 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Procedural Parameters") 77 | uint8 Iterations = 5; 78 | 79 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Procedural Parameters") 80 | int32 RadialSegmentCount = 10; 81 | 82 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Procedural Parameters") 83 | bool bSmoothNormals = true; 84 | 85 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Procedural Parameters") 86 | int32 RandomSeed = 1238; 87 | 88 | 89 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Procedural Parameters", meta = (UIMin = "0.1", ClampMin = "0.1")) 90 | float MaxBranchOffset = 20.0f; 91 | 92 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Procedural Parameters") 93 | bool bMaxBranchOffsetAsPercentageOfLength = true; 94 | 95 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Procedural Parameters") 96 | float BranchOffsetReductionEachGenerationPercentage = 50.0f; 97 | 98 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Procedural Parameters") 99 | float TrunkWidth = 2.5f; 100 | 101 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Procedural Parameters", meta = (UIMin = "0", UIMax = "100", ClampMin = "0", ClampMax = "100")) 102 | float ChanceOfForkPercentage = 50.0f; 103 | 104 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Procedural Parameters") 105 | float WidthReductionOnFork = 0.75f; 106 | 107 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Procedural Parameters") 108 | float ForkLengthMin = 0.8f; 109 | 110 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Procedural Parameters") 111 | float ForkLengthMax = 1.3f; 112 | 113 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Procedural Parameters") 114 | float ForkRotationMin = 5.0f; 115 | 116 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Procedural Parameters") 117 | float ForkRotationMax = 40.0f; 118 | 119 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Procedural Parameters") 120 | UMaterialInterface* Material; 121 | 122 | virtual void OnConstruction(const FTransform& Transform) override; 123 | virtual void PostLoad() override; 124 | 125 | protected: 126 | UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Transient) 127 | URuntimeMeshProviderStatic* StaticProvider; 128 | 129 | private: 130 | void GenerateMesh(); 131 | void CreateSegments(); 132 | 133 | UPROPERTY(Transient) 134 | TArray Segments; 135 | 136 | void GenerateCylinder(TArray& InVertices, TArray& InTriangles, TArray& InNormals, TArray& InTangents, TArray& InTexCoords, const FVector StartPoint, const FVector EndPoint, const float InWidth, const int32 InCrossSectionCount, int32& InVertexIndex, int32& InTriangleIndex, const bool bInSmoothNormals = true); 137 | 138 | static FVector RotatePointAroundPivot(const FVector InPoint, const FVector InPivot, const FVector InAngles); 139 | void PreCacheCrossSection(); 140 | 141 | int32 LastCachedCrossSectionCount; 142 | UPROPERTY(Transient) 143 | TArray CachedCrossSectionPoints; 144 | 145 | UPROPERTY(Transient) 146 | TArray OffsetDirections; 147 | 148 | UPROPERTY(Transient) 149 | FRandomStream RngStream; 150 | 151 | // Mesh buffers 152 | void SetupMeshBuffers(); 153 | UPROPERTY(Transient) 154 | TArray Positions; 155 | UPROPERTY(Transient) 156 | TArray Triangles; 157 | UPROPERTY(Transient) 158 | TArray Normals; 159 | UPROPERTY(Transient) 160 | TArray Tangents; 161 | UPROPERTY(Transient) 162 | TArray TexCoords; 163 | }; 164 | -------------------------------------------------------------------------------- /Plugins/ProceduralMeshes/Source/ProceduralMeshes/Public/CylinderStripActor.h: -------------------------------------------------------------------------------- 1 | // Copyright Sigurdur Gunnarsson. All Rights Reserved. 2 | // Licensed under the MIT License. See LICENSE file in the project root for full license information. 3 | // Example cylinder strip mesh 4 | 5 | #pragma once 6 | 7 | #include "CoreMinimal.h" 8 | #include "RuntimeMeshActor.h" 9 | #include "CylinderStripActor.generated.h" 10 | 11 | UCLASS() 12 | class PROCEDURALMESHES_API ACylinderStripActor : public ARuntimeMeshActor 13 | { 14 | GENERATED_BODY() 15 | 16 | public: 17 | ACylinderStripActor(); 18 | 19 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Procedural Parameters") 20 | TArray LinePoints; 21 | 22 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Procedural Parameters") 23 | float Radius = 10; 24 | 25 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Procedural Parameters") 26 | int32 RadialSegmentCount = 10; 27 | 28 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Procedural Parameters") 29 | bool bSmoothNormals = true; 30 | 31 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Procedural Parameters") 32 | UMaterialInterface* Material; 33 | 34 | virtual void OnConstruction(const FTransform& Transform) override; 35 | virtual void PostLoad() override; 36 | 37 | protected: 38 | UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Transient) 39 | URuntimeMeshProviderStatic* StaticProvider; 40 | 41 | private: 42 | 43 | void GenerateMesh(); 44 | void GenerateCylinder(TArray& InVertices, TArray& InTriangles, TArray& InNormals, TArray& InTangents, TArray& InTexCoords, const FVector StartPoint, const FVector EndPoint, const float InWidth, const int32 InCrossSectionCount, int32& InVertexIndex, int32& InTriangleIndex, const bool bInSmoothNormals = true); 45 | 46 | static FVector RotatePointAroundPivot(const FVector InPoint, const FVector InPivot, const FVector InAngles); 47 | void PreCacheCrossSection(); 48 | 49 | int32 LastCachedCrossSectionCount; 50 | UPROPERTY(Transient) 51 | TArray CachedCrossSectionPoints; 52 | 53 | // Mesh buffers 54 | void SetupMeshBuffers(); 55 | UPROPERTY(Transient) 56 | TArray Positions; 57 | UPROPERTY(Transient) 58 | TArray Triangles; 59 | UPROPERTY(Transient) 60 | TArray Normals; 61 | UPROPERTY(Transient) 62 | TArray Tangents; 63 | UPROPERTY(Transient) 64 | TArray TexCoords; 65 | }; 66 | -------------------------------------------------------------------------------- /Plugins/ProceduralMeshes/Source/ProceduralMeshes/Public/HeightFieldAnimatedActor.h: -------------------------------------------------------------------------------- 1 | // Copyright Sigurdur Gunnarsson. All Rights Reserved. 2 | // Licensed under the MIT License. See LICENSE file in the project root for full license information. 3 | // Example heightfield grid animated with sine and cosine waves 4 | 5 | #pragma once 6 | 7 | #include "CoreMinimal.h" 8 | #include "RuntimeMeshActor.h" 9 | #include "HeightFieldAnimatedActor.generated.h" 10 | 11 | UCLASS() 12 | class PROCEDURALMESHES_API AHeightFieldAnimatedActor : public ARuntimeMeshActor // TODO Create a new provider instead of using the static provider 13 | { 14 | GENERATED_BODY() 15 | 16 | public: 17 | AHeightFieldAnimatedActor(); 18 | 19 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Procedural Parameters") 20 | FVector Size = FVector(1000.0f, 1000.0f, 100.0f); 21 | 22 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Procedural Parameters") 23 | float ScaleFactor = 1.0f; 24 | 25 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Procedural Parameters") 26 | int32 LengthSections = 10; 27 | 28 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Procedural Parameters") 29 | int32 WidthSections = 10; 30 | 31 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Procedural Parameters") 32 | UMaterialInterface* Material; 33 | 34 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Procedural Parameters") 35 | bool AnimateMesh = false; 36 | 37 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Procedural Parameters") 38 | float AnimationSpeedX = 4.0f; 39 | 40 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Procedural Parameters") 41 | float AnimationSpeedY = 4.5f; 42 | 43 | virtual void OnConstruction(const FTransform& Transform) override; 44 | virtual void PostLoad() override; 45 | 46 | virtual void Tick(float DeltaSeconds) override; 47 | 48 | protected: 49 | // TODO Create a new provider instead of using the static provider 50 | UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Transient) 51 | URuntimeMeshProviderStatic* StaticProvider; 52 | 53 | float CurrentAnimationFrameX = 0.0f; 54 | float CurrentAnimationFrameY = 0.0f; 55 | 56 | private: 57 | void GenerateMesh(); 58 | void GeneratePoints(); 59 | static void GenerateGrid(TArray& InVertices, TArray& InTriangles, TArray& InNormals, TArray& InTexCoords, const FVector2D InSize, const int32 InLengthSections, const int32 InWidthSections, const TArray& InHeightValues); 60 | 61 | UPROPERTY(Transient) 62 | TArray HeightValues; 63 | float MaxHeightValue = 0.0f; 64 | 65 | // Mesh buffers 66 | void SetupMeshBuffers(); 67 | UPROPERTY(Transient) 68 | TArray Positions; 69 | UPROPERTY(Transient) 70 | TArray Triangles; 71 | UPROPERTY(Transient) 72 | TArray Normals; 73 | UPROPERTY(Transient) 74 | TArray TexCoords; 75 | }; 76 | -------------------------------------------------------------------------------- /Plugins/ProceduralMeshes/Source/ProceduralMeshes/Public/HeightFieldNoiseActor.h: -------------------------------------------------------------------------------- 1 | // Copyright Sigurdur Gunnarsson. All Rights Reserved. 2 | // Licensed under the MIT License. See LICENSE file in the project root for full license information. 3 | // Example heightfield generated with noise 4 | 5 | #pragma once 6 | 7 | #include "CoreMinimal.h" 8 | #include "RuntimeMeshActor.h" 9 | #include "HeightFieldNoiseActor.generated.h" 10 | 11 | UCLASS() 12 | class PROCEDURALMESHES_API AHeightFieldNoiseActor : public ARuntimeMeshActor 13 | { 14 | GENERATED_BODY() 15 | 16 | public: 17 | AHeightFieldNoiseActor(); 18 | 19 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Procedural Parameters") 20 | FVector Size = FVector(1000.0f, 1000.0f, 20.0f); 21 | 22 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Procedural Parameters") 23 | int32 LengthSections = 100; 24 | 25 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Procedural Parameters") 26 | int32 WidthSections = 100; 27 | 28 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Procedural Parameters") 29 | int32 RandomSeed = 1238; 30 | 31 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Procedural Parameters") 32 | UMaterialInterface* Material; 33 | 34 | virtual void OnConstruction(const FTransform& Transform) override; 35 | virtual void PostLoad() override; 36 | 37 | protected: 38 | UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Transient) 39 | URuntimeMeshProviderStatic* StaticProvider; 40 | 41 | private: 42 | void GenerateMesh(); 43 | void GeneratePoints(); 44 | static void GenerateGrid(TArray& InVertices, TArray& InTriangles, TArray& InNormals, TArray& InTangents, TArray& InTexCoords, const FVector2D InSize, const int32 InLengthSections, const int32 InWidthSections, const TArray& InHeightValues); 45 | 46 | UPROPERTY(Transient) 47 | FRandomStream RngStream; 48 | 49 | UPROPERTY(Transient) 50 | TArray HeightValues; 51 | 52 | // Mesh buffers 53 | void SetupMeshBuffers(); 54 | UPROPERTY(Transient) 55 | TArray Positions; 56 | UPROPERTY(Transient) 57 | TArray Triangles; 58 | UPROPERTY(Transient) 59 | TArray Normals; 60 | UPROPERTY(Transient) 61 | TArray Tangents; 62 | UPROPERTY(Transient) 63 | TArray TexCoords; 64 | }; 65 | -------------------------------------------------------------------------------- /Plugins/ProceduralMeshes/Source/ProceduralMeshes/Public/ProceduralMeshes.h: -------------------------------------------------------------------------------- 1 | // Copyright Sigurdur Gunnarsson. All Rights Reserved. 2 | // Licensed under the MIT License. See LICENSE file in the project root for full license information. 3 | 4 | #pragma once 5 | 6 | #include "CoreMinimal.h" 7 | 8 | class FProceduralMeshesModule : public IModuleInterface 9 | { 10 | public: 11 | 12 | /** IModuleInterface implementation */ 13 | virtual void StartupModule() override; 14 | virtual void ShutdownModule() override; 15 | }; -------------------------------------------------------------------------------- /Plugins/ProceduralMeshes/Source/ProceduralMeshes/Public/SierpinskiLineActor.h: -------------------------------------------------------------------------------- 1 | // Copyright Sigurdur Gunnarsson. All Rights Reserved. 2 | // Licensed under the MIT License. See LICENSE file in the project root for full license information. 3 | // Example Sierpinski pyramid using cylinder lines 4 | 5 | #pragma once 6 | 7 | #include "CoreMinimal.h" 8 | #include "RuntimeMeshActor.h" 9 | #include "SierpinskiLineActor.generated.h" 10 | 11 | // A simple struct to keep some data together 12 | USTRUCT() 13 | struct FPyramidLine 14 | { 15 | GENERATED_BODY() 16 | 17 | UPROPERTY() 18 | FVector Start; 19 | 20 | UPROPERTY() 21 | FVector End; 22 | 23 | UPROPERTY() 24 | float Width; 25 | 26 | FPyramidLine() 27 | { 28 | Start = FVector::ZeroVector; 29 | End = FVector::ZeroVector; 30 | Width = 1.0f; 31 | } 32 | 33 | FPyramidLine(FVector InStart, FVector InEnd) 34 | { 35 | Start = InStart; 36 | End = InEnd; 37 | Width = 1.0f; 38 | } 39 | 40 | FPyramidLine(FVector InStart, FVector InEnd, float InWidth) 41 | { 42 | Start = InStart; 43 | End = InEnd; 44 | Width = InWidth; 45 | } 46 | }; 47 | 48 | UCLASS() 49 | class PROCEDURALMESHES_API ASierpinskiLineActor : public ARuntimeMeshActor 50 | { 51 | GENERATED_BODY() 52 | 53 | public: 54 | ASierpinskiLineActor(); 55 | 56 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Procedural Parameters") 57 | float Size = 400.0f; 58 | 59 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Procedural Parameters") 60 | int32 Iterations = 5; 61 | 62 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Procedural Parameters") 63 | float LineThickness = 2.0f; 64 | 65 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Procedural Parameters") 66 | float ThicknessMultiplierPerGeneration = 0.8f; 67 | 68 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Procedural Parameters") 69 | int32 RadialSegmentCount = 4; 70 | 71 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Procedural Parameters") 72 | bool bSmoothNormals = false; 73 | 74 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Procedural Parameters") 75 | UMaterialInterface* Material; 76 | 77 | virtual void OnConstruction(const FTransform& Transform) override; 78 | virtual void PostLoad() override; 79 | 80 | protected: 81 | UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Transient) 82 | URuntimeMeshProviderStatic* StaticProvider; 83 | 84 | private: 85 | void GenerateMesh(); 86 | 87 | UPROPERTY(Transient) 88 | TArray Lines; 89 | 90 | void GenerateLines(); 91 | void AddSection(FVector InBottomLeftPoint, FVector InTopPoint, FVector InBottomRightPoint, FVector InBottomMiddlePoint, int32 InDepth); 92 | void GenerateCylinder(TArray& InVertices, TArray& InTriangles, TArray& InNormals, TArray& InTangents, TArray& InTexCoords, const FVector StartPoint, const FVector EndPoint, const float InWidth, const int32 InCrossSectionCount, int32& VertexIndex, int32& TriangleIndex, const bool bInSmoothNormals = true); 93 | 94 | static FVector RotatePointAroundPivot(const FVector InPoint, const FVector InPivot, const FVector InAngles); 95 | void PreCacheCrossSection(); 96 | 97 | int32 LastCachedCrossSectionCount; 98 | UPROPERTY(Transient) 99 | TArray CachedCrossSectionPoints; 100 | 101 | // Mesh buffers 102 | void SetupMeshBuffers(); 103 | UPROPERTY(Transient) 104 | TArray Positions; 105 | UPROPERTY(Transient) 106 | TArray Triangles; 107 | UPROPERTY(Transient) 108 | TArray Normals; 109 | UPROPERTY(Transient) 110 | TArray Tangents; 111 | UPROPERTY(Transient) 112 | TArray TexCoords; 113 | }; 114 | -------------------------------------------------------------------------------- /Plugins/ProceduralMeshes/Source/ProceduralMeshes/Public/SierpinskiTetrahedron.h: -------------------------------------------------------------------------------- 1 | // Copyright Sigurdur Gunnarsson. All Rights Reserved. 2 | // Licensed under the MIT License. See LICENSE file in the project root for full license information. 3 | // Example Sierpinski tetrahedron 4 | 5 | #pragma once 6 | 7 | #include "CoreMinimal.h" 8 | #include "RuntimeMeshActor.h" 9 | #include "SierpinskiTetrahedron.generated.h" 10 | 11 | UENUM(BlueprintType) 12 | enum class ETetrahedronSide : uint8 13 | { 14 | Front, 15 | Left, 16 | Right, 17 | Bottom 18 | }; 19 | 20 | USTRUCT() 21 | struct FTetrahedronStructure 22 | { 23 | GENERATED_BODY() 24 | 25 | FVector CornerBottomLeft; 26 | FVector CornerBottomRight; 27 | FVector CornerBottomMiddle; 28 | FVector CornerTop; 29 | 30 | // Remove these and provide ways to calculate them instead 31 | FVector FrontFaceLeftPoint; 32 | FVector2D FrontFaceLeftPointUV; 33 | FVector FrontFaceRightPoint; 34 | FVector2D FrontFaceRightPointUV; 35 | FVector FrontFaceTopPoint; 36 | FVector2D FrontFaceTopPointUV; 37 | 38 | FVector LeftFaceLeftPoint; 39 | FVector2D LeftFaceLeftPointUV; 40 | FVector LeftFaceRightPoint; 41 | FVector2D LeftFaceRightPointUV; 42 | FVector LeftFaceTopPoint; 43 | FVector2D LeftFaceTopPointUV; 44 | 45 | FVector RightFaceLeftPoint; 46 | FVector2D RightFaceLeftPointUV; 47 | FVector RightFaceRightPoint; 48 | FVector2D RightFaceRightPointUV; 49 | FVector RightFaceTopPoint; 50 | FVector2D RightFaceTopPointUV; 51 | 52 | FVector BottomFaceLeftPoint; 53 | FVector2D BottomFaceLeftPointUV; 54 | FVector BottomFaceRightPoint; 55 | FVector2D BottomFaceRightPointUV; 56 | FVector BottomFaceTopPoint; 57 | FVector2D BottomFaceTopPointUV; 58 | 59 | FVector FrontFaceNormal; 60 | FVector LeftFaceNormal; 61 | FVector RightFaceNormal; 62 | FVector BottomFaceNormal; 63 | 64 | FTetrahedronStructure() 65 | { 66 | } 67 | 68 | FTetrahedronStructure(const FVector InCornerBottomLeft, const FVector InCornerBottomRight, const FVector InCornerBottomMiddle, const FVector InCornerTop) 69 | { 70 | CornerBottomLeft = InCornerBottomLeft; 71 | CornerBottomRight = InCornerBottomRight; 72 | CornerBottomMiddle = InCornerBottomMiddle; 73 | CornerTop = InCornerTop; 74 | 75 | // Now setup each face 76 | FrontFaceLeftPoint = CornerBottomLeft; 77 | FrontFaceLeftPointUV = FVector2D(0, 1); 78 | FrontFaceRightPoint = CornerBottomRight; 79 | FrontFaceRightPointUV = FVector2D(1, 1); 80 | FrontFaceTopPoint = CornerTop; 81 | FrontFaceTopPointUV = FVector2D(0.5f, 0); 82 | 83 | FrontFaceNormal = FVector::CrossProduct(FrontFaceTopPoint - FrontFaceLeftPoint, FrontFaceRightPoint - FrontFaceLeftPoint).GetSafeNormal(); 84 | 85 | LeftFaceLeftPoint = CornerBottomMiddle; 86 | LeftFaceLeftPointUV = FVector2D(0, 1); 87 | LeftFaceRightPoint = CornerBottomLeft; 88 | LeftFaceRightPointUV = FVector2D(1, 1); 89 | LeftFaceTopPoint = CornerTop; 90 | LeftFaceTopPointUV = FVector2D(0.5f, 0); 91 | 92 | LeftFaceNormal = FVector::CrossProduct(LeftFaceTopPoint - LeftFaceLeftPoint, LeftFaceRightPoint - LeftFaceLeftPoint).GetSafeNormal(); 93 | 94 | RightFaceLeftPoint = CornerBottomRight; 95 | RightFaceLeftPointUV = FVector2D(0, 1); 96 | RightFaceRightPoint = CornerBottomMiddle; 97 | RightFaceRightPointUV = FVector2D(1, 1); 98 | RightFaceTopPoint = CornerTop; 99 | RightFaceTopPointUV = FVector2D(0.5f, 0); 100 | 101 | RightFaceNormal = FVector::CrossProduct(RightFaceTopPoint - RightFaceLeftPoint, RightFaceRightPoint - RightFaceLeftPoint).GetSafeNormal(); 102 | 103 | BottomFaceLeftPoint = CornerBottomRight; 104 | BottomFaceLeftPointUV = FVector2D(0, 1); 105 | BottomFaceRightPoint = CornerBottomLeft; 106 | BottomFaceRightPointUV = FVector2D(1, 1); 107 | BottomFaceTopPoint = CornerBottomMiddle; 108 | BottomFaceTopPointUV = FVector2D(0.5f, 0); 109 | 110 | BottomFaceNormal = FVector::CrossProduct(BottomFaceTopPoint - BottomFaceLeftPoint, BottomFaceRightPoint - BottomFaceLeftPoint).GetSafeNormal(); 111 | } 112 | }; 113 | 114 | UCLASS() 115 | class PROCEDURALMESHES_API ASierpinskiTetrahedron : public ARuntimeMeshActor 116 | { 117 | GENERATED_BODY() 118 | 119 | public: 120 | ASierpinskiTetrahedron(); 121 | 122 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Procedural Parameters") 123 | float Size = 400.0f; 124 | 125 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Procedural Parameters") 126 | int32 Iterations = 5; // 4^5 = 1024 tetrahedrons 127 | 128 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Procedural Parameters") 129 | UMaterialInterface* Material; 130 | 131 | virtual void OnConstruction(const FTransform& Transform) override; 132 | virtual void PostLoad() override; 133 | 134 | protected: 135 | UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Transient) 136 | URuntimeMeshProviderStatic* StaticProvider; 137 | 138 | private: 139 | 140 | void GenerateMesh(); 141 | 142 | void GenerateTetrahedron(const FTetrahedronStructure& Tetrahedron, int32 InDepth, TArray& InVertices, TArray& InTriangles, TArray& InNormals, TArray& InTangents, TArray& InTexCoords, int32& VertexIndex, int32& TriangleIndex) const; 143 | static void AddTetrahedronPolygons(const FTetrahedronStructure& Tetrahedron, TArray& InVertices, TArray& InTriangles, TArray& InNormals, TArray& InTangents, TArray& InTexCoords, int32& VertexIndex, int32& TriangleIndex); 144 | static void AddPolygon(const FVector& Point1, const FVector2D& Point1UV, const FVector& Point2, const FVector2D& Point2UV, const FVector& Point3, const FVector2D& Point3UV, FVector const FaceNormal, TArray& InVertices, TArray& InTriangles, TArray& InNormals, TArray& InTangents, TArray& InTexCoords, int32& VertexIndex, int32& TriangleIndex); 145 | void SetTetrahedronUV(FTetrahedronStructure& Tetrahedron) const; 146 | FVector2D GetUVForSide(const FVector Point, const ETetrahedronSide Side) const; 147 | 148 | UPROPERTY(Transient) 149 | FTetrahedronStructure FirstTetrahedron; 150 | 151 | // Mesh buffers 152 | void SetupMeshBuffers(); 153 | UPROPERTY(Transient) 154 | TArray Positions; 155 | UPROPERTY(Transient) 156 | TArray Triangles; 157 | UPROPERTY(Transient) 158 | TArray Normals; 159 | UPROPERTY(Transient) 160 | TArray Tangents; 161 | UPROPERTY(Transient) 162 | TArray TexCoords; 163 | 164 | // Pre-calculated vectors that define a quad for each tetrahedron side 165 | void PrecalculateTetrahedronSideQuads(); 166 | FVector FrontQuadTopLeftPoint; 167 | FVector FrontQuadTopSide; 168 | FVector FrontQuadLeftSide; 169 | 170 | FVector LeftQuadTopLeftPoint; 171 | FVector LeftQuadTopSide; 172 | FVector LeftQuadLeftSide; 173 | 174 | FVector RightQuadTopLeftPoint; 175 | FVector RightQuadTopSide; 176 | FVector RightQuadLeftSide; 177 | 178 | FVector BottomQuadTopLeftPoint; 179 | FVector BottomQuadTopSide; 180 | FVector BottomQuadLeftSide; 181 | }; 182 | -------------------------------------------------------------------------------- /Plugins/ProceduralMeshes/Source/ProceduralMeshes/Public/SimpleCubeActor.h: -------------------------------------------------------------------------------- 1 | // Copyright Sigurdur Gunnarsson. All Rights Reserved. 2 | // Licensed under the MIT License. See LICENSE file in the project root for full license information. 3 | // Example cube mesh 4 | 5 | #pragma once 6 | 7 | #include "CoreMinimal.h" 8 | #include "RuntimeMeshActor.h" 9 | #include "SimpleCubeActor.generated.h" 10 | 11 | class URuntimeMeshProviderStatic; 12 | struct FRuntimeMeshTangent; 13 | 14 | UCLASS() 15 | class PROCEDURALMESHES_API ASimpleCubeActor : public ARuntimeMeshActor 16 | { 17 | GENERATED_BODY() 18 | 19 | public: 20 | ASimpleCubeActor(); 21 | 22 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Procedural Parameters") 23 | FVector Size = FVector(100.0f, 100.0f, 100.0f); 24 | 25 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Procedural Parameters") 26 | UMaterialInterface* Material; 27 | 28 | virtual void OnConstruction(const FTransform& Transform) override; 29 | virtual void PostLoad() override; 30 | 31 | protected: 32 | UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Transient) 33 | URuntimeMeshProviderStatic* StaticProvider; 34 | 35 | private: 36 | void GenerateMesh(); 37 | static void GenerateCube(TArray& InVertices, TArray& InTriangles, TArray& InNormals, TArray& InTangents, TArray& InTexCoords, FVector InSize); 38 | static void BuildQuad(TArray& InVertices, TArray& InTriangles, TArray& InNormals, TArray& InTangents, TArray& InTexCoords, const FVector BottomLeft, const FVector BottomRight, const FVector TopRight, const FVector TopLeft, int32& VertexOffset, int32& TriangleOffset, const FVector Normal, const FRuntimeMeshTangent Tangent); 39 | 40 | // Mesh buffers 41 | void SetupMeshBuffers(); 42 | UPROPERTY(Transient) 43 | TArray Positions; 44 | UPROPERTY(Transient) 45 | TArray Triangles; 46 | UPROPERTY(Transient) 47 | TArray Normals; 48 | UPROPERTY(Transient) 49 | TArray Tangents; 50 | UPROPERTY(Transient) 51 | TArray TexCoords; 52 | }; 53 | -------------------------------------------------------------------------------- /Plugins/ProceduralMeshes/Source/ProceduralMeshes/Public/SimpleCylinderActor.h: -------------------------------------------------------------------------------- 1 | // Copyright Sigurdur Gunnarsson. All Rights Reserved. 2 | // Licensed under the MIT License. See LICENSE file in the project root for full license information. 3 | // Example cylinder mesh 4 | 5 | #pragma once 6 | 7 | #include "CoreMinimal.h" 8 | #include "RuntimeMeshActor.h" 9 | #include "SimpleCylinderActor.generated.h" 10 | 11 | UCLASS() 12 | class PROCEDURALMESHES_API ASimpleCylinderActor : public ARuntimeMeshActor 13 | { 14 | GENERATED_BODY() 15 | 16 | public: 17 | ASimpleCylinderActor(); 18 | 19 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Procedural Parameters") 20 | float Radius = 10; 21 | 22 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Procedural Parameters") 23 | float Height = 100; 24 | 25 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Procedural Parameters") 26 | int32 RadialSegmentCount = 10; 27 | 28 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Procedural Parameters") 29 | bool bCapEnds = true; 30 | 31 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Procedural Parameters") 32 | bool bDoubleSided = false; 33 | 34 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Procedural Parameters") 35 | bool bSmoothNormals = true; 36 | 37 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Procedural Parameters") 38 | UMaterialInterface* Material; 39 | 40 | virtual void OnConstruction(const FTransform& Transform) override; 41 | virtual void PostLoad() override; 42 | 43 | protected: 44 | UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Transient) 45 | URuntimeMeshProviderStatic* StaticProvider; 46 | 47 | private: 48 | 49 | void GenerateMesh(); 50 | static void GenerateCylinder(TArray& InVertices, TArray& InTriangles, TArray& InNormals, TArray& InTangents, TArray& InTexCoords, const float InHeight, const float InWidth, const int32 InCrossSectionCount, const bool bInCapEnds = false, const bool bInDoubleSided = false, const bool bInSmoothNormals = true); 51 | 52 | // Mesh buffers 53 | void SetupMeshBuffers(); 54 | UPROPERTY(Transient) 55 | TArray Positions; 56 | UPROPERTY(Transient) 57 | TArray Triangles; 58 | UPROPERTY(Transient) 59 | TArray Normals; 60 | UPROPERTY(Transient) 61 | TArray Tangents; 62 | UPROPERTY(Transient) 63 | TArray TexCoords; 64 | }; 65 | -------------------------------------------------------------------------------- /Plugins/RuntimeMeshComponent/.gitignore: -------------------------------------------------------------------------------- 1 | # Git files 2 | .git/ 3 | 4 | # Visual Studio 2015 user specific files 5 | .vs/ 6 | 7 | # Visual Studio 2015 database file 8 | *.VC.db 9 | 10 | # Compiled Object files 11 | *.slo 12 | *.lo 13 | *.o 14 | *.obj 15 | 16 | # Precompiled Headers 17 | *.gch 18 | *.pch 19 | 20 | # Compiled Dynamic libraries 21 | *.so 22 | *.dylib 23 | *.dll 24 | 25 | # Fortran module files 26 | *.mod 27 | 28 | # Compiled Static libraries 29 | *.lai 30 | *.la 31 | *.a 32 | *.lib 33 | 34 | # Executables 35 | *.exe 36 | *.out 37 | *.app 38 | *.ipa 39 | 40 | # These project files can be generated by the engine 41 | *.xcodeproj 42 | *.xcworkspace 43 | *.sln 44 | *.suo 45 | *.opensdf 46 | *.sdf 47 | *.VC.db 48 | *.VC.opendb 49 | 50 | # Precompiled Assets 51 | SourceArt/**/*.png 52 | SourceArt/**/*.tga 53 | 54 | # Binary Files 55 | Binaries/** 56 | Plugins/*/Binaries/* 57 | 58 | # Builds 59 | Build/* 60 | 61 | # Whitelist PakBlacklist-.txt files 62 | !Build/*/ 63 | Build/*/** 64 | !Build/*/PakBlacklist*.txt 65 | 66 | # Don't ignore icon files in Build 67 | !Build/**/*.ico 68 | 69 | # Built data for maps 70 | *_BuiltData.uasset 71 | 72 | # Configuration files generated by the Editor 73 | Saved/* 74 | 75 | # Compiled source files for the engine to use 76 | Intermediate/** 77 | Plugins/*/Intermediate/* 78 | 79 | # Cache files for the editor to use 80 | DerivedDataCache/* 81 | 82 | # Mac crap 83 | .DS_Store 84 | 85 | # Un-Ignore All ThirdParty binary/libs etc. 86 | !Source/ThirdParty/** 87 | 88 | # Ignore Export directory 89 | Export/** 90 | 91 | # Ignore VS Code files 92 | .vscode/** 93 | 94 | # Unignore .github folder 95 | !.github/** 96 | 97 | # Unignore .gitignore 98 | !.gitignore -------------------------------------------------------------------------------- /Plugins/RuntimeMeshComponent/CREDITS.md: -------------------------------------------------------------------------------- 1 | # Thank you to those of you who have contributed code to the project over the years! 2 | 3 | ### Special thanks to Moddingear who has submitted numerous code submissions, as well as assisted with the docs and helping the community in Discord 4 | [Moddingear](https://github.com/Moddingear) 5 | 6 | ### Contributors 7 | 8 | [alleysark](https://github.com/alleysark) 9 | [bhumphreys](https://github.com/bhumphreys) 10 | [caswal](https://github.com/caswal) 11 | [connorjak](https://github.com/connorjak) 12 | [davenye](https://github.com/davenye) 13 | [GlassBeaver](https://github.com/GlassBeaver) 14 | [gribuser](https://github.com/gribuser) 15 | [iblackcat](https://github.com/iblackcat) 16 | [JerryHyun](https://github.com/JerryHyun) 17 | [Kuldaen](https://github.com/Kuldaen) 18 | [manlok876](https://github.com/manlok876) 19 | [Maze-DK](https://github.com/Maze-DK) 20 | [michaeltchapman](https://github.com/michaeltchapman) 21 | [RaiaN](https://github.com/RaiaN) 22 | [RPG3D](https://github.com/RPG3D) 23 | [RumbleballTheReal](https://github.com/RumbleballTheReal) 24 | [SiggiG](https://github.com/SiggiG) 25 | [timdecode](https://github.com/timdecode) 26 | -------------------------------------------------------------------------------- /Plugins/RuntimeMeshComponent/Config/FilterPlugin.ini: -------------------------------------------------------------------------------- 1 | [FilterPlugin] 2 | ; This section lists additional files which will be packaged along with your plugin. Paths should be listed relative to the root plugin directory, and 3 | ; may include "...", "*", and "?" wildcards to match directories, files, and individual characters respectively. 4 | ; 5 | ; Examples: 6 | ; /README.txt 7 | ; /Extras/... 8 | ; /Binaries/ThirdParty/*.dll 9 | 10 | /CREDITS.md 11 | /README.md -------------------------------------------------------------------------------- /Plugins/RuntimeMeshComponent/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016-2020 Chris Conway (Koderz) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Plugins/RuntimeMeshComponent/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Runtime Mesh Component Community MIT License 2 | 3 | Copyright (c) 2016-2020 TriAxis Games L.L.C. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | 24 | Contributor License Agreement 25 | By contributing your code to Runtime Mesh Component you grant TriAxis Games L.L.C. 26 | a non-exclusive, irrevocable, worldwide, royalty-free, sublicenseable, 27 | transferable license under all of Your relevant intellectual property rights 28 | (including copyright, patent, and any other rights), to use, copy, prepare 29 | derivative works of, distribute and publicly perform and display the Contributions 30 | on any licensing terms, including without limitation: (a) open source licenses 31 | like the MIT license; and (b) binary, proprietary, or commercial licenses. Except 32 | for the licenses granted herein, You reserve all right, title, and interest in and 33 | to the Contribution. 34 | 35 | You confirm that you are able to grant us these rights. You represent that You are 36 | legally entitled to grant the above license. If Your employer has rights to 37 | intellectual property that You create, You represent that You have received 38 | permission to make the Contributions on behalf of that employer, or that Your 39 | employer has waived such rights for the Contributions. 40 | 41 | You represent that the Contributions are Your original works of authorship, and 42 | to Your knowledge, no other person claims, or has the right to claim, any right 43 | in any invention or patent related to the Contributions. You also represent that 44 | You are not legally obligated, whether by entering into an agreement or otherwise, 45 | in any way that conflicts with the terms of this license. 46 | 47 | TriAxis Games L.L.C. acknowledges that, except as explicitly described in this 48 | Agreement, any Contribution which you provide is on an "AS IS" BASIS, WITHOUT 49 | WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, 50 | WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, 51 | MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. -------------------------------------------------------------------------------- /Plugins/RuntimeMeshComponent/README.md: -------------------------------------------------------------------------------- 1 | # Runtime Mesh Component for Unreal Engine 4 2 | --- 3 | ### Here you will find the current version of the RMC. At present it only supports UE4.23 and newer. 4 | ### If you require support for UE4.20-4.22 you'll need to use the v4 release found here: https://github.com/KoderzUnreal/RuntimeMeshComponent/releases/tag/v4.0 5 | --- 6 | 7 | **For information on installation, usage and everything else, [please read the docs!](https://runtimemesh.koderz.io/)** 8 | 9 | --- 10 | **Join us on [Discord](https://discord.gg/KGvBBTv)** 11 | 12 | **Basic examples of the features of the RMC can be found [here!](https://github.com/TriAxis-Games/RuntimeMeshComponent-Examples)** 13 | **A more advanced example project can be found [here!](https://github.com/Moddingear/Hexagons)** 14 | 15 | **This project is a labor of love, but unfortunately love doesn't pay the bills! 16 | If you've found this project useful, please consider supporting the development! 17 | [You can support the project here!](https://github.com/Koderz/RuntimeMeshComponent/wiki/Support-the-development!)** 18 | 19 | --- 20 | 21 | The RuntimeMeshComponent or more commonly known as RMC, is a replacement to the ProceduralMeshComponent (aka PMC) found in UE4. The RMC is much more efficient, and carries many more features, while allowing for a much more fine-grained approach for advanced use cases, while being simple to use just like the PMC. It can handle any use case from simply loading models at runtime, to debug views, to modification of existing models all the way up to procedural generation of entire worlds! 22 | 23 | The RMC has been around for 4+ years and has an active community of users from individuals, to schools, to Fortune 500 companies, with many released projects. You can also find active support in our Discord server here: https://discord.gg/KGvBBTv 24 | 25 | --- 26 | 27 | Features (Community Edition): 28 | * Full Collision Support, both static triangle mesh and dynamic moving objects 29 | * Variable mesh formats, allowing for tradeoff in needed features and memory/performance overhead 30 | * Up to 8 Texture Coordinate (UV) channels 31 | * Normal or High preicision Texture Coordinate (UV) channels 32 | * Normal or High preicision texture coordinates, supports engine feature for high precision normals 33 | * LOD Support, alowing engine maximum of 8 LOD levels and full dithering support 34 | * Full NavMesh support 35 | * Tessellation support, including generation 36 | * Full threading support, both internally managing threads and allowing for your external threading safely around the garbage collector. 37 | * Async collision updates. As collision can be slow to update, the RMC can offload it from the game thread. 38 | * Separate collision from rendering 39 | * StaticMesh conversion in game and editor. 40 | * Tangent generation utility 41 | * Mesh Slicer 42 | 43 | 44 | Features (Premium Edition): 45 | * All features found in RMC-Community! 46 | * Additional Reversed Indices buffer for inverted views or inverted transforms like negative scaling. 47 | * Depth Only Indices, allow for a separate index buffer for depth prepass and shadows for improved performance 48 | * Distance Field support. Supports engine features like DF Shadows, and DF Ambient Occlusion, and material distance queries, and Niagara collision 49 | * Distance Field generation on CPU. RMC can generate the DF for you on the CPU, GPU implementation coming later. 50 | * Model loading of many common formats including obj, stl, fbx, x, 3ds, dae, and more through Assimp 51 | * Optimization-ReIndex, can reindex the mesh to remove redundant vertices. 52 | * Optimization-VertexOrder, Forsyth algorithm to optimize the order of vertices to improve caching efficiency 53 | * Optimization-Overdraw, Reducing overdraw of a mesh by rearranging triangles 54 | * Optimization-VertexFetch, Improve memory coherency by ordering vertex buffer to more efficiently work with triangle order 55 | * Texture loading support for .jpg/.jpeg, .png, .tga, .bmp, .psd, .gif 56 | * Texture mipmap generation support 57 | 58 | 59 | Improvements over PMC: 60 | * 50-90% Lower memory useage than PMC 61 | * 30-100% lower render thread cpu time 62 | * Static draw path for maximum rendering performance 63 | * Dynamic Draw path for efficient frequent updates. 64 | 65 | 66 | 67 | **Supported Engine Versions:** 68 | v4.1 supports engine versions 4.23+ 69 | v4.0 supports engine versions 4.20+ 70 | v3.0 supports engine versions 4.17+ 71 | v2.0 supports engine versions 4.12+ 72 | v1.2 supports engine versions 4.10+ 73 | 74 | *The Runtime Mesh Component should support all UE4 platforms.* 75 | *Collision MAY NOT be available on some platforms (HTML5)* 76 | -------------------------------------------------------------------------------- /Plugins/RuntimeMeshComponent/Resources/Icon128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SiggiG/ProceduralMeshDemos/4e2b2949523329cdf4d7d86bd0e5f7fc58821039/Plugins/RuntimeMeshComponent/Resources/Icon128.png -------------------------------------------------------------------------------- /Plugins/RuntimeMeshComponent/RuntimeMeshComponent.uplugin: -------------------------------------------------------------------------------- 1 | { 2 | "FileVersion": 3, 3 | "Version": 41, 4 | "VersionName": "4.1", 5 | "FriendlyName": "Runtime Mesh Component Community", 6 | "Description": "A component allowing for rendering and interacting with runtime generated geometry.", 7 | "Category": "Rendering", 8 | "CreatedBy": "Chris Conway (Koderz)", 9 | "CreatedByURL": "hhttps://github.com/Koderz", 10 | "DocsURL": "https://runtimemesh.koderz.io/", 11 | "MarketplaceURL": "com.epicgames.launcher://ue/marketplace/content/ad0b45a6a31e462aba7cf7c790a9c125", 12 | "SupportURL": "https://github.com/TriAxis-Games/RuntimeMeshComponent/issues", 13 | "EnabledByDefault": true, 14 | "CanContainContent": false, 15 | "IsBetaVersion": false, 16 | "Installed": false, 17 | "Modules": [ 18 | { 19 | "Name": "RuntimeMeshComponent", 20 | "Type": "Runtime", 21 | "LoadingPhase": "Default", 22 | "WhitelistPlatforms": [ 23 | "Win64", 24 | "Linux", 25 | "Mac", 26 | "XboxOne", 27 | "PS4" 28 | ] 29 | }, 30 | { 31 | "Name": "RuntimeMeshComponentEditor", 32 | "Type": "Editor", 33 | "LoadingPhase": "Default", 34 | "WhitelistPlatforms": [ 35 | "Win64", 36 | "Linux", 37 | "Mac" 38 | ] 39 | } 40 | ] 41 | } -------------------------------------------------------------------------------- /Plugins/RuntimeMeshComponent/Source/RuntimeMeshComponent/Private/Modifiers/RuntimeMeshModifierAdjacency.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2020 TriAxis Games L.L.C. All Rights Reserved. 2 | 3 | 4 | #include "Modifiers/RuntimeMeshModifierAdjacency.h" 5 | #include "Logging/MessageLog.h" 6 | 7 | const uint32 EdgesPerTriangle = 3; 8 | const uint32 IndicesPerTriangle = 3; 9 | const uint32 VerticesPerTriangle = 3; 10 | const uint32 DuplicateIndexCount = 3; 11 | 12 | const uint32 PnAenDomCorner_IndicesPerPatch = 12; 13 | 14 | DECLARE_CYCLE_STAT(TEXT("RML - Calculate Tessellation Indices"), STAT_RuntimeMeshLibrary_CalculateTessellationIndices, STATGROUP_RuntimeMesh); 15 | 16 | URuntimeMeshModifierAdjacency::URuntimeMeshModifierAdjacency() 17 | { 18 | 19 | } 20 | 21 | void URuntimeMeshModifierAdjacency::ApplyToMesh_Implementation(FRuntimeMeshRenderableMeshData& MeshData) 22 | { 23 | if (MeshData.TexCoords.Num() == MeshData.Positions.Num() && MeshData.Tangents.Num() == MeshData.Positions.Num()) 24 | { 25 | CalculateTessellationIndices(MeshData); 26 | } 27 | else 28 | { 29 | FFormatNamedArguments Arguments; 30 | Arguments.Add(TEXT("NumPositions"), MeshData.Positions.Num()); 31 | Arguments.Add(TEXT("NumNormals"), MeshData.Tangents.Num()); 32 | Arguments.Add(TEXT("NumTexCoords"), MeshData.TexCoords.Num()); 33 | FText Message = FText::Format(NSLOCTEXT("RuntimeMeshModifierAdjacency", "InvalidMeshDataForTessellation", "Supplied mesh doesn't contain enough data to calculate adjacency triangles for tessellation. All must be same length: Positions:{NumPositions} Normals:{NumNormals} TexCoords:{NumTexCoords}"), Arguments); 34 | FMessageLog("RuntimeMesh").Error(Message); 35 | } 36 | } 37 | 38 | void URuntimeMeshModifierAdjacency::CalculateTessellationIndices(FRuntimeMeshRenderableMeshData& MeshData) 39 | { 40 | SCOPE_CYCLE_COUNTER(STAT_RuntimeMeshLibrary_CalculateTessellationIndices); 41 | 42 | int32 NumIndices = MeshData.Triangles.Num(); 43 | 44 | EdgeDictionary EdgeDict; 45 | EdgeDict.Reserve(NumIndices); 46 | PositionDictionary PosDict; 47 | PosDict.Reserve(NumIndices); 48 | 49 | MeshData.AdjacencyTriangles.SetNum(PnAenDomCorner_IndicesPerPatch * (NumIndices / IndicesPerTriangle)); 50 | 51 | ExpandIB(MeshData, EdgeDict, PosDict); 52 | 53 | ReplacePlaceholderIndices(MeshData, EdgeDict, PosDict); 54 | } 55 | 56 | void URuntimeMeshModifierAdjacency::AddIfLeastUV(PositionDictionary& PosDict, const Vertex& Vert, uint32 Index) 57 | { 58 | auto* Pos = PosDict.Find(Vert.Position); 59 | if (Pos == nullptr) 60 | { 61 | PosDict.Add(Vert.Position, Corner(Index, Vert.TexCoord)); 62 | } 63 | else if (Vert.TexCoord < Pos->TexCoord) 64 | { 65 | PosDict[Vert.Position] = Corner(Index, Vert.TexCoord); 66 | } 67 | } 68 | 69 | 70 | void URuntimeMeshModifierAdjacency::ReplacePlaceholderIndices(FRuntimeMeshRenderableMeshData& MeshData, EdgeDictionary& EdgeDict, PositionDictionary& PosDict) 71 | { 72 | int32 NumIndices = MeshData.Triangles.Num(); 73 | const uint32 TriangleCount = NumIndices / PnAenDomCorner_IndicesPerPatch; 74 | 75 | for (uint32 U = 0; U < TriangleCount; U++) 76 | { 77 | const uint32 StartOutIndex = U * PnAenDomCorner_IndicesPerPatch; 78 | 79 | const uint32 Index0 = MeshData.AdjacencyTriangles.GetVertexIndex(StartOutIndex + 0); 80 | const uint32 Index1 = MeshData.AdjacencyTriangles.GetVertexIndex(StartOutIndex + 1); 81 | const uint32 Index2 = MeshData.AdjacencyTriangles.GetVertexIndex(StartOutIndex + 2); 82 | 83 | const Vertex Vertex0(MeshData.Positions.GetPosition(Index0), MeshData.TexCoords.GetTexCoord(Index0)); 84 | const Vertex Vertex1(MeshData.Positions.GetPosition(Index1), MeshData.TexCoords.GetTexCoord(Index1)); 85 | const Vertex Vertex2(MeshData.Positions.GetPosition(Index2), MeshData.TexCoords.GetTexCoord(Index2)); 86 | 87 | Triangle Tri(Index0, Index1, Index2, Vertex0, Vertex1, Vertex2); 88 | 89 | Edge* Ed = EdgeDict.Find(Tri.GetEdge(0)); 90 | if (Ed != nullptr) 91 | { 92 | MeshData.AdjacencyTriangles.SetVertexIndex(StartOutIndex + 3, Ed->GetIndex(0)); 93 | MeshData.AdjacencyTriangles.SetVertexIndex(StartOutIndex + 4, Ed->GetIndex(1)); 94 | } 95 | 96 | Ed = EdgeDict.Find(Tri.GetEdge(1)); 97 | if (Ed != nullptr) 98 | { 99 | MeshData.AdjacencyTriangles.SetVertexIndex(StartOutIndex + 5, Ed->GetIndex(0)); 100 | MeshData.AdjacencyTriangles.SetVertexIndex(StartOutIndex + 6, Ed->GetIndex(1)); 101 | } 102 | 103 | Ed = EdgeDict.Find(Tri.GetEdge(2)); 104 | if (Ed != nullptr) 105 | { 106 | MeshData.AdjacencyTriangles.SetVertexIndex(StartOutIndex + 7, Ed->GetIndex(0)); 107 | MeshData.AdjacencyTriangles.SetVertexIndex(StartOutIndex + 8, Ed->GetIndex(1)); 108 | } 109 | 110 | // Deal with dominant positions. 111 | for (uint32 V = 0; V < VerticesPerTriangle; V++) 112 | { 113 | Corner* Corn = PosDict.Find(Tri.GetEdge(V).GetVertex(0).Position); 114 | if (Corn != nullptr) 115 | { 116 | MeshData.AdjacencyTriangles.SetVertexIndex(StartOutIndex + 9 + V, Corn->Index); 117 | } 118 | } 119 | } 120 | } 121 | 122 | 123 | void URuntimeMeshModifierAdjacency::ExpandIB(FRuntimeMeshRenderableMeshData& MeshData, EdgeDictionary& OutEdgeDict, PositionDictionary& OutPosDict) 124 | { 125 | int32 NumIndices = MeshData.Triangles.Num(); 126 | const uint32 TriangleCount = NumIndices / IndicesPerTriangle; 127 | 128 | for (uint32 U = 0; U < TriangleCount; U++) 129 | { 130 | const uint32 StartInIndex = U * IndicesPerTriangle; 131 | const uint32 StartOutIndex = U * PnAenDomCorner_IndicesPerPatch; 132 | 133 | const uint32 Index0 = MeshData.Triangles.GetVertexIndex(U * 3 + 0); 134 | const uint32 Index1 = MeshData.Triangles.GetVertexIndex(U * 3 + 1); 135 | const uint32 Index2 = MeshData.Triangles.GetVertexIndex(U * 3 + 2); 136 | 137 | const Vertex Vertex0(MeshData.Positions.GetPosition(Index0), MeshData.TexCoords.GetTexCoord(Index0)); 138 | const Vertex Vertex1(MeshData.Positions.GetPosition(Index1), MeshData.TexCoords.GetTexCoord(Index1)); 139 | const Vertex Vertex2(MeshData.Positions.GetPosition(Index2), MeshData.TexCoords.GetTexCoord(Index2)); 140 | 141 | Triangle Tri(Index0, Index1, Index2, Vertex0, Vertex1, Vertex2); 142 | 143 | if ((uint32)MeshData.AdjacencyTriangles.Num() <= (StartOutIndex + PnAenDomCorner_IndicesPerPatch)) 144 | { 145 | MeshData.AdjacencyTriangles.SetNum((StartOutIndex + PnAenDomCorner_IndicesPerPatch) + 1); 146 | } 147 | 148 | MeshData.AdjacencyTriangles.SetVertexIndex(StartOutIndex + 0, Tri.GetIndex(0)); 149 | MeshData.AdjacencyTriangles.SetVertexIndex(StartOutIndex + 1, Tri.GetIndex(1)); 150 | MeshData.AdjacencyTriangles.SetVertexIndex(StartOutIndex + 2, Tri.GetIndex(2)); 151 | 152 | MeshData.AdjacencyTriangles.SetVertexIndex(StartOutIndex + 3, Tri.GetIndex(0)); 153 | MeshData.AdjacencyTriangles.SetVertexIndex(StartOutIndex + 4, Tri.GetIndex(1)); 154 | 155 | MeshData.AdjacencyTriangles.SetVertexIndex(StartOutIndex + 5, Tri.GetIndex(1)); 156 | MeshData.AdjacencyTriangles.SetVertexIndex(StartOutIndex + 6, Tri.GetIndex(2)); 157 | 158 | MeshData.AdjacencyTriangles.SetVertexIndex(StartOutIndex + 7, Tri.GetIndex(2)); 159 | MeshData.AdjacencyTriangles.SetVertexIndex(StartOutIndex + 8, Tri.GetIndex(0)); 160 | 161 | MeshData.AdjacencyTriangles.SetVertexIndex(StartOutIndex + 9, Tri.GetIndex(0)); 162 | MeshData.AdjacencyTriangles.SetVertexIndex(StartOutIndex + 10, Tri.GetIndex(1)); 163 | MeshData.AdjacencyTriangles.SetVertexIndex(StartOutIndex + 11, Tri.GetIndex(2)); 164 | 165 | 166 | Edge Rev0 = Tri.GetEdge(0).GetReverse(); 167 | Edge Rev1 = Tri.GetEdge(1).GetReverse(); 168 | Edge Rev2 = Tri.GetEdge(2).GetReverse(); 169 | 170 | OutEdgeDict.Add(Rev0, Rev0); 171 | OutEdgeDict.Add(Rev1, Rev1); 172 | OutEdgeDict.Add(Rev2, Rev2); 173 | 174 | AddIfLeastUV(OutPosDict, Vertex0, Index0); 175 | AddIfLeastUV(OutPosDict, Vertex1, Index1); 176 | AddIfLeastUV(OutPosDict, Vertex2, Index2); 177 | } 178 | } 179 | 180 | 181 | -------------------------------------------------------------------------------- /Plugins/RuntimeMeshComponent/Source/RuntimeMeshComponent/Private/Providers/RuntimeMeshProviderCollision.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2020 TriAxis Games L.L.C. All Rights Reserved. 2 | 3 | 4 | #include "Providers/RuntimeMeshProviderCollision.h" 5 | 6 | 7 | URuntimeMeshProviderCollision::URuntimeMeshProviderCollision() 8 | : LODForMeshCollision(0) 9 | { 10 | 11 | } 12 | 13 | void URuntimeMeshProviderCollision::SetCollisionSettings(const FRuntimeMeshCollisionSettings& NewCollisionSettings) 14 | { 15 | { 16 | FScopeLock Lock(&SyncRoot); 17 | CollisionSettings = NewCollisionSettings; 18 | } 19 | MarkCollisionDirty(); 20 | } 21 | 22 | void URuntimeMeshProviderCollision::SetCollisionMesh(const FRuntimeMeshCollisionData& NewCollisionMesh) 23 | { 24 | { 25 | FScopeLock Lock(&SyncRoot); 26 | CollisionMesh = NewCollisionMesh; 27 | } 28 | MarkCollisionDirty(); 29 | } 30 | 31 | void URuntimeMeshProviderCollision::SetRenderableLODForCollision(int32 LODIndex) 32 | { 33 | bool bMarkCollisionDirty = false; 34 | { 35 | FScopeLock Lock(&SyncRoot); 36 | if (LODForMeshCollision != LODIndex) 37 | { 38 | LODForMeshCollision = LODIndex; 39 | RenderableCollisionData.Empty(); 40 | 41 | bMarkCollisionDirty = true; 42 | } 43 | } 44 | 45 | if (bMarkCollisionDirty) 46 | { 47 | MarkCollisionDirty(); 48 | } 49 | } 50 | 51 | void URuntimeMeshProviderCollision::SetRenderableSectionAffectsCollision(int32 SectionId, bool bCollisionEnabled) 52 | { 53 | bool bShouldMarkCollisionDirty = false; 54 | { 55 | FScopeLock Lock(&SyncRoot); 56 | if (bCollisionEnabled && !SectionsAffectingCollision.Contains(SectionId)) 57 | { 58 | SectionsAffectingCollision.Add(SectionId); 59 | bShouldMarkCollisionDirty = true; 60 | } 61 | else if (!bCollisionEnabled && SectionsAffectingCollision.Contains(SectionId)) 62 | { 63 | SectionsAffectingCollision.Remove(SectionId); 64 | RenderableCollisionData.Remove(SectionId); 65 | bShouldMarkCollisionDirty = true; 66 | } 67 | } 68 | 69 | if (bShouldMarkCollisionDirty) 70 | { 71 | MarkCollisionDirty(); 72 | } 73 | } 74 | 75 | 76 | 77 | 78 | bool URuntimeMeshProviderCollision::GetSectionMeshForLOD(int32 LODIndex, int32 SectionId, FRuntimeMeshRenderableMeshData& MeshData) 79 | { 80 | bool bResult = Super::GetSectionMeshForLOD(LODIndex, SectionId, MeshData); 81 | 82 | FScopeLock Lock(&SyncRoot); 83 | if (bResult && LODIndex == LODForMeshCollision && SectionsAffectingCollision.Contains(SectionId)) 84 | { 85 | FRuntimeMeshRenderableCollisionData& SectionCacheData = RenderableCollisionData.FindOrAdd(SectionId); 86 | SectionCacheData = FRuntimeMeshRenderableCollisionData(MeshData); 87 | MarkCollisionDirty(); 88 | } 89 | 90 | return bResult; 91 | } 92 | 93 | bool URuntimeMeshProviderCollision::GetAllSectionsMeshForLOD(int32 LODIndex, TMap& MeshDatas) 94 | { 95 | bool bResult = Super::GetAllSectionsMeshForLOD(LODIndex, MeshDatas); 96 | 97 | FScopeLock Lock(&SyncRoot); 98 | if (bResult && LODIndex == LODForMeshCollision) 99 | { 100 | RenderableCollisionData.Empty(); 101 | for (const auto& Entry : MeshDatas) 102 | { 103 | if (SectionsAffectingCollision.Contains(Entry.Key)) 104 | { 105 | FRuntimeMeshRenderableCollisionData& SectionCacheData = RenderableCollisionData.FindOrAdd(Entry.Key); 106 | SectionCacheData = FRuntimeMeshRenderableCollisionData(Entry.Value.MeshData); 107 | } 108 | } 109 | 110 | MarkCollisionDirty(); 111 | } 112 | 113 | return bResult; 114 | } 115 | 116 | FRuntimeMeshCollisionSettings URuntimeMeshProviderCollision::GetCollisionSettings() 117 | { 118 | FScopeLock Lock(&SyncRoot); 119 | return CollisionSettings; 120 | } 121 | 122 | bool URuntimeMeshProviderCollision::HasCollisionMesh() 123 | { 124 | FScopeLock Lock(&SyncRoot); 125 | return (CollisionMesh.Vertices.Num() > 0 && CollisionMesh.Triangles.Num() > 0) || 126 | RenderableCollisionData.Num() > 0; 127 | } 128 | 129 | bool URuntimeMeshProviderCollision::GetCollisionMesh(FRuntimeMeshCollisionData& CollisionData) 130 | { 131 | FScopeLock Lock(&SyncRoot); 132 | 133 | //If the given collision mesh is valid, use it 134 | if (CollisionMesh.Vertices.Num() > 0 && CollisionMesh.Triangles.Num() > 0) 135 | { 136 | CollisionData = CollisionMesh; 137 | return true; 138 | } 139 | 140 | 141 | for (const auto& CachedSectionEntry : RenderableCollisionData) 142 | { 143 | int32 SectionId = CachedSectionEntry.Key; 144 | const FRuntimeMeshRenderableCollisionData& CachedSection = CachedSectionEntry.Value; 145 | 146 | int32 FirstVertex = CollisionData.Vertices.Num(); 147 | 148 | 149 | // Copy the vertices 150 | int32 NumVertices = CachedSection.Vertices.Num(); 151 | CollisionData.Vertices.SetNum(FirstVertex + NumVertices); 152 | for (int32 Index = 0; Index < NumVertices; Index++) 153 | { 154 | CollisionData.Vertices.SetPosition(FirstVertex + Index, CachedSection.Vertices.GetPosition(Index)); 155 | } 156 | 157 | // Copy tex coords 158 | int32 MaxTexCoordChannels = FMath::Max(CollisionData.TexCoords.NumChannels(), CachedSection.TexCoords.NumChannels()); 159 | CollisionData.TexCoords.SetNum(MaxTexCoordChannels, FirstVertex + NumVertices); 160 | for (int32 Index = 0; Index < NumVertices; Index++) 161 | { 162 | for (int32 ChannelId = 0; ChannelId < MaxTexCoordChannels; ChannelId++) 163 | { 164 | if (ChannelId < CachedSection.TexCoords.NumChannels() && CachedSection.TexCoords.NumTexCoords(ChannelId) > Index) 165 | { 166 | FVector2D TexCoord = CachedSection.TexCoords.GetTexCoord(ChannelId, Index); 167 | CollisionData.TexCoords.SetTexCoord(ChannelId, Index, TexCoord); 168 | } 169 | else 170 | { 171 | CollisionData.TexCoords.SetTexCoord(ChannelId, Index, FVector2D::ZeroVector); 172 | } 173 | } 174 | } 175 | 176 | 177 | // Copy triangles and fill in material indices 178 | int32 StartTriangle = CollisionData.Triangles.Num(); 179 | int32 NumTriangles = CachedSection.Triangles.Num(); 180 | CollisionData.Triangles.SetNum(StartTriangle + NumTriangles); 181 | CollisionData.MaterialIndices.SetNum(StartTriangle + NumTriangles); 182 | for (int32 Index = 0; Index < NumTriangles; Index++) 183 | { 184 | int32 IdA, IdB, IdC; 185 | CachedSection.Triangles.GetTriangleIndices(Index, IdA, IdB, IdC); 186 | 187 | CollisionData.Triangles.SetTriangleIndices(StartTriangle + Index, IdA + FirstVertex, IdB + FirstVertex, IdC + FirstVertex); 188 | CollisionData.MaterialIndices.SetMaterialIndex(StartTriangle + Index, SectionId); 189 | } 190 | 191 | 192 | CollisionData.CollisionSources.Emplace(StartTriangle, StartTriangle + NumTriangles - 1, this, SectionId, ERuntimeMeshCollisionFaceSourceType::Renderable); 193 | } 194 | return true; 195 | } 196 | 197 | bool URuntimeMeshProviderCollision::IsThreadSafe() 198 | { 199 | return Super::IsThreadSafe(); 200 | } 201 | 202 | 203 | 204 | 205 | void URuntimeMeshProviderCollision::ConfigureLODs(const TArray& InLODs) 206 | { 207 | ClearCachedData(); 208 | 209 | Super::ConfigureLODs(InLODs); 210 | } 211 | 212 | void URuntimeMeshProviderCollision::CreateSection(int32 LODIndex, int32 SectionId, const FRuntimeMeshSectionProperties& SectionProperties) 213 | { 214 | ClearSectionData(LODIndex, SectionId); 215 | 216 | Super::CreateSection(LODIndex, SectionId, SectionProperties); 217 | } 218 | 219 | void URuntimeMeshProviderCollision::ClearSection(int32 LODIndex, int32 SectionId) 220 | { 221 | ClearSectionData(LODIndex, SectionId); 222 | 223 | Super::ClearSection(LODIndex, SectionId); 224 | } 225 | 226 | void URuntimeMeshProviderCollision::RemoveSection(int32 LODIndex, int32 SectionId) 227 | { 228 | ClearSectionData(LODIndex, SectionId); 229 | 230 | URuntimeMeshProvider::RemoveSection(LODIndex, SectionId); 231 | } 232 | 233 | void URuntimeMeshProviderCollision::ClearCachedData() 234 | { 235 | FScopeLock Lock(&SyncRoot); 236 | RenderableCollisionData.Empty(); 237 | } 238 | 239 | void URuntimeMeshProviderCollision::ClearSectionData(int32 LODIndex, int32 SectionId) 240 | { 241 | FScopeLock Lock(&SyncRoot); 242 | if (LODIndex == LODForMeshCollision) 243 | { 244 | RenderableCollisionData.Remove(SectionId); 245 | } 246 | } 247 | 248 | -------------------------------------------------------------------------------- /Plugins/RuntimeMeshComponent/Source/RuntimeMeshComponent/Private/Providers/RuntimeMeshProviderMemoryCache.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2020 TriAxis Games L.L.C. All Rights Reserved. 2 | 3 | 4 | #include "Providers/RuntimeMeshProviderMemoryCache.h" 5 | 6 | 7 | void URuntimeMeshProviderMemoryCache::ClearCache() 8 | { 9 | { 10 | FScopeLock Lock(&MeshSyncRoot); 11 | CachedMeshData.Empty(); 12 | } 13 | { 14 | FScopeLock Lock(&CollisionSyncRoot); 15 | CachedCollisionSettings.Reset(); 16 | CachedHasCollisionMesh.Reset(); 17 | CachedCollisionData.Reset(); 18 | } 19 | } 20 | 21 | 22 | 23 | bool URuntimeMeshProviderMemoryCache::GetSectionMeshForLOD(int32 LODIndex, int32 SectionId, FRuntimeMeshRenderableMeshData& MeshData) 24 | { 25 | FScopeLock Lock(&MeshSyncRoot); 26 | 27 | const auto* FoundLOD = CachedMeshData.Find(LODIndex); 28 | if (FoundLOD) 29 | { 30 | const auto* FoundSection = FoundLOD->Find(SectionId); 31 | if (FoundSection) 32 | { 33 | if (FoundSection->IsSet()) 34 | { 35 | MeshData = FoundSection->GetValue(); 36 | } 37 | 38 | return FoundSection->IsSet(); 39 | } 40 | } 41 | 42 | if (GetChildProvider()) 43 | { 44 | bool bHasData = GetChildProvider()->GetSectionMeshForLOD(LODIndex, SectionId, MeshData); 45 | TOptional& NewCache = CachedMeshData.FindOrAdd(LODIndex).FindOrAdd(SectionId); 46 | if (bHasData) 47 | { 48 | NewCache = MeshData; 49 | } 50 | return bHasData; 51 | } 52 | 53 | return false; 54 | } 55 | 56 | bool URuntimeMeshProviderMemoryCache::GetAllSectionsMeshForLOD(int32 LODIndex, TMap& MeshDatas) 57 | { 58 | FScopeLock Lock(&MeshSyncRoot); 59 | 60 | const auto* FoundLOD = CachedMeshData.Find(LODIndex); 61 | if (FoundLOD) 62 | { 63 | MeshDatas.Empty(); 64 | 65 | // Add all cached sections 66 | for (const auto& CachedSection : *FoundLOD) 67 | { 68 | FRuntimeMeshSectionData& SectionData = MeshDatas.FindOrAdd(CachedSection.Key); 69 | 70 | // Copy the section properties 71 | SectionData.Properties = CacheSectionConfig.FindOrAdd(LODIndex).FindChecked(CachedSection.Key); 72 | 73 | if (CachedSection.Value.IsSet()) 74 | { 75 | SectionData.MeshData = CachedSection.Value.GetValue(); 76 | } 77 | } 78 | 79 | return FoundLOD->Num() > 0; 80 | } 81 | 82 | if (GetChildProvider()) 83 | { 84 | bool bHasData = GetChildProvider()->GetAllSectionsMeshForLOD(LODIndex, MeshDatas); 85 | 86 | TMap>& NewCache = CachedMeshData.FindOrAdd(LODIndex); 87 | TMap& PropertiesCache = CacheSectionConfig.FindOrAdd(LODIndex); 88 | 89 | NewCache.Empty(); 90 | PropertiesCache.Empty(); 91 | 92 | if (bHasData) 93 | { 94 | for (const auto& NewSection : MeshDatas) 95 | { 96 | PropertiesCache.FindOrAdd(NewSection.Key) = NewSection.Value.Properties; 97 | NewCache.FindOrAdd(NewSection.Key) = NewSection.Value.MeshData; 98 | } 99 | } 100 | 101 | return bHasData; 102 | } 103 | 104 | return false; 105 | } 106 | 107 | FRuntimeMeshCollisionSettings URuntimeMeshProviderMemoryCache::GetCollisionSettings() 108 | { 109 | FScopeLock Lock(&CollisionSyncRoot); 110 | 111 | if (CachedCollisionSettings.IsSet()) 112 | { 113 | return CachedCollisionSettings.Get(FRuntimeMeshCollisionSettings()); 114 | } 115 | 116 | if (GetChildProvider()) 117 | { 118 | FRuntimeMeshCollisionSettings NewSettings = GetChildProvider()->GetCollisionSettings(); 119 | CachedCollisionSettings = NewSettings; 120 | return NewSettings; 121 | } 122 | return FRuntimeMeshCollisionSettings(); 123 | } 124 | 125 | bool URuntimeMeshProviderMemoryCache::HasCollisionMesh() 126 | { 127 | FScopeLock Lock(&CollisionSyncRoot); 128 | 129 | if (CachedHasCollisionMesh.IsSet()) 130 | { 131 | return CachedHasCollisionMesh.Get(false); 132 | } 133 | 134 | if (GetChildProvider()) 135 | { 136 | bool bHasData = GetChildProvider()->HasCollisionMesh(); 137 | CachedHasCollisionMesh = bHasData; 138 | return bHasData; 139 | } 140 | return false; 141 | } 142 | 143 | bool URuntimeMeshProviderMemoryCache::GetCollisionMesh(FRuntimeMeshCollisionData& CollisionData) 144 | { 145 | FScopeLock Lock(&CollisionSyncRoot); 146 | 147 | if (CachedCollisionData.IsSet()) 148 | { 149 | CollisionData = CachedCollisionData->Value; 150 | return CachedCollisionData->Key; 151 | } 152 | 153 | if (GetChildProvider()) 154 | { 155 | bool bHasData = GetChildProvider()->GetCollisionMesh(CollisionData); 156 | CachedCollisionData = TPair(bHasData, CollisionData); 157 | return bHasData; 158 | } 159 | return false; 160 | } 161 | 162 | bool URuntimeMeshProviderMemoryCache::IsThreadSafe() 163 | { 164 | // We ourselves are threadsafe, so our thread safety depends on the child provider 165 | return GetChildProvider()->IsThreadSafe(); 166 | } 167 | 168 | 169 | 170 | 171 | void URuntimeMeshProviderMemoryCache::ConfigureLODs(const TArray& InLODs) 172 | { 173 | { 174 | FScopeLock Lock(&MeshSyncRoot); 175 | CacheSectionConfig.Empty(); 176 | } 177 | ClearCacheLOD(INDEX_NONE); 178 | URuntimeMeshProviderPassthrough::ConfigureLODs(InLODs); 179 | } 180 | 181 | void URuntimeMeshProviderMemoryCache::MarkLODDirty(int32 LODIndex) 182 | { 183 | ClearCacheLOD(LODIndex); 184 | URuntimeMeshProviderPassthrough::MarkLODDirty(LODIndex); 185 | } 186 | 187 | void URuntimeMeshProviderMemoryCache::MarkAllLODsDirty() 188 | { 189 | ClearCacheLOD(INDEX_NONE); 190 | URuntimeMeshProviderPassthrough::MarkAllLODsDirty(); 191 | } 192 | 193 | void URuntimeMeshProviderMemoryCache::CreateSection(int32 LODIndex, int32 SectionId, const FRuntimeMeshSectionProperties& SectionProperties) 194 | { 195 | { 196 | FScopeLock Lock(&MeshSyncRoot); 197 | CacheSectionConfig.FindOrAdd(LODIndex).FindOrAdd(SectionId) = SectionProperties; 198 | } 199 | ClearCacheSection(LODIndex, SectionId); 200 | URuntimeMeshProviderPassthrough::CreateSection(LODIndex, SectionId, SectionProperties); 201 | } 202 | 203 | void URuntimeMeshProviderMemoryCache::MarkSectionDirty(int32 LODIndex, int32 SectionId) 204 | { 205 | ClearCacheSection(LODIndex, SectionId); 206 | URuntimeMeshProviderPassthrough::MarkSectionDirty(LODIndex, SectionId); 207 | } 208 | 209 | void URuntimeMeshProviderMemoryCache::ClearSection(int32 LODIndex, int32 SectionId) 210 | { 211 | ClearCacheSection(LODIndex, SectionId); 212 | URuntimeMeshProviderPassthrough::ClearSection(LODIndex, SectionId); 213 | } 214 | 215 | void URuntimeMeshProviderMemoryCache::RemoveSection(int32 LODIndex, int32 SectionId) 216 | { 217 | { 218 | FScopeLock Lock(&MeshSyncRoot); 219 | CacheSectionConfig.FindOrAdd(LODIndex).Remove(SectionId); 220 | } 221 | ClearCacheSection(LODIndex, SectionId); 222 | URuntimeMeshProviderPassthrough::RemoveSection(LODIndex, SectionId); 223 | } 224 | 225 | void URuntimeMeshProviderMemoryCache::MarkCollisionDirty() 226 | { 227 | FScopeLock Lock(&CollisionSyncRoot); 228 | 229 | CachedCollisionSettings.Reset(); 230 | CachedHasCollisionMesh.Reset(); 231 | CachedCollisionData.Reset(); 232 | URuntimeMeshProviderPassthrough::MarkCollisionDirty(); 233 | } 234 | 235 | 236 | 237 | 238 | void URuntimeMeshProviderMemoryCache::BeginDestroy() 239 | { 240 | ClearCache(); 241 | Super::BeginDestroy(); 242 | } 243 | 244 | 245 | 246 | 247 | void URuntimeMeshProviderMemoryCache::ClearCacheLOD(int32 LODIndex) 248 | { 249 | FScopeLock Lock(&MeshSyncRoot); 250 | if (LODIndex == INDEX_NONE) 251 | { 252 | CachedMeshData.Empty(); 253 | } 254 | else 255 | { 256 | CachedMeshData.Remove(LODIndex); 257 | } 258 | } 259 | 260 | void URuntimeMeshProviderMemoryCache::ClearCacheSection(int32 LODIndex, int32 SectionId) 261 | { 262 | FScopeLock Lock(&MeshSyncRoot); 263 | TMap>* FoundLOD = CachedMeshData.Find(LODIndex); 264 | 265 | if (FoundLOD) 266 | { 267 | FoundLOD->Remove(SectionId); 268 | } 269 | } -------------------------------------------------------------------------------- /Plugins/RuntimeMeshComponent/Source/RuntimeMeshComponent/Private/Providers/RuntimeMeshProviderModifiers.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2020 TriAxis Games L.L.C. All Rights Reserved. 2 | 3 | 4 | #include "Providers/RuntimeMeshProviderModifiers.h" 5 | 6 | 7 | 8 | void URuntimeMeshProviderModifiers::AddModifier(URuntimeMeshModifier* NewModifier) 9 | { 10 | Modifiers.Add(NewModifier); 11 | } 12 | 13 | void URuntimeMeshProviderModifiers::RemoveModifier(URuntimeMeshModifier* ModifierToRemove) 14 | { 15 | Modifiers.Remove(ModifierToRemove); 16 | } 17 | 18 | bool URuntimeMeshProviderModifiers::GetSectionMeshForLOD(int32 LODIndex, int32 SectionId, FRuntimeMeshRenderableMeshData& MeshData) 19 | { 20 | URuntimeMeshProvider* ChildProviderTemp = GetChildProvider(); 21 | if (ChildProviderTemp) 22 | { 23 | if (ChildProviderTemp->GetSectionMeshForLOD(LODIndex, SectionId, MeshData)) 24 | { 25 | ApplyModifiers(MeshData); 26 | return true; 27 | } 28 | } 29 | return false; 30 | } 31 | 32 | bool URuntimeMeshProviderModifiers::GetAllSectionsMeshForLOD(int32 LODIndex, TMap& MeshDatas) 33 | { 34 | URuntimeMeshProvider* ChildProviderTemp = GetChildProvider(); 35 | if (ChildProviderTemp) 36 | { 37 | if (ChildProviderTemp->GetAllSectionsMeshForLOD(LODIndex, MeshDatas)) 38 | { 39 | for (auto& Entry : MeshDatas) 40 | { 41 | ApplyModifiers(Entry.Value.MeshData); 42 | return true; 43 | } 44 | } 45 | } 46 | return false; 47 | } 48 | 49 | bool URuntimeMeshProviderModifiers::GetCollisionMesh(FRuntimeMeshCollisionData& CollisionData) 50 | { 51 | URuntimeMeshProvider* ChildProviderTemp = GetChildProvider(); 52 | if (ChildProviderTemp) 53 | { 54 | if (ChildProviderTemp->GetCollisionMesh(CollisionData)) 55 | { 56 | ApplyModifiers(CollisionData); 57 | return true; 58 | } 59 | } 60 | return false; 61 | } 62 | 63 | void URuntimeMeshProviderModifiers::ApplyModifiers(FRuntimeMeshRenderableMeshData& MeshData) 64 | { 65 | if (MeshData.HasValidMeshData()) 66 | { 67 | for (int32 Index = 0; Index < Modifiers.Num(); Index++) 68 | { 69 | Modifiers[Index]->ApplyToMesh(MeshData); 70 | } 71 | } 72 | } 73 | 74 | void URuntimeMeshProviderModifiers::ApplyModifiers(FRuntimeMeshCollisionData& CollisionData) 75 | { 76 | if (CollisionData.HasValidMeshData()) 77 | { 78 | for (int32 Index = 0; Index < Modifiers.Num(); Index++) 79 | { 80 | Modifiers[Index]->ApplyToCollisionMesh(CollisionData); 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /Plugins/RuntimeMeshComponent/Source/RuntimeMeshComponent/Private/Providers/RuntimeMeshProviderPlane.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2020 TriAxis Games L.L.C. All Rights Reserved. 2 | 3 | 4 | #include "Providers/RuntimeMeshProviderPlane.h" 5 | 6 | 7 | URuntimeMeshProviderPlane::URuntimeMeshProviderPlane() 8 | : LocationA(100, 100, 0) 9 | , LocationB(-100, 100, 0) 10 | , LocationC(100, -100, 0) 11 | , VertsAB({100,10,2}) 12 | , VertsAC({100,10,2}) 13 | , ScreenSize({ 0.1,0.01 }) 14 | { 15 | } 16 | 17 | void URuntimeMeshProviderPlane::Initialize() 18 | { 19 | MaxLOD = GetMaximumPossibleLOD(); 20 | 21 | SetupMaterialSlot(0, FName("Plane Base"), Material); 22 | 23 | 24 | TArray NewLODs; 25 | for (int32 LODIndex = 0; LODIndex <= MaxLOD; LODIndex++) 26 | { 27 | FRuntimeMeshLODProperties LODProperties; 28 | LODProperties.ScreenSize = LODIndex >= ScreenSize.Num() ? 0.0 : ScreenSize[LODIndex]; 29 | NewLODs.Add(LODProperties); 30 | } 31 | ConfigureLODs(NewLODs); 32 | 33 | 34 | for (int32 LODIndex = 0; LODIndex <= MaxLOD; LODIndex++) 35 | { 36 | FRuntimeMeshSectionProperties Properties; 37 | Properties.bCastsShadow = true; 38 | Properties.bIsVisible = true; 39 | Properties.MaterialSlot = 0; 40 | Properties.UpdateFrequency = ERuntimeMeshUpdateFrequency::Infrequent; 41 | Properties.bWants32BitIndices = VertsAB[LODIndex] * VertsAC[LODIndex] > 1 << 16; //Use 32 bit indices if more than 2^16 verts are needed 42 | 43 | CreateSection(LODIndex, 0, Properties); 44 | } 45 | } 46 | 47 | bool URuntimeMeshProviderPlane::GetSectionMeshForLOD(int32 LODIndex, int32 SectionId, FRuntimeMeshRenderableMeshData& MeshData) 48 | { 49 | FScopeLock Lock(&PropertySyncRoot); 50 | 51 | // We should only ever be queried for section 0 52 | check(SectionId == 0 && LODIndex <= MaxLOD); 53 | 54 | int32 NumVertsAB = VertsAB[LODIndex]; 55 | int32 NumVertsAC = VertsAC[LODIndex]; 56 | FVector ABDirection = (LocationB - LocationA) / (NumVertsAB - 1); 57 | FVector ACDirection = (LocationC - LocationA) / (NumVertsAB - 1); 58 | FVector Normal = (ABDirection ^ ACDirection).GetUnsafeNormal(); 59 | FVector Tangent = ABDirection.GetUnsafeNormal(); 60 | FColor Color = FColor::White; 61 | for (int32 ACIndex = 0; ACIndex < NumVertsAC; ACIndex++) 62 | { 63 | for (int32 ABIndex = 0; ABIndex < NumVertsAB; ABIndex++) 64 | { 65 | FVector Location = LocationA + ABDirection * ABIndex + ACDirection * ACIndex; 66 | FVector2D TexCoord = FVector2D((float)ABIndex / (float)(NumVertsAB - 1), (float)ACIndex / (float)(NumVertsAC - 1)); 67 | //UE_LOG(LogTemp, Log, TEXT("TexCoord for vertex %i:%i : %s"), ABIndex, ACIndex, *TexCoord.ToString()); 68 | MeshData.Positions.Add(Location); 69 | MeshData.Tangents.Add(Normal, Tangent); 70 | MeshData.Colors.Add(Color); 71 | MeshData.TexCoords.Add(TexCoord); 72 | if (ABIndex != NumVertsAB - 1 && ACIndex != NumVertsAC - 1) 73 | { 74 | int32 AIndex = ABIndex + ACIndex * NumVertsAB; 75 | int32 BIndex = AIndex + 1; 76 | int32 CIndex = AIndex + NumVertsAB; 77 | int32 DIndex = CIndex + 1; 78 | MeshData.Triangles.AddTriangle(AIndex, CIndex, BIndex); 79 | MeshData.Triangles.AddTriangle(BIndex, CIndex, DIndex); 80 | } 81 | } 82 | } 83 | 84 | return true; 85 | } 86 | 87 | FRuntimeMeshCollisionSettings URuntimeMeshProviderPlane::GetCollisionSettings() 88 | { 89 | FRuntimeMeshCollisionSettings Settings; 90 | Settings.bUseAsyncCooking = false; 91 | Settings.bUseComplexAsSimple = true; 92 | 93 | return Settings; 94 | } 95 | 96 | FBoxSphereBounds URuntimeMeshProviderPlane::GetBounds() 97 | { 98 | FScopeLock Lock(&PropertySyncRoot); 99 | FVector LocationD = LocationB - LocationA + LocationC; // C + BA 100 | FVector points[4] = { LocationA, LocationB, LocationC, LocationD }; 101 | FBox BoundingBox = FBox(points, 4); 102 | return FBoxSphereBounds(BoundingBox); 103 | } 104 | 105 | bool URuntimeMeshProviderPlane::IsThreadSafe() 106 | { 107 | return true; 108 | } 109 | 110 | int32 URuntimeMeshProviderPlane::GetMaximumPossibleLOD() 111 | { 112 | return FMath::Min3(VertsAB.Num() - 1, VertsAC.Num() - 1, ScreenSize.Num()); 113 | } 114 | -------------------------------------------------------------------------------- /Plugins/RuntimeMeshComponent/Source/RuntimeMeshComponent/Private/Providers/RuntimeMeshProviderStaticMesh.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2020 TriAxis Games L.L.C. All Rights Reserved. 2 | 3 | 4 | #include "Providers/RuntimeMeshProviderStaticMesh.h" 5 | #include "RuntimeMeshStaticMeshConverter.h" 6 | #include "Engine/StaticMesh.h" 7 | 8 | URuntimeMeshProviderStaticMesh::URuntimeMeshProviderStaticMesh() 9 | : StaticMesh(nullptr) 10 | , MaxLOD(RUNTIMEMESH_MAXLODS) 11 | , ComplexCollisionLOD(0) 12 | { 13 | 14 | } 15 | 16 | UStaticMesh* URuntimeMeshProviderStaticMesh::GetStaticMesh() const 17 | { 18 | return StaticMesh; 19 | } 20 | 21 | void URuntimeMeshProviderStaticMesh::SetStaticMesh(UStaticMesh* InStaticMesh) 22 | { 23 | StaticMesh = InStaticMesh; 24 | UpdateRenderingFromStaticMesh(); 25 | UpdateCollisionFromStaticMesh(); 26 | } 27 | 28 | int32 URuntimeMeshProviderStaticMesh::GetMaxLOD() const 29 | { 30 | return MaxLOD; 31 | } 32 | 33 | void URuntimeMeshProviderStaticMesh::SetMaxLOD(int32 InMaxLOD) 34 | { 35 | MaxLOD = InMaxLOD; 36 | UpdateRenderingFromStaticMesh(); 37 | } 38 | 39 | int32 URuntimeMeshProviderStaticMesh::GetComplexCollisionLOD() const 40 | { 41 | return ComplexCollisionLOD; 42 | } 43 | 44 | void URuntimeMeshProviderStaticMesh::SetComplexCollisionLOD(int32 InLOD) 45 | { 46 | ComplexCollisionLOD = InLOD; 47 | UpdateCollisionFromStaticMesh(); 48 | } 49 | 50 | void URuntimeMeshProviderStaticMesh::Initialize() 51 | { 52 | UpdateRenderingFromStaticMesh(); 53 | UpdateCollisionFromStaticMesh(); 54 | } 55 | 56 | FBoxSphereBounds URuntimeMeshProviderStaticMesh::GetBounds() 57 | { 58 | if (StaticMesh) 59 | { 60 | return StaticMesh->GetBounds(); 61 | } 62 | return FBoxSphereBounds(ForceInit); 63 | } 64 | 65 | bool URuntimeMeshProviderStaticMesh::GetSectionMeshForLOD(int32 LODIndex, int32 SectionId, FRuntimeMeshRenderableMeshData& MeshData) 66 | { 67 | return URuntimeMeshStaticMeshConverter::CopyStaticMeshSectionToRenderableMeshData(StaticMesh, LODIndex, SectionId, MeshData); 68 | } 69 | 70 | FRuntimeMeshCollisionSettings URuntimeMeshProviderStaticMesh::GetCollisionSettings() 71 | { 72 | FRuntimeMeshCollisionSettings NewSettings; 73 | NewSettings.bUseAsyncCooking = true; 74 | NewSettings.bUseComplexAsSimple = false; 75 | NewSettings.CookingMode = ERuntimeMeshCollisionCookingMode::CookingPerformance; 76 | 77 | URuntimeMeshStaticMeshConverter::CopyStaticMeshCollisionToCollisionSettings(StaticMesh, NewSettings); 78 | 79 | return NewSettings; 80 | } 81 | 82 | bool URuntimeMeshProviderStaticMesh::HasCollisionMesh() 83 | { 84 | return ComplexCollisionLOD >= 0; 85 | } 86 | 87 | bool URuntimeMeshProviderStaticMesh::GetCollisionMesh(FRuntimeMeshCollisionData& CollisionData) 88 | { 89 | bool bResult = URuntimeMeshStaticMeshConverter::CopyStaticMeshLODToCollisionData(StaticMesh, ComplexCollisionLOD, CollisionData); 90 | 91 | if (bResult) 92 | { 93 | for (auto& Section : CollisionData.CollisionSources) 94 | { 95 | Section.SourceProvider = this; 96 | } 97 | } 98 | return bResult; 99 | } 100 | 101 | 102 | void URuntimeMeshProviderStaticMesh::UpdateCollisionFromStaticMesh() 103 | { 104 | MarkCollisionDirty(); 105 | } 106 | 107 | void URuntimeMeshProviderStaticMesh::UpdateRenderingFromStaticMesh() 108 | { 109 | // Setup the LODs and sections 110 | 111 | // Check valid static mesh 112 | if (StaticMesh == nullptr || StaticMesh->IsPendingKill()) 113 | { 114 | ConfigureLODs({ FRuntimeMeshLODProperties() }); 115 | MarkCollisionDirty(); 116 | return; 117 | } 118 | 119 | // Check mesh data is accessible 120 | if (!((GIsEditor || StaticMesh->bAllowCPUAccess) && StaticMesh->RenderData != nullptr)) 121 | { 122 | ConfigureLODs({ FRuntimeMeshLODProperties() }); 123 | MarkCollisionDirty(); 124 | return; 125 | } 126 | 127 | // Copy materials 128 | const auto& MaterialSlots = StaticMesh->StaticMaterials; 129 | for (int32 SlotIndex = 0; SlotIndex < MaterialSlots.Num(); SlotIndex++) 130 | { 131 | SetupMaterialSlot(SlotIndex, MaterialSlots[SlotIndex].MaterialSlotName, MaterialSlots[SlotIndex].MaterialInterface); 132 | } 133 | 134 | const auto& LODResources = StaticMesh->RenderData->LODResources; 135 | 136 | // Setup LODs 137 | TArray LODs; 138 | for (int32 LODIndex = 0; LODIndex < LODResources.Num() && LODIndex <= MaxLOD; LODIndex++) 139 | { 140 | FRuntimeMeshLODProperties LODProperties; 141 | LODProperties.ScreenSize = StaticMesh->RenderData->ScreenSize[LODIndex].Default; 142 | 143 | LODs.Add(LODProperties); 144 | } 145 | ConfigureLODs(LODs); 146 | 147 | 148 | // Create all sections for all LODs 149 | for (int32 LODIndex = 0; LODIndex < LODResources.Num() && LODIndex <= MaxLOD; LODIndex++) 150 | { 151 | const auto& LOD = LODResources[LODIndex]; 152 | 153 | for (int32 SectionId = 0; SectionId < LOD.Sections.Num(); SectionId++) 154 | { 155 | const auto& Section = LOD.Sections[SectionId]; 156 | 157 | FRuntimeMeshSectionProperties SectionProperties; 158 | 159 | CreateSection(LODIndex, SectionId, SectionProperties); 160 | } 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /Plugins/RuntimeMeshComponent/Source/RuntimeMeshComponent/Private/RuntimeMeshActor.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2020 TriAxis Games L.L.C. All Rights Reserved. 2 | 3 | #include "RuntimeMeshActor.h" 4 | #include "RuntimeMeshComponent.h" 5 | #include "RuntimeMeshComponentPlugin.h" 6 | #include "Engine/CollisionProfile.h" 7 | 8 | 9 | 10 | ARuntimeMeshActor::ARuntimeMeshActor(const FObjectInitializer& ObjectInitializer) 11 | : Super(ObjectInitializer) 12 | { 13 | #if ENGINE_MAJOR_VERSION >= 4 && ENGINE_MINOR_VERSION >= 24 14 | SetCanBeDamaged(false); 15 | #else 16 | bCanBeDamaged = false; 17 | #endif 18 | 19 | RuntimeMeshComponent = CreateDefaultSubobject(TEXT("RuntimeMeshComponent0")); 20 | RuntimeMeshComponent->SetCollisionProfileName(UCollisionProfile::BlockAll_ProfileName); 21 | RuntimeMeshComponent->Mobility = EComponentMobility::Static; 22 | 23 | RuntimeMeshComponent->SetGenerateOverlapEvents(false); 24 | RootComponent = RuntimeMeshComponent; 25 | } 26 | 27 | ERuntimeMeshMobility ARuntimeMeshActor::GetRuntimeMeshMobility() 28 | { 29 | if (RuntimeMeshComponent) 30 | { 31 | return RuntimeMeshComponent->GetRuntimeMeshMobility(); 32 | } 33 | return ERuntimeMeshMobility::Static; 34 | } 35 | 36 | void ARuntimeMeshActor::SetRuntimeMeshMobility(ERuntimeMeshMobility NewMobility) 37 | { 38 | if (RuntimeMeshComponent) 39 | { 40 | RuntimeMeshComponent->SetRuntimeMeshMobility(NewMobility); 41 | } 42 | } 43 | 44 | void ARuntimeMeshActor::SetMobility(EComponentMobility::Type InMobility) 45 | { 46 | if (RuntimeMeshComponent) 47 | { 48 | RuntimeMeshComponent->SetMobility(InMobility); 49 | } 50 | } 51 | 52 | EComponentMobility::Type ARuntimeMeshActor::GetMobility() 53 | { 54 | if (RuntimeMeshComponent) 55 | { 56 | return RuntimeMeshComponent->Mobility; 57 | } 58 | return EComponentMobility::Static; 59 | } 60 | 61 | -------------------------------------------------------------------------------- /Plugins/RuntimeMeshComponent/Source/RuntimeMeshComponent/Private/RuntimeMeshComponent.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2020 TriAxis Games L.L.C. All Rights Reserved. 2 | 3 | #include "RuntimeMeshComponent.h" 4 | #include "RuntimeMeshComponentPlugin.h" 5 | #include "PhysicsEngine/BodySetup.h" 6 | #include "PhysicsEngine/PhysicsSettings.h" 7 | #include "IPhysXCookingModule.h" 8 | #include "RuntimeMeshCore.h" 9 | #include "RuntimeMeshRenderable.h" 10 | #include "RuntimeMeshSectionProxy.h" 11 | #include "RuntimeMesh.h" 12 | #include "RuntimeMeshComponentProxy.h" 13 | #include "NavigationSystem.h" 14 | 15 | 16 | 17 | DECLARE_CYCLE_STAT(TEXT("RuntimeMeshComponent - Collision Data Received"), STAT_RuntimeMeshComponent_NewCollisionMeshReceived, STATGROUP_RuntimeMesh); 18 | DECLARE_CYCLE_STAT(TEXT("RuntimeMeshComponent - Create Scene Proxy"), STAT_RuntimeMeshComponent_CreateSceneProxy, STATGROUP_RuntimeMesh); 19 | 20 | 21 | URuntimeMeshComponent::URuntimeMeshComponent() 22 | { 23 | SetNetAddressable(); 24 | 25 | Super::SetTickGroup(TG_DuringPhysics); 26 | Super::SetTickableWhenPaused(true); 27 | } 28 | 29 | void URuntimeMeshComponent::EnsureHasRuntimeMesh() 30 | { 31 | if (RuntimeMeshReference == nullptr) 32 | { 33 | SetRuntimeMesh(NewObject(this)); 34 | } 35 | } 36 | 37 | void URuntimeMeshComponent::SetRuntimeMesh(URuntimeMesh* NewMesh) 38 | { 39 | // Unlink from any existing runtime mesh 40 | if (RuntimeMeshReference) 41 | { 42 | RuntimeMeshReference->UnRegisterLinkedComponent(this); 43 | RuntimeMeshReference = nullptr; 44 | } 45 | 46 | if (NewMesh) 47 | { 48 | RuntimeMeshReference = NewMesh; 49 | RuntimeMeshReference->RegisterLinkedComponent(this); 50 | } 51 | 52 | MarkRenderStateDirty(); 53 | } 54 | 55 | 56 | FRuntimeMeshCollisionHitInfo URuntimeMeshComponent::GetHitSource(int32 FaceIndex) const 57 | { 58 | URuntimeMesh* Mesh = GetRuntimeMesh(); 59 | if (Mesh) 60 | { 61 | FRuntimeMeshCollisionHitInfo HitInfo = Mesh->GetHitSource(FaceIndex); 62 | if (HitInfo.SectionId >= 0) 63 | { 64 | HitInfo.Material = GetMaterial(HitInfo.SectionId); 65 | } 66 | return HitInfo; 67 | } 68 | return FRuntimeMeshCollisionHitInfo(); 69 | } 70 | 71 | void URuntimeMeshComponent::NewCollisionMeshReceived() 72 | { 73 | SCOPE_CYCLE_COUNTER(STAT_RuntimeMeshComponent_NewCollisionMeshReceived); 74 | 75 | // First recreate the physics state 76 | RecreatePhysicsState(); 77 | 78 | // Now update the navigation. 79 | FNavigationSystem::UpdateComponentData(*this); 80 | } 81 | 82 | void URuntimeMeshComponent::NewBoundsReceived() 83 | { 84 | UpdateBounds(); 85 | if (bRenderStateCreated) 86 | { 87 | MarkRenderTransformDirty(); 88 | } 89 | } 90 | 91 | void URuntimeMeshComponent::ForceProxyRecreate() 92 | { 93 | check(IsInGameThread()); 94 | if (bRenderStateCreated) 95 | { 96 | MarkRenderStateDirty(); 97 | } 98 | } 99 | 100 | 101 | FBoxSphereBounds URuntimeMeshComponent::CalcBounds(const FTransform& LocalToWorld) const 102 | { 103 | if (GetRuntimeMesh()) 104 | { 105 | FBoxSphereBounds TempBounds = GetRuntimeMesh()->GetLocalBounds(); 106 | return TempBounds.TransformBy(LocalToWorld); 107 | } 108 | 109 | return FBoxSphereBounds(FSphere(FVector::ZeroVector, 1)); 110 | } 111 | 112 | 113 | FPrimitiveSceneProxy* URuntimeMeshComponent::CreateSceneProxy() 114 | { 115 | SCOPE_CYCLE_COUNTER(STAT_RuntimeMeshComponent_CreateSceneProxy); 116 | 117 | if (RuntimeMeshReference == nullptr || !RuntimeMeshReference->GetRenderProxy(GetScene()->GetFeatureLevel()).IsValid()) 118 | { 119 | return nullptr; 120 | } 121 | 122 | return new FRuntimeMeshComponentSceneProxy(this); 123 | } 124 | 125 | UBodySetup* URuntimeMeshComponent::GetBodySetup() 126 | { 127 | if (GetRuntimeMesh()) 128 | { 129 | return GetRuntimeMesh()->BodySetup; 130 | } 131 | 132 | return nullptr; 133 | } 134 | 135 | 136 | 137 | int32 URuntimeMeshComponent::GetMaterialIndex(FName MaterialSlotName) const 138 | { 139 | if (URuntimeMesh* Mesh = GetRuntimeMesh()) 140 | { 141 | return Mesh->GetMaterialIndex(MaterialSlotName); 142 | } 143 | return INDEX_NONE; 144 | } 145 | 146 | TArray URuntimeMeshComponent::GetMaterialSlotNames() const 147 | { 148 | if (URuntimeMesh* Mesh = GetRuntimeMesh()) 149 | { 150 | return Mesh->GetMaterialSlotNames(); 151 | } 152 | return TArray(); 153 | } 154 | 155 | bool URuntimeMeshComponent::IsMaterialSlotNameValid(FName MaterialSlotName) const 156 | { 157 | if (URuntimeMesh* Mesh = GetRuntimeMesh()) 158 | { 159 | return Mesh->IsMaterialSlotNameValid(MaterialSlotName); 160 | } 161 | return false; 162 | } 163 | 164 | void URuntimeMeshComponent::GetUsedMaterials(TArray& OutMaterials, bool bGetDebugMaterials /*= false*/) const 165 | { 166 | TArray Slots = GetMaterialSlots(); 167 | 168 | for (int32 Index = 0; Index < Slots.Num(); Index++) 169 | { 170 | UMaterialInterface* Mat = Super::GetMaterial(Index); 171 | 172 | if (Mat == nullptr) 173 | { 174 | Mat = Slots[Index].Material; 175 | } 176 | 177 | if (Mat) 178 | { 179 | OutMaterials.Add(Mat); 180 | } 181 | } 182 | } 183 | 184 | int32 URuntimeMeshComponent::GetNumMaterials() const 185 | { 186 | int32 RuntimeMeshSections = GetRuntimeMesh() != nullptr ? GetRuntimeMesh()->GetNumMaterials() : 0; 187 | 188 | return FMath::Max(Super::GetNumMaterials(), RuntimeMeshSections); 189 | } 190 | 191 | UMaterialInterface* URuntimeMeshComponent::GetMaterial(int32 ElementIndex) const 192 | { 193 | UMaterialInterface* Mat = Super::GetMaterial(ElementIndex); 194 | 195 | // Use default override material system 196 | if (Mat != nullptr) 197 | return Mat; 198 | 199 | // fallback to RM sections material 200 | if (URuntimeMesh* Mesh = GetRuntimeMesh()) 201 | { 202 | return Mesh->GetMaterial(ElementIndex); 203 | } 204 | 205 | // Had no RM/Section return null 206 | return nullptr; 207 | } 208 | 209 | 210 | 211 | 212 | 213 | 214 | void URuntimeMeshComponent::PostLoad() 215 | { 216 | Super::PostLoad(); 217 | } 218 | 219 | void URuntimeMeshComponent::BeginDestroy() 220 | { 221 | Super::BeginDestroy(); 222 | } 223 | 224 | void URuntimeMeshComponent::OnRegister() 225 | { 226 | Super::OnRegister(); 227 | 228 | if (RuntimeMeshReference) 229 | { 230 | RuntimeMeshReference->RegisterLinkedComponent(this); 231 | } 232 | } 233 | 234 | void URuntimeMeshComponent::OnUnregister() 235 | { 236 | if (RuntimeMeshReference) 237 | { 238 | RuntimeMeshReference->UnRegisterLinkedComponent(this); 239 | RuntimeMeshReference = nullptr; 240 | } 241 | 242 | Super::OnUnregister(); 243 | } -------------------------------------------------------------------------------- /Plugins/RuntimeMeshComponent/Source/RuntimeMeshComponent/Private/RuntimeMeshComponentEngineSubsystem.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2020 TriAxis Games L.L.C. All Rights Reserved. 2 | 3 | 4 | #include "RuntimeMeshComponentEngineSubsystem.h" 5 | #include "RuntimeMeshComponentSettings.h" 6 | #include "RuntimeMeshCore.h" 7 | #include "RuntimeMesh.h" 8 | 9 | void URuntimeMeshComponentEngineSubsystem::FRuntimeMeshComponentDelayedActionTickObject::Tick(float DeltaTime) 10 | { 11 | ParentSubsystem->Tick(DeltaTime); 12 | } 13 | bool URuntimeMeshComponentEngineSubsystem::FRuntimeMeshComponentDelayedActionTickObject::IsTickable() const 14 | { 15 | return ParentSubsystem->IsTickable(); 16 | } 17 | 18 | 19 | void URuntimeMeshComponentEngineSubsystem::Initialize(FSubsystemCollectionBase& Collection) 20 | { 21 | Super::Initialize(Collection); 22 | 23 | // Create the tick object 24 | TickObject = MakeUnique(this); 25 | 26 | const URuntimeMeshComponentSettings* Settings = GetDefault(); 27 | check(Settings); 28 | 29 | InitializeThreads(CalculateNumThreads(Settings), Settings->ThreadStackSize, ConvertThreadPriority(Settings->ThreadPriority)); 30 | } 31 | 32 | void URuntimeMeshComponentEngineSubsystem::Deinitialize() 33 | { 34 | Super::Deinitialize(); 35 | 36 | if (ThreadPool) 37 | { 38 | ThreadPool->Destroy(); 39 | delete ThreadPool; 40 | ThreadPool = nullptr; 41 | } 42 | } 43 | 44 | void URuntimeMeshComponentEngineSubsystem::QueueMeshForUpdate(const FRuntimeMeshWeakRef& InMesh) 45 | { 46 | MeshesToUpdate.Enqueue(InMesh); 47 | } 48 | 49 | int32 URuntimeMeshComponentEngineSubsystem::CalculateNumThreads(const URuntimeMeshComponentSettings* Settings) 50 | { 51 | int32 MinThreads = Settings->MinMaxThreadPoolThreads.GetLowerBoundValue(); 52 | int32 MaxThreads = Settings->MinMaxThreadPoolThreads.GetUpperBoundValue(); 53 | int32 ThreadDivisor = Settings->SystemThreadDivisor; 54 | 55 | MaxThreads = FMath::Clamp(MaxThreads, 1, 64); 56 | MinThreads = FMath::Clamp(MinThreads, 1, MaxThreads); 57 | ThreadDivisor = FMath::Clamp(ThreadDivisor, 1, MaxThreads); 58 | 59 | int32 CoresWithHyperthreads = FGenericPlatformMisc::NumberOfCoresIncludingHyperthreads(); 60 | 61 | return FMath::Clamp( 62 | FMath::RoundToInt(CoresWithHyperthreads / (float)ThreadDivisor), 63 | MinThreads, MaxThreads); 64 | } 65 | 66 | 67 | void URuntimeMeshComponentEngineSubsystem::InitializeThreads(int32 NumThreads, int32 StackSize /*= 0*/, EThreadPriority ThreadPriority /*= TPri_BelowNormal*/) 68 | { 69 | if (ThreadPool == nullptr) 70 | { 71 | if (FPlatformProcess::SupportsMultithreading()) 72 | { 73 | ThreadPool = FQueuedThreadPool::Allocate(); 74 | 75 | int32 NumThreadsInThreadPool = NumThreads; 76 | 77 | if (FPlatformProperties::IsServerOnly()) 78 | { 79 | NumThreadsInThreadPool = 1; 80 | } 81 | 82 | verify(ThreadPool->Create(NumThreadsInThreadPool, StackSize, ThreadPriority)); 83 | } 84 | } 85 | } 86 | 87 | EThreadPriority URuntimeMeshComponentEngineSubsystem::ConvertThreadPriority(ERuntimeMeshThreadingPriority InPriority) 88 | { 89 | switch (InPriority) 90 | { 91 | case ERuntimeMeshThreadingPriority::Normal: 92 | return TPri_Normal; 93 | case ERuntimeMeshThreadingPriority::AboveNormal: 94 | return TPri_AboveNormal; 95 | case ERuntimeMeshThreadingPriority::BelowNormal: 96 | return TPri_BelowNormal; 97 | case ERuntimeMeshThreadingPriority::Highest: 98 | return TPri_Highest; 99 | case ERuntimeMeshThreadingPriority::Lowest: 100 | return TPri_Lowest; 101 | case ERuntimeMeshThreadingPriority::SlightlyBelowNormal: 102 | return TPri_SlightlyBelowNormal; 103 | case ERuntimeMeshThreadingPriority::TimeCritical: 104 | return TPri_TimeCritical; 105 | default: 106 | return TPri_BelowNormal; 107 | } 108 | } 109 | 110 | bool URuntimeMeshComponentEngineSubsystem::IsTickable() const 111 | { 112 | return !MeshesToUpdate.IsEmpty(); 113 | } 114 | 115 | void URuntimeMeshComponentEngineSubsystem::Tick(float DeltaTime) 116 | { 117 | FRuntimeMeshWeakRef WeakMeshRef; 118 | while (MeshesToUpdate.Dequeue(WeakMeshRef)) 119 | { 120 | FRuntimeMeshSharedRef MeshRef = WeakMeshRef.Pin(); 121 | 122 | if (MeshRef.IsValid()) 123 | { 124 | if (MeshRef->MeshProviderPtr) 125 | { 126 | // if (MeshRef->bNeedsInitialization) 127 | // { 128 | // MeshRef->InitializeInternal(); 129 | // MeshRef->bNeedsInitialization = false; 130 | // } 131 | 132 | if (MeshRef->bCollisionIsDirty) 133 | { 134 | MeshRef->UpdateCollision(); 135 | MeshRef->bCollisionIsDirty = false; 136 | } 137 | 138 | FReadScopeLock Lock(MeshRef->MeshProviderLock); 139 | if (MeshRef->bQueuedForMeshUpdate && !MeshRef->MeshProviderPtr->IsThreadSafe()) 140 | { 141 | // we check again when we actually set it just to make sure it hasn't changed 142 | if (MeshRef->bQueuedForMeshUpdate.AtomicSet(false) == true) 143 | { 144 | MeshRef->HandleUpdate(); 145 | } 146 | 147 | } 148 | } 149 | } 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /Plugins/RuntimeMeshComponent/Source/RuntimeMeshComponent/Private/RuntimeMeshComponentPlugin.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2020 TriAxis Games L.L.C. All Rights Reserved. 2 | 3 | #include "RuntimeMeshComponentPlugin.h" 4 | #include "Serialization/CustomVersion.h" 5 | #include "RuntimeMeshCore.h" 6 | 7 | 8 | // Register the custom version with core 9 | FCustomVersionRegistration GRegisterRuntimeMeshCustomVersion(FRuntimeMeshVersion::GUID, FRuntimeMeshVersion::LatestVersion, TEXT("RuntimeMesh")); 10 | 11 | 12 | class FRuntimeMeshComponentPlugin : public IRuntimeMeshComponentPlugin 13 | { 14 | /** IModuleInterface implementation */ 15 | virtual void StartupModule() override; 16 | virtual void ShutdownModule() override; 17 | }; 18 | 19 | IMPLEMENT_MODULE(FRuntimeMeshComponentPlugin, RuntimeMeshComponent) 20 | 21 | 22 | void FRuntimeMeshComponentPlugin::StartupModule() 23 | { 24 | } 25 | 26 | void FRuntimeMeshComponentPlugin::ShutdownModule() 27 | { 28 | } 29 | 30 | DEFINE_LOG_CATEGORY(RuntimeMeshLog); 31 | -------------------------------------------------------------------------------- /Plugins/RuntimeMeshComponent/Source/RuntimeMeshComponent/Private/RuntimeMeshComponentProxy.h: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2020 TriAxis Games L.L.C. All Rights Reserved. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "RuntimeMesh.h" 7 | #include "RuntimeMeshSectionProxy.h" 8 | #include "Materials/Material.h" 9 | 10 | class UBodySetup; 11 | class URuntimeMeshComponent; 12 | 13 | /** Runtime mesh scene proxy */ 14 | class FRuntimeMeshComponentSceneProxy : public FPrimitiveSceneProxy 15 | { 16 | private: 17 | // THis is the proxy we're rendering 18 | FRuntimeMeshProxyPtr RuntimeMeshProxy; 19 | 20 | // All the in use materials 21 | TMap Materials; 22 | 23 | // Reference all the in-use buffers so that as long as this proxy is around these buffers will be too. 24 | // This is meant only for statically drawn sections. Dynamically drawn sections can update safely in place. 25 | // Static sections get new buffers on each update. 26 | TArray> InUseBuffers; 27 | 28 | // Reference to the body setup for rendering. 29 | UBodySetup* BodySetup; 30 | 31 | // Store the combined material relevance. 32 | FMaterialRelevance MaterialRelevance; 33 | 34 | FRuntimeMeshObjectId ObjectId; 35 | 36 | bool bAnyMaterialUsesDithering; 37 | public: 38 | 39 | /*Constructor, copies the whole mesh data to feed to UE */ 40 | FRuntimeMeshComponentSceneProxy(URuntimeMeshComponent* Component); 41 | 42 | virtual ~FRuntimeMeshComponentSceneProxy(); 43 | 44 | int32 GetUniqueID() const { return ObjectId.Get(); } 45 | 46 | UMaterialInterface* GetMaterialSlot(int32 MaterialSlotId) const 47 | { 48 | UMaterialInterface*const* Mat = Materials.Find(MaterialSlotId); 49 | if (Mat && *Mat) 50 | { 51 | return *Mat; 52 | } 53 | 54 | return UMaterial::GetDefaultMaterial(MD_Surface); 55 | } 56 | 57 | void CreateRenderThreadResources() override; 58 | 59 | virtual bool CanBeOccluded() const override 60 | { 61 | return !MaterialRelevance.bDisableDepthTest; 62 | } 63 | 64 | virtual FPrimitiveViewRelevance GetViewRelevance(const FSceneView* View) const override; 65 | 66 | void CreateMeshBatch(FMeshBatch& MeshBatch, const FRuntimeMeshSectionProxy& Section, int32 LODIndex, int32 SectionId, UMaterialInterface* Material, FMaterialRenderProxy* WireframeMaterial, bool bForRayTracing) const; 67 | 68 | virtual void DrawStaticElements(FStaticPrimitiveDrawInterface* PDI) override; 69 | 70 | virtual void GetDynamicMeshElements(const TArray& Views, const FSceneViewFamily& ViewFamily, uint32 VisibilityMap, FMeshElementCollector& Collector) const override; 71 | 72 | 73 | #if RHI_RAYTRACING 74 | virtual bool IsRayTracingRelevant() const { return true; } 75 | virtual bool IsRayTracingStaticRelevant() const { return false; } 76 | 77 | /** Gathers dynamic ray tracing instances from this proxy. */ 78 | virtual void GetDynamicRayTracingInstances(struct FRayTracingMaterialGatheringContext& Context, TArray& OutRayTracingInstances); 79 | 80 | #endif // RHI_RAYTRACING 81 | 82 | int8 GetCurrentFirstLOD() const; 83 | 84 | int8 ComputeTemporalStaticMeshLOD(const FVector4& Origin, const float SphereRadius, const FSceneView& View, int32 MinLOD, float FactorScale, int32 SampleIndex) const; 85 | int8 ComputeStaticMeshLOD(const FVector4& Origin, const float SphereRadius, const FSceneView& View, int32 MinLOD, float FactorScale) const; 86 | FLODMask GetLODMask(const FSceneView* View) const; 87 | 88 | virtual int32 GetLOD(const FSceneView* View) const; 89 | 90 | virtual uint32 GetMemoryFootprint(void) const 91 | { 92 | return(sizeof(*this) + GetAllocatedSize()); 93 | } 94 | 95 | uint32 GetAllocatedSize(void) const 96 | { 97 | return(FPrimitiveSceneProxy::GetAllocatedSize()); 98 | } 99 | 100 | SIZE_T GetTypeHash() const override 101 | { 102 | static size_t UniquePointer; 103 | return reinterpret_cast(&UniquePointer); 104 | } 105 | }; -------------------------------------------------------------------------------- /Plugins/RuntimeMeshComponent/Source/RuntimeMeshComponent/Private/RuntimeMeshComponentSettings.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2020 TriAxis Games L.L.C. All Rights Reserved. 2 | 3 | 4 | #include "RuntimeMeshComponentSettings.h" 5 | 6 | URuntimeMeshComponentSettings::URuntimeMeshComponentSettings(const FObjectInitializer & ObjectInitializer) 7 | : Super(ObjectInitializer) 8 | , bUse32BitIndicesByDefault(false) 9 | , bUseHighPrecisionTexCoordsByDefault(false) 10 | , bUseHighPrecisionTangentsByDefault(false) 11 | , bCookCollisionAsync(false) 12 | , DefaultCookingMode(ERuntimeMeshCollisionCookingMode::CookingPerformance) 13 | , MinMaxThreadPoolThreads(1, 4) 14 | , SystemThreadDivisor(2) 15 | , ThreadPriority(ERuntimeMeshThreadingPriority::BelowNormal) 16 | , ThreadStackSize(0) 17 | , MaxAllowedTimePerTick(1000 / 90) 18 | { 19 | 20 | } 21 | 22 | FName URuntimeMeshComponentSettings::GetCategoryName() const 23 | { 24 | return TEXT("Plugins"); 25 | } 26 | 27 | #if WITH_EDITOR 28 | FText URuntimeMeshComponentSettings::GetSectionText() const 29 | { 30 | return NSLOCTEXT("RuntimeMeshComponent", "RuntimeMeshComponentSettingsSection", "Runtime Mesh Component"); 31 | } 32 | 33 | void URuntimeMeshComponentSettings::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) 34 | { 35 | if (PropertyChangedEvent.Property != nullptr) 36 | { 37 | SettingsChangedDelegate.Broadcast(PropertyChangedEvent.Property->GetName(), this); 38 | } 39 | } 40 | 41 | URuntimeMeshComponentSettings::FOnRuntimeMeshComponentSettingsChanged& URuntimeMeshComponentSettings::OnSettingsChanged() 42 | { 43 | return SettingsChangedDelegate; 44 | } 45 | 46 | URuntimeMeshComponentSettings::FOnRuntimeMeshComponentSettingsChanged URuntimeMeshComponentSettings::SettingsChangedDelegate; 47 | #endif -------------------------------------------------------------------------------- /Plugins/RuntimeMeshComponent/Source/RuntimeMeshComponent/Private/RuntimeMeshModifier.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2020 TriAxis Games L.L.C. All Rights Reserved. 2 | 3 | 4 | #include "RuntimeMeshModifier.h" 5 | 6 | URuntimeMeshModifier::URuntimeMeshModifier() 7 | { 8 | 9 | } 10 | 11 | void URuntimeMeshModifier::ApplyToMesh_Implementation(FRuntimeMeshRenderableMeshData& MeshData) 12 | { 13 | 14 | } 15 | 16 | void URuntimeMeshModifier::ApplyToCollisionMesh_Implementation(FRuntimeMeshCollisionData& MeshData) 17 | { 18 | 19 | } 20 | -------------------------------------------------------------------------------- /Plugins/RuntimeMeshComponent/Source/RuntimeMeshComponent/Private/RuntimeMeshProviderTargetInterface.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2020 TriAxis Games L.L.C. All Rights Reserved. 2 | 3 | 4 | #include "RuntimeMeshProviderTargetInterface.h" 5 | 6 | -------------------------------------------------------------------------------- /Plugins/RuntimeMeshComponent/Source/RuntimeMeshComponent/Private/RuntimeMeshProxy.h: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2020 TriAxis Games L.L.C. All Rights Reserved. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "RuntimeMeshSectionProxy.h" 7 | #include "HAL/ThreadSafeBool.h" 8 | #include "Containers/Queue.h" 9 | 10 | 11 | /** 12 | * 13 | */ 14 | class FRuntimeMeshProxy : public TSharedFromThis 15 | { 16 | TInlineLODArray LODs; 17 | 18 | 19 | 20 | FThreadSafeBool IsQueuedForUpdate; 21 | TQueue, EQueueMode::Mpsc> PendingUpdates; 22 | 23 | 24 | uint32 bShouldRender : 1; 25 | uint32 bShouldRenderStatic : 1; 26 | uint32 bShouldRenderDynamic : 1; 27 | uint32 bShouldRenderShadow : 1; 28 | 29 | int8 MinAvailableLOD; 30 | int8 MaxAvailableLOD; 31 | 32 | int8 CurrentForcedLOD; 33 | 34 | FRuntimeMeshObjectId ObjectId; 35 | 36 | uint32 ParentMeshId; 37 | public: 38 | FRuntimeMeshProxy(uint32 InParentMeshId); 39 | ~FRuntimeMeshProxy(); 40 | 41 | int32 GetUniqueID() const { return ObjectId.Get(); } 42 | int32 GetMeshID() const { return ParentMeshId; } 43 | 44 | bool ShouldRender() const { return bShouldRender; } 45 | bool ShouldRenderStatic() const { return bShouldRenderStatic; } 46 | bool ShouldRenderDynamic() const { return bShouldRenderDynamic; } 47 | bool ShouldRenderShadow() const { return bShouldRenderShadow; } 48 | 49 | int32 GetMinLOD() const { return MinAvailableLOD; } 50 | int32 GetMaxLOD() const { return MaxAvailableLOD; } 51 | 52 | bool HasValidLODs() const { return MinAvailableLOD != INDEX_NONE && MaxAvailableLOD != INDEX_NONE && MaxAvailableLOD >= MinAvailableLOD; } 53 | 54 | int32 GetForcedLOD() const { return CurrentForcedLOD; } 55 | 56 | FRuntimeMeshLODData& GetLOD(int32 LODIndex) { return LODs[LODIndex]; } 57 | 58 | float GetScreenSize(int32 LODIndex) const; 59 | 60 | 61 | void QueueForUpdate(); 62 | void FlushPendingUpdates(); 63 | 64 | 65 | void ResetProxy_GameThread(); 66 | 67 | void InitializeLODs_GameThread(const TArray& InProperties); 68 | void ClearAllSectionsForLOD_GameThread(int32 LODIndex); 69 | void RemoveAllSectionsForLOD_GameThread(int32 LODIndex); 70 | 71 | void CreateOrUpdateSection_GameThread(int32 LODIndex, int32 SectionId, const FRuntimeMeshSectionProperties& InProperties, bool bShouldReset); 72 | void SetSectionsForLOD_GameThread(int32 LODIndex, const TMap& InProperties, bool bShouldReset); 73 | void UpdateSectionMesh_GameThread(int32 LODIndex, int32 SectionId, const TSharedPtr& MeshData); 74 | void UpdateMultipleSectionsMesh_GameThread(int32 LODIndex, const TMap>& MeshData); 75 | void ClearSection_GameThread(int32 LODIndex, int32 SectionId); 76 | void RemoveSection_GameThread(int32 LODIndex, int32 SectionId); 77 | 78 | 79 | void ResetProxy_RenderThread(); 80 | 81 | void InitializeLODs_RenderThread(const TArray& InProperties); 82 | void ClearAllSectionsForLOD_RenderThread(int32 LODIndex); 83 | void RemoveAllSectionsForLOD_RenderThread(int32 LODIndex); 84 | 85 | void CreateOrUpdateSection_RenderThread(int32 LODIndex, int32 SectionId, const FRuntimeMeshSectionProperties& InProperties, bool bShouldReset); 86 | void SetSectionsForLOD_RenderThread(int32 LODIndex, const TMap& InProperties, bool bShouldReset); 87 | void UpdateSectionMesh_RenderThread(int32 LODIndex, int32 SectionId, const TSharedPtr& MeshData); 88 | void UpdateMultipleSectionsMesh_RenderThread(int32 LODIndex, const TMap>& MeshData); 89 | void ClearSection_RenderThread(int32 LODIndex, int32 SectionId); 90 | void RemoveSection_RenderThread(int32 LODIndex, int32 SectionId); 91 | 92 | 93 | void UpdateRenderState(); 94 | 95 | void ClearSection(FRuntimeMeshSectionProxy& Section); 96 | 97 | void ApplyMeshToSection(int32 LODIndex, int32 SectionId, FRuntimeMeshSectionProxy& Section, FRuntimeMeshSectionUpdateData&& MeshData); 98 | 99 | }; 100 | 101 | -------------------------------------------------------------------------------- /Plugins/RuntimeMeshComponent/Source/RuntimeMeshComponent/Private/RuntimeMeshRendering.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2020 TriAxis Games L.L.C. All Rights Reserved. 2 | 3 | #include "RuntimeMeshRendering.h" 4 | #include "RuntimeMeshComponentPlugin.h" 5 | #include "RuntimeMeshSectionProxy.h" 6 | 7 | 8 | FRuntimeMeshVertexBuffer::FRuntimeMeshVertexBuffer(bool bInIsDynamicBuffer, int32 DefaultVertexSize) 9 | : bIsDynamicBuffer(bInIsDynamicBuffer) 10 | , VertexSize(DefaultVertexSize) 11 | , NumVertices(0) 12 | , ShaderResourceView(nullptr) 13 | { 14 | } 15 | 16 | 17 | void FRuntimeMeshVertexBuffer::InitRHI() 18 | { 19 | } 20 | 21 | void FRuntimeMeshVertexBuffer::ReleaseRHI() 22 | { 23 | ShaderResourceView.SafeRelease(); 24 | FVertexBuffer::ReleaseRHI(); 25 | } 26 | 27 | 28 | 29 | FRuntimeMeshIndexBuffer::FRuntimeMeshIndexBuffer(bool bInIsDynamicBuffer) 30 | : bIsDynamicBuffer(bInIsDynamicBuffer) 31 | , IndexSize(CalculateStride(false)) 32 | , NumIndices(0) 33 | { 34 | } 35 | 36 | void FRuntimeMeshIndexBuffer::InitRHI() 37 | { 38 | } 39 | 40 | 41 | 42 | 43 | FRuntimeMeshVertexFactory::FRuntimeMeshVertexFactory(ERHIFeatureLevel::Type InFeatureLevel) 44 | : FLocalVertexFactory(InFeatureLevel, "FRuntimeMeshVertexFactory") 45 | { 46 | } 47 | 48 | /** Init function that can be called on any thread, and will do the right thing (enqueue command if called on main thread) */ 49 | void FRuntimeMeshVertexFactory::Init(FLocalVertexFactory::FDataType VertexStructure) 50 | { 51 | if (IsInRenderingThread()) 52 | { 53 | SetData(VertexStructure); 54 | } 55 | else 56 | { 57 | // Send the command to the render thread 58 | ENQUEUE_RENDER_COMMAND(InitRuntimeMeshVertexFactory)( 59 | [this, VertexStructure](FRHICommandListImmediate & RHICmdList) 60 | { 61 | Init(VertexStructure); 62 | } 63 | ); 64 | } 65 | } -------------------------------------------------------------------------------- /Plugins/RuntimeMeshComponent/Source/RuntimeMeshComponent/Private/RuntimeMeshSectionProxy.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2020 TriAxis Games L.L.C. All Rights Reserved. 2 | 3 | #include "RuntimeMeshSectionProxy.h" 4 | #include "RuntimeMeshComponentPlugin.h" 5 | 6 | 7 | #if RHI_RAYTRACING 8 | #include "RayTracingInstance.h" 9 | #endif 10 | 11 | 12 | DECLARE_DWORD_COUNTER_STAT(TEXT("RuntimeMeshSectionProxy - Num Triangles"), STAT_RuntimeMeshSectionProxy_NumTriangles, STATGROUP_RuntimeMesh); 13 | 14 | 15 | void FRuntimeMeshSectionProxyBuffers::Reset() 16 | { 17 | VertexFactory.ReleaseResource(); 18 | 19 | PositionBuffer.ReleaseResource(); 20 | TangentsBuffer.ReleaseResource(); 21 | UVsBuffer.ReleaseResource(); 22 | ColorBuffer.ReleaseResource(); 23 | 24 | IndexBuffer.ReleaseResource(); 25 | AdjacencyIndexBuffer.ReleaseResource(); 26 | 27 | #if RHI_RAYTRACING 28 | if (IsRayTracingEnabled()) 29 | { 30 | RayTracingGeometry.ReleaseResource(); 31 | } 32 | #endif 33 | } 34 | 35 | void FRuntimeMeshSectionProxyBuffers::UpdateRayTracingGeometry() 36 | { 37 | #if RHI_RAYTRACING 38 | if (IsRayTracingEnabled()) 39 | { 40 | FRayTracingGeometryInitializer Initializer; 41 | #if ENGINE_MAJOR_VERSION >= 4 && ENGINE_MINOR_VERSION <= 23 42 | Initializer.PositionVertexBuffer = nullptr; 43 | #endif 44 | Initializer.IndexBuffer = nullptr; 45 | #if ENGINE_MAJOR_VERSION >= 4 && ENGINE_MINOR_VERSION <= 23 46 | Initializer.BaseVertexIndex = 0; 47 | Initializer.VertexBufferStride = 12; 48 | Initializer.VertexBufferByteOffset = 0; 49 | #endif 50 | Initializer.TotalPrimitiveCount = 0; 51 | 52 | #if ENGINE_MAJOR_VERSION >= 4 && ENGINE_MINOR_VERSION <= 23 53 | Initializer.VertexBufferElementType = VET_Float3; 54 | #endif 55 | Initializer.GeometryType = RTGT_Triangles; 56 | Initializer.bFastBuild = true; 57 | Initializer.bAllowUpdate = false; 58 | 59 | RayTracingGeometry.SetInitializer(Initializer); 60 | RayTracingGeometry.InitResource(); 61 | 62 | #if ENGINE_MAJOR_VERSION >= 4 && ENGINE_MINOR_VERSION <= 23 63 | RayTracingGeometry.Initializer.PositionVertexBuffer = PositionBuffer.VertexBufferRHI; 64 | #endif 65 | RayTracingGeometry.Initializer.IndexBuffer = IndexBuffer.IndexBufferRHI; 66 | RayTracingGeometry.Initializer.TotalPrimitiveCount = IndexBuffer.Num() / 3; 67 | 68 | #if ENGINE_MAJOR_VERSION >= 4 && ENGINE_MINOR_VERSION >= 24 69 | FRayTracingGeometrySegment Segment; 70 | Segment.VertexBuffer = PositionBuffer.VertexBufferRHI; 71 | Segment.NumPrimitives = IndexBuffer.Num() / 3; 72 | RayTracingGeometry.Initializer.Segments.Add(Segment); 73 | #endif 74 | 75 | RayTracingGeometry.UpdateRHI(); 76 | } 77 | #endif 78 | } 79 | -------------------------------------------------------------------------------- /Plugins/RuntimeMeshComponent/Source/RuntimeMeshComponent/Public/Modifiers/RuntimeMeshModifierAdjacency.h: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2020 TriAxis Games L.L.C. All Rights Reserved. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "RuntimeMeshModifier.h" 7 | #include "RuntimeMeshModifierAdjacency.generated.h" 8 | 9 | /** 10 | * 11 | */ 12 | UCLASS() 13 | class RUNTIMEMESHCOMPONENT_API URuntimeMeshModifierAdjacency : public URuntimeMeshModifier 14 | { 15 | GENERATED_BODY() 16 | 17 | 18 | public: 19 | URuntimeMeshModifierAdjacency(); 20 | 21 | virtual void ApplyToMesh_Implementation(FRuntimeMeshRenderableMeshData& MeshData) override; 22 | 23 | 24 | /* 25 | * Calculates the tessellation indices for the supplied mesh data, setting the result back to the tessellation triangles in the mesh data. 26 | */ 27 | UFUNCTION(BlueprintCallable, Category="RuntimeMesh|Modifiers|Adjacency") 28 | static void CalculateTessellationIndices(FRuntimeMeshRenderableMeshData& MeshData); 29 | 30 | private: 31 | struct Vertex; 32 | struct Edge; 33 | struct Corner; 34 | struct Triangle; 35 | 36 | static FORCEINLINE uint32 HashValue(const FVector& Vec) 37 | { 38 | return 31337 * GetTypeHash(Vec.X) + 13 * GetTypeHash(Vec.Y) + 3 * GetTypeHash(Vec.Z); 39 | } 40 | 41 | static FORCEINLINE uint32 HashValue(const Vertex& Vert) 42 | { 43 | return HashValue(Vert.Position); 44 | } 45 | 46 | using EdgeDictionary = TMap; 47 | using PositionDictionary = TMap; 48 | 49 | struct Vertex 50 | { 51 | FVector Position; 52 | FVector2D TexCoord; 53 | 54 | Vertex() { } 55 | Vertex(const FVector& InPosition, const FVector2D& InTexCoord) 56 | : Position(InPosition), TexCoord(InTexCoord) 57 | { } 58 | 59 | FORCEINLINE bool operator==(const Vertex& Other) const 60 | { 61 | return Position == Other.Position; 62 | } 63 | FORCEINLINE bool operator<(const Vertex& Other) const 64 | { 65 | return Position.X < Other.Position.X 66 | || Position.Y < Other.Position.Y 67 | || Position.Z < Other.Position.Z; 68 | } 69 | }; 70 | 71 | struct Edge 72 | { 73 | private: 74 | uint32 IndexFrom; 75 | uint32 IndexTo; 76 | 77 | Vertex VertexFrom; 78 | Vertex VertexTo; 79 | 80 | uint32 CachedHash; 81 | 82 | public: 83 | Edge() : CachedHash(0) { } 84 | Edge(uint32 InIndexFrom, uint32 InIndexTo, const Vertex& InVertexFrom, const Vertex& InVertexTo) 85 | : IndexFrom(InIndexFrom), IndexTo(InIndexTo), VertexFrom(InVertexFrom), VertexTo(InVertexTo) 86 | { 87 | // Hash should only consider position, not index. 88 | // We want values with different indices to compare true. 89 | CachedHash = 7 * HashValue(VertexFrom) + 2 * HashValue(VertexTo); 90 | } 91 | 92 | Vertex GetVertex(uint32 I) const 93 | { 94 | switch (I) 95 | { 96 | case 0: 97 | return VertexFrom; 98 | case 1: 99 | return VertexTo; 100 | default: 101 | checkNoEntry(); 102 | return Vertex(); 103 | } 104 | } 105 | 106 | uint32 GetIndex(uint32 I) const 107 | { 108 | switch (I) 109 | { 110 | case 0: 111 | return IndexFrom; 112 | case 1: 113 | return IndexTo; 114 | default: 115 | checkNoEntry(); 116 | return 0; 117 | } 118 | } 119 | 120 | Edge GetReverse() const 121 | { 122 | return Edge(IndexTo, IndexFrom, VertexTo, VertexFrom); 123 | } 124 | 125 | FORCEINLINE bool operator<(const Edge& Other) const 126 | { 127 | // Quick out, otherwise we have to compare vertices 128 | if (IndexFrom == Other.IndexFrom && IndexTo == Other.IndexTo) 129 | { 130 | return false; 131 | } 132 | 133 | return VertexFrom < Other.VertexFrom || VertexTo < Other.VertexTo; 134 | } 135 | 136 | FORCEINLINE bool operator==(const Edge& Other) const 137 | { 138 | return (IndexFrom == Other.IndexFrom && IndexTo == Other.IndexTo) || 139 | (VertexFrom == Other.VertexFrom && VertexTo == Other.VertexTo); 140 | } 141 | 142 | friend FORCEINLINE uint32 GetTypeHash(const Edge& E) 143 | { 144 | return E.CachedHash; 145 | } 146 | }; 147 | 148 | struct Corner 149 | { 150 | uint32 Index; 151 | FVector2D TexCoord; 152 | 153 | Corner() : Index(0) { } 154 | Corner(uint32 InIndex, FVector2D InTexCoord) 155 | : Index(InIndex), TexCoord(InTexCoord) 156 | { } 157 | }; 158 | 159 | struct Triangle 160 | { 161 | Edge Edge0; 162 | Edge Edge1; 163 | Edge Edge2; 164 | 165 | public: 166 | Triangle(uint32 Index0, uint32 Index1, uint32 Index2, const Vertex& Vertex0, const Vertex& Vertex1, const Vertex& Vertex2) 167 | : Edge0(Index0, Index1, Vertex0, Vertex1) 168 | , Edge1(Index1, Index2, Vertex1, Vertex2) 169 | , Edge2(Index2, Index0, Vertex2, Vertex0) 170 | { } 171 | 172 | FORCEINLINE bool operator<(const Triangle& Other) const 173 | { 174 | return Edge0 < Other.Edge0 || Edge1 < Other.Edge1 || Edge2 < Other.Edge2; 175 | } 176 | 177 | FORCEINLINE const Edge& GetEdge(uint32 I) 178 | { 179 | return ((Edge*)&Edge0)[I]; 180 | } 181 | FORCEINLINE uint32 GetIndex(uint32 I) 182 | { 183 | return GetEdge(I).GetIndex(0); 184 | } 185 | 186 | }; 187 | 188 | static void AddIfLeastUV(PositionDictionary& PosDict, const Vertex& Vert, uint32 Index); 189 | 190 | static void ReplacePlaceholderIndices(FRuntimeMeshRenderableMeshData& MeshData, EdgeDictionary& EdgeDict, PositionDictionary& PosDict); 191 | 192 | static void ExpandIB(FRuntimeMeshRenderableMeshData& MeshData, EdgeDictionary& OutEdgeDict, PositionDictionary& OutPosDict); 193 | }; 194 | -------------------------------------------------------------------------------- /Plugins/RuntimeMeshComponent/Source/RuntimeMeshComponent/Public/Modifiers/RuntimeMeshModifierNormals.h: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2020 TriAxis Games L.L.C. All Rights Reserved. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "RuntimeMeshModifier.h" 7 | #include "RuntimeMeshModifierNormals.generated.h" 8 | 9 | UCLASS(HideCategories = Object, BlueprintType, Blueprintable, Meta = (ShortTooltip = "A RuntimeMeshModifierNormals is a class that implements logic to generate normals and tangents for a supplied mesh.")) 10 | class RUNTIMEMESHCOMPONENT_API URuntimeMeshModifierNormals : public URuntimeMeshModifier 11 | { 12 | GENERATED_BODY() 13 | public: 14 | 15 | UPROPERTY(Category = "RuntimeMesh|Modifiers|Normals", VisibleAnywhere, BlueprintReadWrite) 16 | bool bComputeSmoothNormals; 17 | 18 | public: 19 | URuntimeMeshModifierNormals(); 20 | 21 | virtual void ApplyToMesh_Implementation(FRuntimeMeshRenderableMeshData& MeshData) override; 22 | 23 | UFUNCTION(BlueprintCallable, Category = "RuntimeMesh|Modifiers|Normals") 24 | static void CalculateNormalsTangents(FRuntimeMeshRenderableMeshData& MeshData, bool bInComputeSmoothNormals = false); 25 | 26 | private: 27 | 28 | static TMultiMap FindDuplicateVerticesMap(const FRuntimeMeshVertexPositionStream& PositionStream, float Tollerance = 0.0); 29 | 30 | struct FRuntimeMeshVertexSortingElement 31 | { 32 | float Value; 33 | int32 Index; 34 | 35 | FRuntimeMeshVertexSortingElement() {} 36 | 37 | FRuntimeMeshVertexSortingElement(int32 InIndex, FVector Vector) 38 | { 39 | Value = 0.30f * Vector.X + 0.33f * Vector.Y + 0.37f * Vector.Z; 40 | Index = InIndex; 41 | } 42 | }; 43 | 44 | struct FRuntimeMeshVertexSortingFunction 45 | { 46 | FORCEINLINE bool operator()(FRuntimeMeshVertexSortingElement const& Left, FRuntimeMeshVertexSortingElement const& Right) const 47 | { 48 | return Left.Value < Right.Value; 49 | } 50 | }; 51 | 52 | }; 53 | -------------------------------------------------------------------------------- /Plugins/RuntimeMeshComponent/Source/RuntimeMeshComponent/Public/Providers/RuntimeMeshProviderBox.h: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2020 TriAxis Games L.L.C. All Rights Reserved. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "RuntimeMeshProvider.h" 7 | #include "RuntimeMeshProviderBox.generated.h" 8 | 9 | UCLASS(HideCategories = Object, BlueprintType) 10 | class RUNTIMEMESHCOMPONENT_API URuntimeMeshProviderBox : public URuntimeMeshProvider 11 | { 12 | GENERATED_BODY() 13 | private: 14 | mutable FCriticalSection PropertySyncRoot; 15 | 16 | UPROPERTY(Category = "RuntimeMesh|Providers|Box", VisibleAnywhere, BlueprintGetter=GetBoxRadius, BlueprintSetter=SetBoxRadius) 17 | FVector BoxRadius; 18 | 19 | UPROPERTY(Category = "RuntimeMesh|Providers|Box", VisibleAnywhere, BlueprintGetter=GetBoxMaterial, BlueprintSetter=SetBoxMaterial) 20 | UMaterialInterface* Material; 21 | public: 22 | UFUNCTION(Category = "RuntimeMesh|Providers|Box", BlueprintCallable) 23 | FVector GetBoxRadius() const; 24 | UFUNCTION(Category = "RuntimeMesh|Providers|Box", BlueprintCallable) 25 | void SetBoxRadius(const FVector& InRadius); 26 | 27 | UFUNCTION(Category = "RuntimeMesh|Providers|Box", BlueprintCallable) 28 | UMaterialInterface* GetBoxMaterial() const; 29 | UFUNCTION(Category = "RuntimeMesh|Providers|Box", BlueprintCallable) 30 | void SetBoxMaterial(UMaterialInterface* InMaterial); 31 | 32 | 33 | protected: 34 | void Initialize() override; 35 | FBoxSphereBounds GetBounds() override; 36 | bool GetSectionMeshForLOD(int32 LODIndex, int32 SectionId, FRuntimeMeshRenderableMeshData& MeshData) override; 37 | FRuntimeMeshCollisionSettings GetCollisionSettings() override; 38 | bool HasCollisionMesh() override; 39 | bool GetCollisionMesh(FRuntimeMeshCollisionData& CollisionData) override; 40 | bool IsThreadSafe() override; 41 | 42 | }; 43 | -------------------------------------------------------------------------------- /Plugins/RuntimeMeshComponent/Source/RuntimeMeshComponent/Public/Providers/RuntimeMeshProviderCollision.h: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2020 TriAxis Games L.L.C. All Rights Reserved. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "RuntimeMeshProvider.h" 7 | #include "RuntimeMeshProviderCollision.generated.h" 8 | 9 | UCLASS(HideCategories = Object, BlueprintType) 10 | class RUNTIMEMESHCOMPONENT_API URuntimeMeshProviderCollision : public URuntimeMeshProviderPassthrough 11 | { 12 | GENERATED_BODY() 13 | 14 | private: 15 | UPROPERTY() 16 | int32 LODForMeshCollision; 17 | 18 | UPROPERTY() 19 | TMap RenderableCollisionData; 20 | 21 | UPROPERTY() 22 | TSet SectionsAffectingCollision; 23 | 24 | UPROPERTY() 25 | FRuntimeMeshCollisionSettings CollisionSettings; 26 | 27 | UPROPERTY() 28 | FRuntimeMeshCollisionData CollisionMesh; 29 | 30 | FCriticalSection SyncRoot; 31 | public: 32 | 33 | URuntimeMeshProviderCollision(); 34 | 35 | UFUNCTION(Category = "RuntimeMesh|Providers|Collision", BlueprintCallable) 36 | void SetCollisionSettings(const FRuntimeMeshCollisionSettings& NewCollisionSettings); 37 | 38 | UFUNCTION(Category = "RuntimeMesh|Providers|Collision", BlueprintCallable) 39 | void SetCollisionMesh(const FRuntimeMeshCollisionData& NewCollisionMesh); 40 | 41 | UFUNCTION(Category = "RuntimeMesh|Providers|Collision", BlueprintCallable) 42 | void SetRenderableLODForCollision(int32 LODIndex); 43 | 44 | UFUNCTION(Category = "RuntimeMesh|Providers|Collision", BlueprintCallable) 45 | void SetRenderableSectionAffectsCollision(int32 SectionId, bool bCollisionEnabled); 46 | 47 | 48 | protected: 49 | virtual bool GetSectionMeshForLOD(int32 LODIndex, int32 SectionId, FRuntimeMeshRenderableMeshData& MeshData) override; 50 | virtual bool GetAllSectionsMeshForLOD(int32 LODIndex, TMap& MeshDatas) override; 51 | virtual FRuntimeMeshCollisionSettings GetCollisionSettings() override; 52 | virtual bool HasCollisionMesh() override; 53 | virtual bool GetCollisionMesh(FRuntimeMeshCollisionData& CollisionData) override; 54 | virtual bool IsThreadSafe() override; 55 | 56 | virtual void ConfigureLODs(const TArray& InLODs) override; 57 | virtual void CreateSection(int32 LODIndex, int32 SectionId, const FRuntimeMeshSectionProperties& SectionProperties) override; 58 | virtual void ClearSection(int32 LODIndex, int32 SectionId) override; 59 | virtual void RemoveSection(int32 LODIndex, int32 SectionId) override; 60 | 61 | void ClearCachedData(); 62 | void ClearSectionData(int32 LODIndex, int32 SectionId); 63 | }; -------------------------------------------------------------------------------- /Plugins/RuntimeMeshComponent/Source/RuntimeMeshComponent/Public/Providers/RuntimeMeshProviderMemoryCache.h: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2020 TriAxis Games L.L.C. All Rights Reserved. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "RuntimeMeshProvider.h" 7 | #include "RuntimeMeshProviderMemoryCache.generated.h" 8 | 9 | 10 | UCLASS(HideCategories = Object, BlueprintType) 11 | class RUNTIMEMESHCOMPONENT_API URuntimeMeshProviderMemoryCache : public URuntimeMeshProviderPassthrough 12 | { 13 | GENERATED_BODY() 14 | private: 15 | 16 | TMap> CacheSectionConfig; 17 | TMap>> CachedMeshData; 18 | 19 | TOptional CachedCollisionSettings; 20 | TOptional CachedHasCollisionMesh; 21 | TOptional> CachedCollisionData; 22 | 23 | FCriticalSection MeshSyncRoot; 24 | FCriticalSection CollisionSyncRoot; 25 | public: 26 | UFUNCTION(Category = "RuntimeMesh|Providers|Cache", BlueprintCallable) 27 | void ClearCache(); 28 | 29 | protected: 30 | virtual bool GetSectionMeshForLOD(int32 LODIndex, int32 SectionId, FRuntimeMeshRenderableMeshData& MeshData) override; 31 | virtual bool GetAllSectionsMeshForLOD(int32 LODIndex, TMap& MeshDatas) override; 32 | virtual FRuntimeMeshCollisionSettings GetCollisionSettings() override; 33 | virtual bool HasCollisionMesh() override; 34 | virtual bool GetCollisionMesh(FRuntimeMeshCollisionData& CollisionData) override; 35 | virtual bool IsThreadSafe() override; 36 | 37 | virtual void ConfigureLODs(const TArray& InLODs) override; 38 | virtual void MarkLODDirty(int32 LODIndex) override; 39 | virtual void MarkAllLODsDirty() override; 40 | virtual void CreateSection(int32 LODIndex, int32 SectionId, const FRuntimeMeshSectionProperties& SectionProperties) override; 41 | virtual void MarkSectionDirty(int32 LODIndex, int32 SectionId) override; 42 | virtual void ClearSection(int32 LODIndex, int32 SectionId) override; 43 | virtual void RemoveSection(int32 LODIndex, int32 SectionId) override; 44 | virtual void MarkCollisionDirty() override; 45 | 46 | virtual void BeginDestroy() override; 47 | 48 | private: 49 | void ClearCacheLOD(int32 LODIndex); 50 | void ClearCacheSection(int32 LODIndex, int32 SectionId); 51 | 52 | }; -------------------------------------------------------------------------------- /Plugins/RuntimeMeshComponent/Source/RuntimeMeshComponent/Public/Providers/RuntimeMeshProviderModifiers.h: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2020 TriAxis Games L.L.C. All Rights Reserved. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "RuntimeMeshProvider.h" 7 | #include "RuntimeMeshModifier.h" 8 | #include "RuntimeMeshProviderModifiers.generated.h" 9 | 10 | 11 | UCLASS(HideCategories = Object, BlueprintType) 12 | class RUNTIMEMESHCOMPONENT_API URuntimeMeshProviderModifiers : public URuntimeMeshProviderPassthrough 13 | { 14 | GENERATED_BODY() 15 | private: 16 | UPROPERTY() 17 | TArray Modifiers; 18 | 19 | public: 20 | 21 | UFUNCTION(Category = "RuntimeMesh|Providers|Modifiers", BlueprintCallable) 22 | void AddModifier(URuntimeMeshModifier* NewModifier); 23 | 24 | UFUNCTION(Category = "RuntimeMesh|Providers|Modifiers", BlueprintCallable) 25 | void RemoveModifier(URuntimeMeshModifier* ModifierToRemove); 26 | 27 | 28 | protected: 29 | bool GetSectionMeshForLOD(int32 LODIndex, int32 SectionId, FRuntimeMeshRenderableMeshData& MeshData) override; 30 | bool GetAllSectionsMeshForLOD(int32 LODIndex, TMap& MeshDatas) override; 31 | bool GetCollisionMesh(FRuntimeMeshCollisionData& CollisionData) override; 32 | 33 | private: 34 | void ApplyModifiers(FRuntimeMeshRenderableMeshData& MeshData); 35 | void ApplyModifiers(FRuntimeMeshCollisionData& CollisionData); 36 | 37 | }; -------------------------------------------------------------------------------- /Plugins/RuntimeMeshComponent/Source/RuntimeMeshComponent/Public/Providers/RuntimeMeshProviderPlane.h: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2020 TriAxis Games L.L.C. All Rights Reserved. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "RuntimeMeshProvider.h" 7 | #include "RuntimeMeshProviderPlane.generated.h" 8 | 9 | /* 10 | A - - - - B Supply with A, B and C, D will be computed 11 | | /| 12 | / | 13 | | / | 14 | / | 15 | |/ | 16 | C - - - - D 17 | */ 18 | 19 | UCLASS(HideCategories = Object, BlueprintType) 20 | class RUNTIMEMESHCOMPONENT_API URuntimeMeshProviderPlane : public URuntimeMeshProviderPassthrough 21 | { 22 | GENERATED_BODY() 23 | 24 | private: 25 | mutable FCriticalSection PropertySyncRoot; 26 | 27 | int32 MaxLOD; 28 | 29 | 30 | UPROPERTY(Category = "RuntimeMesh|Providers|Sphere", EditAnywhere) 31 | FVector LocationA; 32 | 33 | UPROPERTY(Category = "RuntimeMesh|Providers|Sphere", EditAnywhere) 34 | FVector LocationB; 35 | 36 | UPROPERTY(Category = "RuntimeMesh|Providers|Sphere", EditAnywhere) 37 | FVector LocationC; 38 | 39 | UPROPERTY(Category = "RuntimeMesh|Providers|Sphere", EditAnywhere) 40 | TArray VertsAB; 41 | 42 | UPROPERTY(Category = "RuntimeMesh|Providers|Sphere", EditAnywhere) 43 | TArray VertsAC; 44 | 45 | UPROPERTY(Category = "RuntimeMesh|Providers|Sphere", EditAnywhere) 46 | TArray ScreenSize; 47 | 48 | UPROPERTY(Category = "RuntimeMesh|Providers|Sphere", EditAnywhere) 49 | UMaterialInterface* Material; 50 | 51 | public: 52 | URuntimeMeshProviderPlane(); 53 | 54 | // FVector GetLocationA() const; 55 | // void SetLocationA(const FVector& InLocationA); 56 | // FVector GetLocationB() const; 57 | // void SetLocationB(const FVector& InLocationB); 58 | // FVector GetLocationC() const; 59 | // void SetLocationC(const FVector& InLocationC); 60 | 61 | 62 | 63 | protected: 64 | virtual void Initialize() override; 65 | virtual bool GetSectionMeshForLOD(int32 LODIndex, int32 SectionId, FRuntimeMeshRenderableMeshData& MeshData) override; 66 | virtual FRuntimeMeshCollisionSettings GetCollisionSettings() override; 67 | virtual FBoxSphereBounds GetBounds() override; 68 | virtual bool IsThreadSafe() override; 69 | 70 | private: 71 | 72 | int32 GetMaximumPossibleLOD(); 73 | }; 74 | -------------------------------------------------------------------------------- /Plugins/RuntimeMeshComponent/Source/RuntimeMeshComponent/Public/Providers/RuntimeMeshProviderSphere.h: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2020 TriAxis Games L.L.C. All Rights Reserved. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "RuntimeMeshProvider.h" 7 | #include "RuntimeMeshProviderSphere.generated.h" 8 | 9 | UCLASS(HideCategories = Object, BlueprintType) 10 | class RUNTIMEMESHCOMPONENT_API URuntimeMeshProviderSphere : public URuntimeMeshProvider 11 | { 12 | GENERATED_BODY() 13 | 14 | private: 15 | mutable FCriticalSection PropertySyncRoot; 16 | 17 | UPROPERTY() 18 | int32 MaxLOD; 19 | 20 | UPROPERTY(Category = "RuntimeMesh|Providers|Sphere", VisibleAnywhere, BlueprintGetter=GetSphereRadius, BlueprintSetter=SetSphereRadius) 21 | float SphereRadius; 22 | 23 | UPROPERTY(Category = "RuntimeMesh|Providers|Sphere", VisibleAnywhere, BlueprintGetter=GetMaxLatitudeSegments, BlueprintSetter=SetMaxLatitudeSegments) 24 | int32 MaxLatitudeSegments; 25 | 26 | UPROPERTY(Category = "RuntimeMesh|Providers|Sphere", VisibleAnywhere, BlueprintGetter=GetMinLatitudeSegments, BlueprintSetter=SetMinLatitudeSegments) 27 | int32 MinLatitudeSegments; 28 | 29 | UPROPERTY(Category = "RuntimeMesh|Providers|Sphere", VisibleAnywhere, BlueprintGetter=GetMaxLongitudeSegments, BlueprintSetter=SetMaxLongitudeSegments) 30 | int32 MaxLongitudeSegments; 31 | 32 | UPROPERTY(Category = "RuntimeMesh|Providers|Sphere", VisibleAnywhere, BlueprintGetter=GetMinLongitudeSegments, BlueprintSetter=SetMinLongitudeSegments) 33 | int32 MinLongitudeSegments; 34 | 35 | UPROPERTY(Category = "RuntimeMesh|Providers|Sphere", VisibleAnywhere, BlueprintGetter=GetLODMultiplier, BlueprintSetter=SetLODMultiplier) 36 | float LODMultiplier; 37 | 38 | UPROPERTY(Category = "RuntimeMesh|Providers|Sphere", VisibleAnywhere, BlueprintGetter=GetSphereMaterial, BlueprintSetter=SetSphereMaterial) 39 | UMaterialInterface* SphereMaterial; 40 | 41 | public: 42 | 43 | URuntimeMeshProviderSphere(); 44 | 45 | UFUNCTION(Category = "RuntimeMesh|Providers|Sphere", BlueprintCallable) 46 | float GetSphereRadius() const; 47 | UFUNCTION(Category = "RuntimeMesh|Providers|Sphere", BlueprintCallable) 48 | void SetSphereRadius(float InSphereRadius); 49 | 50 | UFUNCTION(Category = "RuntimeMesh|Providers|Sphere", BlueprintCallable) 51 | int32 GetMaxLatitudeSegments() const; 52 | UFUNCTION(Category = "RuntimeMesh|Providers|Sphere", BlueprintCallable) 53 | void SetMaxLatitudeSegments(int32 InMaxLatitudeSegments); 54 | 55 | UFUNCTION(Category = "RuntimeMesh|Providers|Sphere", BlueprintCallable) 56 | int32 GetMinLatitudeSegments() const; 57 | UFUNCTION(Category = "RuntimeMesh|Providers|Sphere", BlueprintCallable) 58 | void SetMinLatitudeSegments(int32 InMinLatitudeSegments); 59 | 60 | UFUNCTION(Category = "RuntimeMesh|Providers|Sphere", BlueprintCallable) 61 | int32 GetMaxLongitudeSegments() const; 62 | UFUNCTION(Category = "RuntimeMesh|Providers|Sphere", BlueprintCallable) 63 | void SetMaxLongitudeSegments(int32 InMaxLongitudeSegments); 64 | 65 | UFUNCTION(Category = "RuntimeMesh|Providers|Sphere", BlueprintCallable) 66 | int32 GetMinLongitudeSegments() const; 67 | UFUNCTION(Category = "RuntimeMesh|Providers|Sphere", BlueprintCallable) 68 | void SetMinLongitudeSegments(int32 InMinLongitudeSegments); 69 | 70 | UFUNCTION(Category = "RuntimeMesh|Providers|Sphere", BlueprintCallable) 71 | float GetLODMultiplier() const; 72 | UFUNCTION(Category = "RuntimeMesh|Providers|Sphere", BlueprintCallable) 73 | void SetLODMultiplier(float InLODMultiplier); 74 | 75 | UFUNCTION(Category = "RuntimeMesh|Providers|Sphere", BlueprintCallable) 76 | UMaterialInterface* GetSphereMaterial() const; 77 | UFUNCTION(Category = "RuntimeMesh|Providers|Sphere", BlueprintCallable) 78 | void SetSphereMaterial(UMaterialInterface* InSphereMaterial); 79 | 80 | 81 | 82 | protected: 83 | virtual void Initialize() override; 84 | virtual bool GetSectionMeshForLOD(int32 LODIndex, int32 SectionId, FRuntimeMeshRenderableMeshData& MeshData) override; 85 | virtual FRuntimeMeshCollisionSettings GetCollisionSettings() override; 86 | virtual FBoxSphereBounds GetBounds() override; 87 | virtual bool IsThreadSafe() override; 88 | 89 | 90 | private: 91 | void GetShapeParams(float& OutRadius, int32& OutMinLatitudeSegments, int32& OutMaxLatitudeSegments, int32& OutMinLongitudeSegments, int32& OutMaxLongitudeSegments, float& OutLODMultiplier); 92 | int32 GetMaxNumberOfLODs(); 93 | float CalculateScreenSize(int32 LODIndex); 94 | void GetSegmentsForLOD(int32& LODIndex, int32& LatitudeSegments, int32& LongitudeSegments) 95 | { 96 | GetSegmentsForLOD(LODIndex, LODMultiplier, MaxLatitudeSegments, MinLatitudeSegments, MaxLongitudeSegments, MinLongitudeSegments, LatitudeSegments, LongitudeSegments); 97 | } 98 | static void GetSegmentsForLOD(int32& LODIndex, float& LODMul, int32& MaxLat, int32& MinLat, int32& MaxLon, int32& MinLon, int32& LatitudeSegments, int32& LongitudeSegments){ 99 | LatitudeSegments = FMath::Max(FMath::RoundToInt(MaxLat * FMath::Pow(LODMul, LODIndex)), MinLat); 100 | LongitudeSegments = FMath::Max(FMath::RoundToInt(MaxLon * FMath::Pow(LODMul, LODIndex)), MinLon); 101 | } 102 | static bool GetSphereMesh(int32 SphereRadius, int32 LatitudeSegments, int32 LongitudeSegments, FRuntimeMeshRenderableMeshData& MeshData); 103 | void UpdateMeshParameters(bool bAffectsCollision); 104 | }; 105 | -------------------------------------------------------------------------------- /Plugins/RuntimeMeshComponent/Source/RuntimeMeshComponent/Public/Providers/RuntimeMeshProviderStaticMesh.h: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2020 TriAxis Games L.L.C. All Rights Reserved. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "RuntimeMeshProvider.h" 7 | #include "RuntimeMeshStaticMeshConverter.h" 8 | #include "RuntimeMeshProviderStaticMesh.generated.h" 9 | 10 | /** 11 | * 12 | */ 13 | UCLASS() 14 | class RUNTIMEMESHCOMPONENT_API URuntimeMeshProviderStaticMesh : public URuntimeMeshProvider 15 | { 16 | GENERATED_BODY() 17 | 18 | private: 19 | UPROPERTY(Category = "RuntimeMesh|Providers|StaticMesh", VisibleAnywhere, BlueprintGetter=GetStaticMesh, BlueprintSetter=SetStaticMesh) 20 | UStaticMesh* StaticMesh; 21 | 22 | UPROPERTY(Category = "RuntimeMesh|Providers|StaticMesh", VisibleAnywhere, BlueprintGetter=GetMaxLOD, BlueprintSetter=SetMaxLOD) 23 | int32 MaxLOD; 24 | 25 | UPROPERTY(Category = "RuntimeMesh|Providers|StaticMesh", VisibleAnywhere, BlueprintGetter=GetComplexCollisionLOD, BlueprintSetter=SetComplexCollisionLOD) 26 | int32 ComplexCollisionLOD; 27 | 28 | public: 29 | URuntimeMeshProviderStaticMesh(); 30 | 31 | UFUNCTION(Category = "RuntimeMesh|Providers|StaticMesh", BlueprintCallable) 32 | UStaticMesh* GetStaticMesh() const; 33 | 34 | UFUNCTION(Category = "RuntimeMesh|Providers|StaticMesh", BlueprintCallable) 35 | void SetStaticMesh(UStaticMesh* InStaticMesh); 36 | 37 | UFUNCTION(Category = "RuntimeMesh|Providers|StaticMesh", BlueprintCallable) 38 | int32 GetMaxLOD() const; 39 | 40 | UFUNCTION(Category = "RuntimeMesh|Providers|StaticMesh", BlueprintCallable) 41 | void SetMaxLOD(int32 InMaxLOD); 42 | 43 | UFUNCTION(Category = "RuntimeMesh|Providers|StaticMesh", BlueprintCallable) 44 | int32 GetComplexCollisionLOD() const; 45 | 46 | UFUNCTION(Category = "RuntimeMesh|Providers|StaticMesh", BlueprintCallable) 47 | void SetComplexCollisionLOD(int32 InLOD); 48 | 49 | 50 | protected: 51 | virtual void Initialize() override; 52 | virtual FBoxSphereBounds GetBounds() override; 53 | virtual bool GetSectionMeshForLOD(int32 LODIndex, int32 SectionId, FRuntimeMeshRenderableMeshData& MeshData) override; 54 | virtual FRuntimeMeshCollisionSettings GetCollisionSettings() override; 55 | virtual bool HasCollisionMesh() override; 56 | virtual bool GetCollisionMesh(FRuntimeMeshCollisionData& CollisionData) override; 57 | 58 | void UpdateCollisionFromStaticMesh(); 59 | void UpdateRenderingFromStaticMesh(); 60 | }; 61 | -------------------------------------------------------------------------------- /Plugins/RuntimeMeshComponent/Source/RuntimeMeshComponent/Public/RuntimeMeshActor.h: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2020 TriAxis Games L.L.C. All Rights Reserved. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "GameFramework/Actor.h" 7 | #include "RuntimeMeshComponent.h" 8 | #include "RuntimeMeshActor.generated.h" 9 | 10 | UCLASS(HideCategories = (Input), ShowCategories = ("Input|MouseInput", "Input|TouchInput"), ComponentWrapperClass, Meta = (ChildCanTick)) 11 | class RUNTIMEMESHCOMPONENT_API ARuntimeMeshActor : public AActor 12 | { 13 | GENERATED_UCLASS_BODY() 14 | 15 | private: 16 | UPROPERTY(Category = "RuntimeMeshActor", VisibleAnywhere, BlueprintReadOnly, Meta = (ExposeFunctionCategories = "Mesh,Rendering,Physics,Components|RuntimeMesh", AllowPrivateAccess = "true")) 17 | class URuntimeMeshComponent* RuntimeMeshComponent; 18 | 19 | public: 20 | 21 | UFUNCTION(BlueprintCallable, Category = "RuntimeMeshActor", Meta = (DisplayName = "Get Mobility")) 22 | ERuntimeMeshMobility GetRuntimeMeshMobility(); 23 | 24 | UFUNCTION(BlueprintCallable, Category = "RuntimeMeshActor", Meta = (DisplayName = "Set Mobility")) 25 | void SetRuntimeMeshMobility(ERuntimeMeshMobility NewMobility); 26 | 27 | public: 28 | 29 | /** Function to change mobility type */ 30 | void SetMobility(EComponentMobility::Type InMobility); 31 | EComponentMobility::Type GetMobility(); 32 | 33 | /** Returns RuntimeMeshComponent subobject **/ 34 | UFUNCTION(BlueprintCallable, Category = "RuntimeMeshActor", Meta = (DisplayName = "Get Runtime Mesh Component")) 35 | class URuntimeMeshComponent* GetRuntimeMeshComponent() const { return RuntimeMeshComponent; } 36 | 37 | 38 | }; 39 | -------------------------------------------------------------------------------- /Plugins/RuntimeMeshComponent/Source/RuntimeMeshComponent/Public/RuntimeMeshComponent.h: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2020 TriAxis Games L.L.C. All Rights Reserved. 2 | 3 | #pragma once 4 | 5 | #include "Components/MeshComponent.h" 6 | #include "RuntimeMeshCore.h" 7 | #include "PhysicsEngine/ConvexElem.h" 8 | #include "RuntimeMesh.h" 9 | #include "Interfaces/Interface_CollisionDataProvider.h" 10 | #include "RuntimeMeshComponent.generated.h" 11 | 12 | 13 | /** 14 | * Component that allows you to specify custom triangle mesh geometry for rendering and collision. 15 | */ 16 | UCLASS(ClassGroup=(Rendering, Common), HideCategories=(Object, Activation, "Components|Activation"), ShowCategories=(Mobility), Meta = (BlueprintSpawnableComponent)) 17 | class RUNTIMEMESHCOMPONENT_API URuntimeMeshComponent : public UMeshComponent, public IInterface_CollisionDataProvider 18 | { 19 | GENERATED_BODY() 20 | 21 | private: 22 | 23 | UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = RuntimeMesh, Meta = (AllowPrivateAccess = "true", DisplayName = "Runtime Mesh")) 24 | URuntimeMesh* RuntimeMeshReference; 25 | 26 | void EnsureHasRuntimeMesh(); 27 | 28 | 29 | 30 | public: 31 | URuntimeMeshComponent(); 32 | 33 | uint32 GetRuntimeMeshId() const { return RuntimeMeshReference? RuntimeMeshReference->GetMeshId() : -1; } 34 | 35 | UFUNCTION(BlueprintCallable, Category = "Components|RuntimeMeshComponent") 36 | void Initialize(URuntimeMeshProvider* Provider) 37 | { 38 | GetOrCreateRuntimeMesh()->Initialize(Provider); 39 | } 40 | 41 | UFUNCTION(BlueprintCallable, Category = "Components|RuntimeMeshComponent") 42 | void SetRuntimeMesh(URuntimeMesh* NewMesh); 43 | 44 | /** Clears the geometry for ALL collision only sections */ 45 | UFUNCTION(BlueprintCallable, Category = "Components|RuntimeMeshComponent") 46 | FORCEINLINE URuntimeMesh* GetRuntimeMesh() const 47 | { 48 | if (RuntimeMeshReference && RuntimeMeshReference->IsValidLowLevel()) 49 | { 50 | return RuntimeMeshReference; 51 | } 52 | return nullptr; 53 | } 54 | 55 | /** Clears the geometry for ALL collision only sections */ 56 | UFUNCTION(BlueprintCallable, Category = "Components|RuntimeMeshComponent") 57 | FORCEINLINE URuntimeMesh* GetOrCreateRuntimeMesh() 58 | { 59 | EnsureHasRuntimeMesh(); 60 | 61 | return RuntimeMeshReference; 62 | } 63 | 64 | 65 | 66 | UFUNCTION(BlueprintCallable, Category = "Components|RuntimeMeshComponent", Meta = (AllowPrivateAccess = "true", DisplayName = "Get Mobility")) 67 | ERuntimeMeshMobility GetRuntimeMeshMobility() 68 | { 69 | return Mobility == EComponentMobility::Movable ? ERuntimeMeshMobility::Movable : 70 | Mobility == EComponentMobility::Stationary ? ERuntimeMeshMobility::Stationary : ERuntimeMeshMobility::Static; 71 | } 72 | 73 | UFUNCTION(BlueprintCallable, Category = "Components|RuntimeMeshComponent", Meta = (AllowPrivateAccess = "true", DisplayName = "Set Mobility")) 74 | void SetRuntimeMeshMobility(ERuntimeMeshMobility NewMobility) 75 | { 76 | Super::SetMobility( 77 | NewMobility == ERuntimeMeshMobility::Movable ? EComponentMobility::Movable : 78 | NewMobility == ERuntimeMeshMobility::Stationary ? EComponentMobility::Stationary : EComponentMobility::Static); 79 | } 80 | 81 | 82 | 83 | 84 | UFUNCTION(BlueprintCallable, Category = "Components|RuntimeMeshComponent") 85 | URuntimeMeshProvider* GetProvider() { return GetRuntimeMesh()? GetRuntimeMesh()->GetProviderPtr() : nullptr; } 86 | 87 | UFUNCTION(BlueprintCallable, Category = "Components|RuntimeMeshComponent") 88 | TArray GetMaterialSlots() const 89 | { 90 | return GetRuntimeMesh()? GetRuntimeMesh()->GetMaterialSlots() : TArray(); 91 | } 92 | 93 | UFUNCTION(BlueprintCallable, Category = "Components|RuntimeMeshComponent") 94 | void SetupMaterialSlot(int32 MaterialSlot, FName SlotName, UMaterialInterface* InMaterial) 95 | { 96 | URuntimeMesh* Mesh = GetRuntimeMesh(); 97 | if (Mesh) 98 | { 99 | Mesh->SetupMaterialSlot(MaterialSlot, SlotName, InMaterial); 100 | } 101 | } 102 | 103 | 104 | 105 | UFUNCTION(BlueprintCallable, Category = "Components|RuntimeMeshComponent") 106 | FRuntimeMeshCollisionHitInfo GetHitSource(int32 FaceIndex) const; 107 | 108 | 109 | 110 | private: 111 | 112 | //~ Begin USceneComponent Interface. 113 | virtual FBoxSphereBounds CalcBounds(const FTransform& LocalToWorld) const override; 114 | virtual bool IsSupportedForNetworking() const override 115 | { 116 | return true; 117 | } 118 | //~ Begin USceneComponent Interface. 119 | 120 | //~ Begin UPrimitiveComponent Interface. 121 | virtual FPrimitiveSceneProxy* CreateSceneProxy() override; 122 | virtual class UBodySetup* GetBodySetup() override; 123 | //~ End UPrimitiveComponent Interface. 124 | public: 125 | 126 | //~ Begin UMeshComponent Interface 127 | virtual int32 GetMaterialIndex(FName MaterialSlotName) const; 128 | virtual TArray GetMaterialSlotNames() const; 129 | virtual bool IsMaterialSlotNameValid(FName MaterialSlotName) const; 130 | virtual void GetUsedMaterials(TArray& OutMaterials, bool bGetDebugMaterials = false) const override; 131 | //~ End UMeshComponent Interface 132 | 133 | //~ Being UPrimitiveComponent Interface 134 | virtual int32 GetNumMaterials() const override; 135 | virtual UMaterialInterface* GetMaterial(int32 ElementIndex) const override; 136 | //~ End UPrimitiveComponent Interface 137 | 138 | protected: 139 | virtual void PostLoad() override; 140 | 141 | virtual void BeginDestroy() override; 142 | 143 | virtual void OnRegister() override; 144 | virtual void OnUnregister() override; 145 | 146 | private: 147 | 148 | 149 | /** Called by URuntimeMesh any time it has new collision data that we should use */ 150 | void NewCollisionMeshReceived(); 151 | void NewBoundsReceived(); 152 | void ForceProxyRecreate(); 153 | 154 | 155 | 156 | friend class URuntimeMesh; 157 | friend class FRuntimeMeshComponentSceneProxy; 158 | }; 159 | -------------------------------------------------------------------------------- /Plugins/RuntimeMeshComponent/Source/RuntimeMeshComponent/Public/RuntimeMeshComponentEngineSubsystem.h: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2020 TriAxis Games L.L.C. All Rights Reserved. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "Subsystems/EngineSubsystem.h" 7 | #include "RuntimeMeshCore.h" 8 | #include "HAL/Runnable.h" 9 | #include "HAL/RunnableThread.h" 10 | #include "HAL/ThreadSafeBool.h" 11 | #include "Tickable.h" 12 | #include "RuntimeMeshReference.h" 13 | #include "RuntimeMeshComponentEngineSubsystem.generated.h" 14 | 15 | class URuntimeMeshComponentSettings; 16 | class URuntimeMesh; 17 | 18 | /** 19 | * 20 | */ 21 | UCLASS() 22 | class RUNTIMEMESHCOMPONENT_API URuntimeMeshComponentEngineSubsystem : public UEngineSubsystem 23 | { 24 | GENERATED_BODY() 25 | private: 26 | 27 | struct FRuntimeMeshComponentDelayedActionTickObject : FTickableGameObject 28 | { 29 | URuntimeMeshComponentEngineSubsystem* ParentSubsystem; 30 | public: 31 | FRuntimeMeshComponentDelayedActionTickObject(URuntimeMeshComponentEngineSubsystem* InParent) 32 | : ParentSubsystem(InParent) 33 | {} 34 | 35 | virtual void Tick(float DeltaTime); 36 | virtual bool IsTickable() const; 37 | virtual bool IsTickableInEditor() const { return true; } 38 | virtual TStatId GetStatId() const { return TStatId(); } 39 | }; 40 | 41 | 42 | TUniquePtr TickObject; 43 | TQueue MeshesToUpdate; 44 | FQueuedThreadPool* ThreadPool; 45 | public: 46 | void Initialize(FSubsystemCollectionBase& Collection) override; 47 | 48 | void Deinitialize() override; 49 | 50 | FQueuedThreadPool* GetThreadPool() { return ThreadPool; } 51 | private: 52 | void QueueMeshForUpdate(const FRuntimeMeshWeakRef& InMesh); 53 | 54 | int32 CalculateNumThreads(const URuntimeMeshComponentSettings* Settings); 55 | void InitializeThreads(int32 NumThreads, int32 StackSize = 0, EThreadPriority ThreadPriority = TPri_BelowNormal); 56 | 57 | EThreadPriority ConvertThreadPriority(ERuntimeMeshThreadingPriority InPriority); 58 | 59 | bool IsTickable() const; 60 | void Tick(float DeltaTime); 61 | 62 | friend class URuntimeMesh; 63 | }; 64 | -------------------------------------------------------------------------------- /Plugins/RuntimeMeshComponent/Source/RuntimeMeshComponent/Public/RuntimeMeshComponentPlugin.h: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2020 TriAxis Games L.L.C. All Rights Reserved. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "Modules/ModuleManager.h" 7 | 8 | /** 9 | * The public interface to this module 10 | */ 11 | class IRuntimeMeshComponentPlugin : public IModuleInterface 12 | { 13 | 14 | public: 15 | 16 | /** 17 | * Singleton-like access to this module's interface. This is just for convenience! 18 | * Beware of calling this during the shutdown phase, though. Your module might have been unloaded already. 19 | * 20 | * @return Returns singleton instance, loading the module on demand if needed 21 | */ 22 | static inline IRuntimeMeshComponentPlugin& Get() 23 | { 24 | return FModuleManager::LoadModuleChecked("RuntimeMeshComponent"); 25 | } 26 | 27 | /** 28 | * Checks to see if this module is loaded and ready. It is only valid to call Get() if IsAvailable() returns true. 29 | * 30 | * @return True if the module is loaded and ready to use 31 | */ 32 | static inline bool IsAvailable() 33 | { 34 | return FModuleManager::Get().IsModuleLoaded("RuntimeMeshComponent"); 35 | } 36 | }; 37 | 38 | DECLARE_LOG_CATEGORY_EXTERN(RuntimeMeshLog, Warning, All); 39 | -------------------------------------------------------------------------------- /Plugins/RuntimeMeshComponent/Source/RuntimeMeshComponent/Public/RuntimeMeshComponentSettings.h: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2020 TriAxis Games L.L.C. All Rights Reserved. 2 | 3 | #pragma once 4 | 5 | #include "Engine/DeveloperSettings.h" 6 | #include "RuntimeMeshCore.h" 7 | #include "RuntimeMeshComponentSettings.generated.h" 8 | 9 | 10 | 11 | /** 12 | * Settings for Runtime Mesh Component 13 | */ 14 | UCLASS(Config = RuntimeMeshComponent, DefaultConfig, Meta = (DisplayName = "Runtime Mesh Component")) 15 | class RUNTIMEMESHCOMPONENT_API URuntimeMeshComponentSettings : public UDeveloperSettings 16 | { 17 | GENERATED_UCLASS_BODY() 18 | 19 | public: 20 | UPROPERTY(Config, EditAnywhere, Category = MeshData) 21 | ERuntimeMeshUpdateFrequency DefaultUpdateFrequency; 22 | 23 | UPROPERTY(Config, EditAnywhere, Category = MeshData) 24 | bool bUse32BitIndicesByDefault; 25 | 26 | UPROPERTY(Config, EditAnywhere, Category = MeshData) 27 | bool bUseHighPrecisionTexCoordsByDefault; 28 | 29 | UPROPERTY(Config, EditAnywhere, Category = MeshData) 30 | bool bUseHighPrecisionTangentsByDefault; 31 | 32 | 33 | 34 | UPROPERTY(Config, EditAnywhere, Category = Collision) 35 | bool bCookCollisionAsync; 36 | 37 | UPROPERTY(Config, EditAnywhere, Category = Collision) 38 | ERuntimeMeshCollisionCookingMode DefaultCookingMode; 39 | 40 | 41 | 42 | UPROPERTY(Config, EditAnywhere, Category = Threading, Meta = (ClampMin=1, ClampMax = 32)) 43 | FInt32Range MinMaxThreadPoolThreads; 44 | 45 | UPROPERTY(Config, EditAnywhere, Category = Threading, Meta = (ClampMin=1, ClampMax = 8)) 46 | int32 SystemThreadDivisor; 47 | 48 | UPROPERTY(Config, EditAnywhere, Category = Threading) 49 | ERuntimeMeshThreadingPriority ThreadPriority; 50 | 51 | UPROPERTY(Config, EditAnywhere, Category = Threading) 52 | int32 ThreadStackSize; 53 | 54 | UPROPERTY(Config, EditAnywhere, Category = Threading) 55 | float MaxAllowedTimePerTick; 56 | 57 | 58 | 59 | 60 | FName GetCategoryName() const override; 61 | 62 | #if WITH_EDITOR 63 | FText GetSectionText() const override; 64 | virtual void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override; 65 | 66 | 67 | DECLARE_MULTICAST_DELEGATE_TwoParams(FOnRuntimeMeshComponentSettingsChanged, const FString&, const URuntimeMeshComponentSettings*); 68 | 69 | static FOnRuntimeMeshComponentSettingsChanged& OnSettingsChanged(); 70 | protected: 71 | static FOnRuntimeMeshComponentSettingsChanged SettingsChangedDelegate; 72 | #endif 73 | 74 | }; 75 | -------------------------------------------------------------------------------- /Plugins/RuntimeMeshComponent/Source/RuntimeMeshComponent/Public/RuntimeMeshModifier.h: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2020 TriAxis Games L.L.C. All Rights Reserved. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "UObject/NoExportTypes.h" 7 | #include "RuntimeMeshReference.h" 8 | #include "RuntimeMeshRenderable.h" 9 | #include "RuntimeMeshCollision.h" 10 | #include "RuntimeMeshModifier.generated.h" 11 | 12 | 13 | UCLASS(HideCategories = Object, BlueprintType, Blueprintable, Meta = (ShortTooltip = "A RuntimeMeshModifier is a class containing logic to modify a mesh data passed to it in some way. This can range from optimizers, to additional data generators.")) 14 | class RUNTIMEMESHCOMPONENT_API URuntimeMeshModifier : public UObject 15 | { 16 | GENERATED_BODY() 17 | public: 18 | URuntimeMeshModifier(); 19 | 20 | UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category="RuntimeMeshModifier") 21 | void ApplyToMesh(FRuntimeMeshRenderableMeshData& MeshData); 22 | 23 | UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "RuntimeMeshModifier") 24 | void ApplyToCollisionMesh(FRuntimeMeshCollisionData& MeshData); 25 | 26 | }; 27 | -------------------------------------------------------------------------------- /Plugins/RuntimeMeshComponent/Source/RuntimeMeshComponent/Public/RuntimeMeshProvider.h: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2020 TriAxis Games L.L.C. All Rights Reserved. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "RuntimeMeshProviderTargetInterface.h" 7 | #include "RuntimeMeshReference.h" 8 | #include "RuntimeMeshProvider.generated.h" 9 | 10 | 11 | 12 | UCLASS(HideCategories = Object, BlueprintType, Meta = (ShortTooltip = "A RuntimeMeshProvider is a class containing the logic to create the mesh data and related information to be used by a RuntimeMeshComponent for rendering.")) 13 | class RUNTIMEMESHCOMPONENT_API URuntimeMeshProvider : public URuntimeMeshProviderTargetInterface 14 | { 15 | GENERATED_BODY() 16 | protected: 17 | 18 | FRuntimeMeshReferenceAnchor GCAnchor; 19 | 20 | URuntimeMeshProviderTargetInterface* Target; 21 | mutable FRWLock TargetLock; 22 | FThreadSafeBool bIsBound; 23 | 24 | public: 25 | UFUNCTION(BlueprintCallable, Category = "RuntimeMeshProvider|ConfigureLODs") 26 | bool IsBound() const { check(bIsBound == (Target != nullptr)); return bIsBound; } 27 | 28 | UFUNCTION(BlueprintCallable, Category = "RuntimeMeshProvider|ConfigureLODs") 29 | void Shutdown(); 30 | 31 | virtual void BindTargetProvider(URuntimeMeshProviderTargetInterface* InTarget); 32 | virtual void UnlinkProviders() override; 33 | 34 | 35 | public: 36 | URuntimeMeshProvider(); 37 | 38 | UFUNCTION(BlueprintCallable, Category = "RuntimeMeshProvider|ConfigureLODs") 39 | virtual void Initialize() { } 40 | 41 | UFUNCTION(BlueprintCallable, Category = "RuntimeMeshProvider|ConfigureLODs") 42 | virtual FBoxSphereBounds GetBounds() { return FBoxSphereBounds(FSphere(FVector::ZeroVector, 1.0f)); } 43 | 44 | UFUNCTION(BlueprintCallable, Category = "RuntimeMeshProvider|ConfigureLODs") 45 | virtual bool GetSectionMeshForLOD(int32 LODIndex, int32 SectionId, FRuntimeMeshRenderableMeshData& MeshData) { return false; } 46 | 47 | UFUNCTION(BlueprintCallable, Category = "RuntimeMeshProvider|ConfigureLODs") 48 | virtual bool GetAllSectionsMeshForLOD(int32 LODIndex, TMap& MeshDatas) { return false; } 49 | 50 | UFUNCTION(BlueprintCallable, Category = "RuntimeMeshProvider|ConfigureLODs") 51 | virtual FRuntimeMeshCollisionSettings GetCollisionSettings() { return FRuntimeMeshCollisionSettings(); } 52 | 53 | UFUNCTION(BlueprintCallable, Category = "RuntimeMeshProvider|ConfigureLODs") 54 | virtual bool HasCollisionMesh() { return false; } 55 | 56 | UFUNCTION(BlueprintCallable, Category = "RuntimeMeshProvider|ConfigureLODs") 57 | virtual bool GetCollisionMesh(FRuntimeMeshCollisionData& CollisionData) { return false; } 58 | 59 | UFUNCTION(BlueprintCallable, Category = "RuntimeMeshProvider|ConfigureLODs") 60 | virtual void CollisionUpdateCompleted() { } 61 | 62 | 63 | UFUNCTION(BlueprintCallable, Category = "RuntimeMeshProvider|ConfigureLODs") 64 | virtual bool IsThreadSafe() { return false; } 65 | 66 | FRuntimeMeshProviderWeakRef GetReference(); 67 | 68 | // Begin IRuntimeMeshProviderTargetInterface interface 69 | virtual FRuntimeMeshWeakRef GetMeshReference() override; 70 | virtual void ConfigureLODs(const TArray& InLODs) override; 71 | virtual void SetLODScreenSize(int32 LODIndex, float ScreenSize) override; 72 | virtual void MarkLODDirty(int32 LODIndex) override; 73 | virtual void MarkAllLODsDirty() override; 74 | 75 | virtual void CreateSection(int32 LODIndex, int32 SectionId, const FRuntimeMeshSectionProperties& SectionProperties) override; 76 | virtual void SetSectionVisibility(int32 LODIndex, int32 SectionId, bool bIsVisible) override; 77 | virtual void SetSectionCastsShadow(int32 LODIndex, int32 SectionId, bool bCastsShadow) override; 78 | virtual void MarkSectionDirty(int32 LODIndex, int32 SectionId) override; 79 | virtual void ClearSection(int32 LODIndex, int32 SectionId) override; 80 | virtual void RemoveSection(int32 LODIndex, int32 SectionId) override; 81 | virtual void MarkCollisionDirty() override; 82 | 83 | 84 | virtual void SetupMaterialSlot(int32 MaterialSlot, FName SlotName, UMaterialInterface* InMaterial) override; 85 | virtual int32 GetMaterialIndex(FName MaterialSlotName) override; 86 | virtual bool IsMaterialSlotNameValid(FName MaterialSlotName) const override; 87 | virtual FRuntimeMeshMaterialSlot GetMaterialSlot(int32 SlotIndex) override; 88 | virtual int32 GetNumMaterials() override; 89 | virtual TArray GetMaterialSlotNames() override; 90 | virtual TArray GetMaterialSlots() override; 91 | virtual UMaterialInterface* GetMaterial(int32 SlotIndex) override; 92 | // End IRuntimeMeshProviderTargetInterface interface 93 | 94 | // Begin UObject interface 95 | void BeginDestroy() override; 96 | bool IsReadyForFinishDestroy() override; 97 | // End UObject interface 98 | protected: 99 | 100 | friend class URuntimeMesh; 101 | }; 102 | 103 | 104 | 105 | 106 | UCLASS(HideCategories = Object, BlueprintType, Meta = (ShortTooltip = "A RuntimeMeshProviderPassthrough is a class containing logic to modify the mesh data from a linked provider before passing it onto the RuntimeMeshComponent.")) 107 | class RUNTIMEMESHCOMPONENT_API URuntimeMeshProviderPassthrough 108 | : public URuntimeMeshProvider 109 | { 110 | GENERATED_BODY() 111 | private: 112 | UPROPERTY(VisibleAnywhere, BlueprintGetter = GetChildProvider, BlueprintSetter = SetChildProvider, Category = "RuntimeMesh|Providers") 113 | URuntimeMeshProvider* ChildProvider; 114 | 115 | mutable FRWLock ChildLock; 116 | public: 117 | 118 | virtual void BindTargetProvider(URuntimeMeshProviderTargetInterface* InTarget) override; 119 | virtual void UnlinkProviders() override; 120 | 121 | public: 122 | URuntimeMeshProviderPassthrough(); 123 | 124 | UFUNCTION(BlueprintCallable, Category = "RuntimeMesh|Providers") 125 | URuntimeMeshProvider* GetChildProvider() const 126 | { 127 | FReadScopeLock Lock(ChildLock); 128 | return ChildProvider; 129 | } 130 | 131 | UFUNCTION(BlueprintCallable, Category = "RuntimeMesh|Providers") 132 | void SetChildProvider(URuntimeMeshProvider* InProvider); 133 | 134 | virtual void Initialize() override; 135 | virtual FBoxSphereBounds GetBounds() override; 136 | virtual bool GetSectionMeshForLOD(int32 LODIndex, int32 SectionId, FRuntimeMeshRenderableMeshData& MeshData) override; 137 | virtual bool GetAllSectionsMeshForLOD(int32 LODIndex, TMap& MeshDatas) override; 138 | virtual FRuntimeMeshCollisionSettings GetCollisionSettings() override; 139 | virtual bool HasCollisionMesh() override; 140 | virtual bool GetCollisionMesh(FRuntimeMeshCollisionData& CollisionData) override; 141 | virtual void CollisionUpdateCompleted() override; 142 | 143 | 144 | virtual bool IsThreadSafe() override; 145 | 146 | }; -------------------------------------------------------------------------------- /Plugins/RuntimeMeshComponent/Source/RuntimeMeshComponent/Public/RuntimeMeshProviderTargetInterface.h: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2020 TriAxis Games L.L.C. All Rights Reserved. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "UObject/Interface.h" 7 | #include "RuntimeMeshRenderable.h" 8 | #include "RuntimeMeshCollision.h" 9 | #include "RuntimeMeshReference.h" 10 | #include "RuntimeMeshProviderTargetInterface.generated.h" 11 | 12 | class URuntimeMesh; 13 | 14 | UCLASS(BlueprintType, Blueprintable) 15 | class RUNTIMEMESHCOMPONENT_API URuntimeMeshProviderTargetInterface : public UObject 16 | { 17 | GENERATED_BODY() 18 | public: 19 | virtual FRuntimeMeshWeakRef GetMeshReference() { return FRuntimeMeshWeakRef(); }; 20 | 21 | //UFUNCTION(BlueprintCallable, BlueprintNativeEvent) 22 | virtual void UnlinkProviders() { } 23 | 24 | 25 | 26 | UFUNCTION(BlueprintCallable, Category="RuntimeMeshInterface|ConfigureLODs") 27 | virtual void ConfigureLODs(const TArray& InLODs) { } 28 | 29 | UFUNCTION(BlueprintCallable, Category = "RuntimeMeshInterface|ConfigureLODs") 30 | virtual void SetLODScreenSize(int32 LODIndex, float ScreenSize) { } 31 | 32 | UFUNCTION(BlueprintCallable, Category = "RuntimeMeshInterface|ConfigureLODs") 33 | virtual void MarkLODDirty(int32 LODIndex) { } 34 | 35 | UFUNCTION(BlueprintCallable, Category = "RuntimeMeshInterface|ConfigureLODs") 36 | virtual void MarkAllLODsDirty() { } 37 | 38 | 39 | UFUNCTION(BlueprintCallable, Category = "RuntimeMeshInterface|ConfigureLODs") 40 | virtual void CreateSection(int32 LODIndex, int32 SectionId, const FRuntimeMeshSectionProperties& SectionProperties) { } 41 | 42 | UFUNCTION(BlueprintCallable, Category = "RuntimeMeshInterface|ConfigureLODs") 43 | virtual void SetSectionVisibility(int32 LODIndex, int32 SectionId, bool bIsVisible) { } 44 | 45 | UFUNCTION(BlueprintCallable, Category = "RuntimeMeshInterface|ConfigureLODs") 46 | virtual void SetSectionCastsShadow(int32 LODIndex, int32 SectionId, bool bCastsShadow) { } 47 | 48 | UFUNCTION(BlueprintCallable, Category = "RuntimeMeshInterface|ConfigureLODs") 49 | virtual void MarkSectionDirty(int32 LODIndex, int32 SectionId) { } 50 | 51 | UFUNCTION(BlueprintCallable, Category = "RuntimeMeshInterface|ConfigureLODs") 52 | virtual void ClearSection(int32 LODIndex, int32 SectionId) { } 53 | 54 | UFUNCTION(BlueprintCallable, Category = "RuntimeMeshInterface|ConfigureLODs") 55 | virtual void RemoveSection(int32 LODIndex, int32 SectionId) { } 56 | 57 | UFUNCTION(BlueprintCallable, Category = "RuntimeMeshInterface|ConfigureLODs") 58 | virtual void MarkCollisionDirty() { } 59 | 60 | 61 | UFUNCTION(BlueprintCallable, Category = "RuntimeMeshInterface|ConfigureLODs") 62 | virtual void SetupMaterialSlot(int32 MaterialSlot, FName SlotName, UMaterialInterface* InMaterial) { } 63 | 64 | UFUNCTION(BlueprintCallable, Category = "RuntimeMeshInterface|ConfigureLODs") 65 | virtual int32 GetMaterialIndex(FName MaterialSlotName) { return INDEX_NONE; } 66 | 67 | UFUNCTION(BlueprintCallable, Category = "RuntimeMeshInterface|ConfigureLODs") 68 | virtual bool IsMaterialSlotNameValid(FName MaterialSlotName) const { return false; } 69 | 70 | UFUNCTION(BlueprintCallable, Category = "RuntimeMeshInterface|ConfigureLODs") 71 | virtual FRuntimeMeshMaterialSlot GetMaterialSlot(int32 SlotIndex) { return FRuntimeMeshMaterialSlot(); } 72 | 73 | UFUNCTION(BlueprintCallable, Category = "RuntimeMeshInterface|ConfigureLODs") 74 | virtual int32 GetNumMaterials() { return 0; } 75 | 76 | UFUNCTION(BlueprintCallable, Category = "RuntimeMeshInterface|ConfigureLODs") 77 | virtual TArray GetMaterialSlotNames() { return TArray(); } 78 | 79 | UFUNCTION(BlueprintCallable, Category = "RuntimeMeshInterface|ConfigureLODs") 80 | virtual TArray GetMaterialSlots() { return TArray(); } 81 | 82 | UFUNCTION(BlueprintCallable, Category = "RuntimeMeshInterface|ConfigureLODs") 83 | virtual UMaterialInterface* GetMaterial(int32 SlotIndex) { return nullptr; } 84 | }; 85 | -------------------------------------------------------------------------------- /Plugins/RuntimeMeshComponent/Source/RuntimeMeshComponent/Public/RuntimeMeshSlicer.h: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2020 TriAxis Games L.L.C. All Rights Reserved. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "Kismet/BlueprintFunctionLibrary.h" 7 | #include "RuntimeMeshRenderable.h" 8 | #include "RuntimeMeshSlicer.generated.h" 9 | 10 | /** Options for creating cap geometry when slicing */ 11 | UENUM() 12 | enum class ERuntimeMeshSliceCapOption : uint8 13 | { 14 | /** Do not create cap geometry */ 15 | NoCap, 16 | /** Add a new section to RuntimeMesh for cap */ 17 | CreateNewSectionForCap, 18 | /** Add cap geometry to existing last section */ 19 | UseLastSectionForCap 20 | }; 21 | 22 | 23 | UCLASS() 24 | class RUNTIMEMESHCOMPONENT_API URuntimeMeshSlicer : public UBlueprintFunctionLibrary 25 | { 26 | GENERATED_BODY() 27 | 28 | public: 29 | 30 | /** 31 | * Slice the RuntimeMeshComponent (including simple convex collision) using a plane. Optionally create 'cap' geometry. 32 | * @param InRuntimeMesh RuntimeMeshComponent to slice 33 | * @param PlanePosition Point on the plane to use for slicing, in world space 34 | * @param PlaneNormal Normal of plane used for slicing. Geometry on the positive side of the plane will be kept. 35 | * @param bCreateOtherHalf If true, an additional RuntimeMeshComponent (OutOtherHalfRuntimeMesh) will be created using the other half of the sliced geometry 36 | * @param OutOtherHalfRuntimeMesh If bCreateOtherHalf is set, this is the new component created. Its owner will be the same as the supplied InRuntimeMesh. 37 | * @param CapOption If and how to create 'cap' geometry on the slicing plane 38 | * @param CapMaterial If creating a new section for the cap, assign this material to that section 39 | */ 40 | UFUNCTION(BlueprintCallable, Category = "Components|RuntimeMesh") 41 | static void SliceRuntimeMesh(URuntimeMeshComponent* InRuntimeMesh, FVector PlanePosition, FVector PlaneNormal, bool bCreateOtherHalf, 42 | URuntimeMeshComponent*& OutOtherHalfRuntimeMesh, ERuntimeMeshSliceCapOption CapOption, UMaterialInterface* CapMaterial); 43 | 44 | 45 | /** 46 | * Slice the RuntimeMeshData using a plane. Optionally create 'cap' geometry. 47 | * @param SourceSection RuntimeMeshData to slice 48 | * @param PlanePosition Point on the plane to use for slicing, in world space 49 | * @param PlaneNormal Normal of plane used for slicing. Geometry on the positive side of the plane will be kept. 50 | * @param CapOption If and how to create 'cap' geometry on the slicing plane 51 | * @param NewSourceSection Resulting mesh data for origin section 52 | * @param DestinationSection Mesh data sliced from source 53 | */ 54 | UFUNCTION(BlueprintCallable, Category = "Components|RuntimeMesh") 55 | static bool SliceRuntimeMeshData(FRuntimeMeshRenderableMeshData& SourceSection, const FPlane& SlicePlane, ERuntimeMeshSliceCapOption CapOption, FRuntimeMeshRenderableMeshData& NewSourceSection, 56 | FRuntimeMeshRenderableMeshData& NewSourceSectionCap, bool bCreateDestination, FRuntimeMeshRenderableMeshData& DestinationSection, FRuntimeMeshRenderableMeshData& NewDestinationSectionCap); 57 | }; 58 | -------------------------------------------------------------------------------- /Plugins/RuntimeMeshComponent/Source/RuntimeMeshComponent/Public/RuntimeMeshStaticMeshConverter.h: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2020 TriAxis Games L.L.C. All Rights Reserved. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "Kismet/BlueprintFunctionLibrary.h" 7 | #include "RuntimeMeshRenderable.h" 8 | #include "RuntimeMeshCollision.h" 9 | #include "StaticMeshResources.h" 10 | #include "RuntimeMeshStaticMeshConverter.generated.h" 11 | 12 | /** 13 | * 14 | */ 15 | UCLASS() 16 | class RUNTIMEMESHCOMPONENT_API URuntimeMeshStaticMeshConverter : public UBlueprintFunctionLibrary 17 | { 18 | GENERATED_BODY() 19 | 20 | private: 21 | static int32 CopyVertexOrGetIndex(const FStaticMeshLODResources& LOD, const FStaticMeshSection& Section, TMap& MeshToSectionVertexMap, int32 VertexIndex, FRuntimeMeshRenderableMeshData& NewMeshData); 22 | 23 | static int32 CopyVertexOrGetIndex(const FStaticMeshLODResources& LOD, const FStaticMeshSection& Section, TMap& MeshToSectionVertexMap, int32 VertexIndex, int32 NumUVChannels, FRuntimeMeshCollisionData& NewMeshData); 24 | 25 | public: 26 | UFUNCTION(BlueprintCallable, Category = "RuntimeMesh|StaticMeshConversion") 27 | static bool CopyStaticMeshSectionToRenderableMeshData(UStaticMesh* StaticMesh, int32 LODIndex, int32 SectionId, FRuntimeMeshRenderableMeshData& OutMeshData); 28 | 29 | UFUNCTION(BlueprintCallable, Category = "RuntimeMesh|StaticMeshConversion") 30 | static bool CopyStaticMeshCollisionToCollisionSettings(UStaticMesh* StaticMesh, FRuntimeMeshCollisionSettings& OutCollisionSettings); 31 | 32 | UFUNCTION(BlueprintCallable, Category = "RuntimeMesh|StaticMeshConversion") 33 | static bool CopyStaticMeshLODToCollisionData(UStaticMesh* StaticMesh, int32 LODIndex, FRuntimeMeshCollisionData& OutCollisionData); 34 | 35 | UFUNCTION(BlueprintCallable, Category = "RuntimeMesh|StaticMeshConversion") 36 | static bool CopyStaticMeshToRuntimeMesh(UStaticMesh* StaticMesh, URuntimeMeshComponent* RuntimeMeshComponent, int32 CollisionLODIndex = -1, int32 MaxLODToCopy = 8); 37 | 38 | UFUNCTION(BlueprintCallable, Category = "RuntimeMesh|StaticMeshConversion") 39 | static bool CopyStaticMeshComponentToRuntimeMesh(UStaticMeshComponent* StaticMeshComponent, URuntimeMeshComponent* RuntimeMeshComponent, int32 CollisionLODIndex = -1, int32 MaxLODToCopy = 8); 40 | }; 41 | -------------------------------------------------------------------------------- /Plugins/RuntimeMeshComponent/Source/RuntimeMeshComponent/RuntimeMeshComponent.Build.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2020 TriAxis Games L.L.C. All Rights Reserved. 2 | 3 | using System.IO; 4 | using UnrealBuildTool; 5 | 6 | public class RuntimeMeshComponent : ModuleRules 7 | { 8 | public RuntimeMeshComponent(ReadOnlyTargetRules rules) : base(rules) 9 | { 10 | bEnforceIWYU = true; 11 | bLegacyPublicIncludePaths = false; 12 | 13 | #if UE_4_23_OR_LATER 14 | PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; 15 | #endif 16 | 17 | #if UE_4_24_OR_LATER 18 | #else 19 | #endif 20 | 21 | // Setup the pro/community definitions 22 | PublicDefinitions.Add("RUNTIMEMESHCOMPONENT_PRO=0"); 23 | PublicDefinitions.Add("RUNTIMEMESHCOMPONENT_VERSION=TEXT(\"Community\")"); 24 | 25 | // This is to access RayTracing Definitions 26 | PrivateIncludePaths.Add(Path.Combine(EngineDirectory, "Shaders", "Shared")); 27 | 28 | PublicDependencyModuleNames.AddRange( 29 | new string[] 30 | { 31 | "Core", 32 | } 33 | ); 34 | 35 | PrivateDependencyModuleNames.AddRange( 36 | new string[] 37 | { 38 | "CoreUObject", 39 | "Engine", 40 | "RenderCore", 41 | "RHI", 42 | "NavigationSystem", 43 | #if UE_4_23_OR_LATER 44 | "PhysicsCore", 45 | #endif 46 | #if UE_4_26_OR_LATER 47 | "DeveloperSettings", 48 | #endif 49 | } 50 | ); 51 | } 52 | } -------------------------------------------------------------------------------- /Plugins/RuntimeMeshComponent/Source/RuntimeMeshComponentEditor/Private/RuntimeMeshComponentDetails.h: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2020 TriAxis Games L.L.C. All Rights Reserved. 2 | 3 | #pragma once 4 | #include "IDetailCustomization.h" 5 | #include "DetailLayoutBuilder.h" 6 | #include "RuntimeMesh.h" 7 | #include "Types/SlateEnums.h" 8 | 9 | class FRuntimeMeshComponentDetails : public IDetailCustomization 10 | { 11 | public: 12 | /** Makes a new instance of this detail layout class for a specific detail view requesting it */ 13 | static TSharedRef MakeInstance(); 14 | 15 | /** IDetailCustomization interface */ 16 | virtual void CustomizeDetails(IDetailLayoutBuilder& DetailBuilder) override; 17 | 18 | /** Handle clicking the convert button */ 19 | FReply ClickedOnConvertToStaticMesh(); 20 | 21 | /** Is the convert button enabled */ 22 | bool ConvertToStaticMeshEnabled() const; 23 | 24 | /** Util to get the RuntimeMeshComponent we want to convert */ 25 | class URuntimeMeshComponent* GetFirstSelectedRuntimeMeshComp() const; 26 | 27 | /** Cached array of selected objects */ 28 | TArray> SelectedObjectsList; 29 | TArray RuntimeMeshesReferenced; 30 | }; -------------------------------------------------------------------------------- /Plugins/RuntimeMeshComponent/Source/RuntimeMeshComponentEditor/Private/RuntimeMeshComponentEditorCommands.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2020 TriAxis Games L.L.C. All Rights Reserved. 2 | 3 | #include "RuntimeMeshComponentEditorCommands.h" 4 | 5 | #define LOCTEXT_NAMESPACE "FRuntimeMeshComponentEditorModule" 6 | 7 | void FRuntimeMeshComponentEditorCommands::RegisterCommands() 8 | { 9 | UI_COMMAND(DonateAction, "Donate to Support the RMC!", "Support the RMC by donating", EUserInterfaceActionType::Button, FInputGesture()); 10 | UI_COMMAND(HelpAction, "Help Documentation", "RMC Help Documentation", EUserInterfaceActionType::Button, FInputGesture()); 11 | UI_COMMAND(ForumsAction, "Forums", "RMC Forums", EUserInterfaceActionType::Button, FInputGesture()); 12 | UI_COMMAND(IssuesAction, "Issues", "RMC Issue Tracker", EUserInterfaceActionType::Button, FInputGesture()); 13 | UI_COMMAND(DiscordAction, "Discord Chat", "RMC Discord Chat", EUserInterfaceActionType::Button, FInputGesture()); 14 | UI_COMMAND(MarketplaceAction, "Marketplace Page", "RMC Marketplace Page", EUserInterfaceActionType::Button, FInputGesture()); 15 | } 16 | 17 | #undef LOCTEXT_NAMESPACE 18 | -------------------------------------------------------------------------------- /Plugins/RuntimeMeshComponent/Source/RuntimeMeshComponentEditor/Private/RuntimeMeshComponentEditorPlugin.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2020 TriAxis Games L.L.C. All Rights Reserved. 2 | 3 | #include "IRuntimeMeshComponentEditorPlugin.h" 4 | #include "PropertyEditorModule.h" 5 | #include "RuntimeMeshComponent.h" 6 | #include "RuntimeMeshComponentDetails.h" 7 | #include "RuntimeMeshComponentEditorStyle.h" 8 | #include "RuntimeMeshComponentEditorCommands.h" 9 | 10 | #include "Modules/ModuleManager.h" 11 | #include "LevelEditor.h" 12 | 13 | class FToolBarBuilder; 14 | class FMenuBuilder; 15 | 16 | #define LOCTEXT_NAMESPACE "FRuntimeMeshComponentEditorModule" 17 | 18 | class FRuntimeMeshComponentEditorPlugin : public IRuntimeMeshComponentEditorPlugin 19 | { 20 | public: 21 | /** IModuleInterface implementation */ 22 | virtual void StartupModule() override; 23 | virtual void ShutdownModule() override; 24 | 25 | /** This function will be bound to Command. */ 26 | void DonateActionClicked(); 27 | void HelpActionClicked(); 28 | void ForumsActionClicked(); 29 | void IssuesActionClicked(); 30 | void DiscordActionClicked(); 31 | void MarketplaceActionClicked(); 32 | 33 | private: 34 | 35 | void AddMenuBarExtension(FMenuBarBuilder& Builder); 36 | void AddMenuExtension(FMenuBuilder& Builder); 37 | 38 | private: 39 | TSharedPtr PluginCommands; 40 | }; 41 | 42 | IMPLEMENT_MODULE(FRuntimeMeshComponentEditorPlugin, RuntimeMeshComponentEditor) 43 | 44 | 45 | 46 | void FRuntimeMeshComponentEditorPlugin::StartupModule() 47 | { 48 | { 49 | FPropertyEditorModule& PropertyModule = FModuleManager::LoadModuleChecked("PropertyEditor"); 50 | PropertyModule.RegisterCustomClassLayout(URuntimeMeshComponent::StaticClass()->GetFName(), FOnGetDetailCustomizationInstance::CreateStatic(&FRuntimeMeshComponentDetails::MakeInstance)); 51 | } 52 | 53 | FRuntimeMeshComponentEditorStyle::Initialize(); 54 | FRuntimeMeshComponentEditorStyle::ReloadTextures(); 55 | 56 | FRuntimeMeshComponentEditorCommands::Register(); 57 | 58 | PluginCommands = MakeShareable(new FUICommandList); 59 | 60 | PluginCommands->MapAction( 61 | FRuntimeMeshComponentEditorCommands::Get().DonateAction, 62 | FExecuteAction::CreateRaw(this, &FRuntimeMeshComponentEditorPlugin::DonateActionClicked), 63 | FCanExecuteAction()); 64 | PluginCommands->MapAction( 65 | FRuntimeMeshComponentEditorCommands::Get().HelpAction, 66 | FExecuteAction::CreateRaw(this, &FRuntimeMeshComponentEditorPlugin::HelpActionClicked), 67 | FCanExecuteAction()); 68 | PluginCommands->MapAction( 69 | FRuntimeMeshComponentEditorCommands::Get().ForumsAction, 70 | FExecuteAction::CreateRaw(this, &FRuntimeMeshComponentEditorPlugin::ForumsActionClicked), 71 | FCanExecuteAction()); 72 | PluginCommands->MapAction( 73 | FRuntimeMeshComponentEditorCommands::Get().IssuesAction, 74 | FExecuteAction::CreateRaw(this, &FRuntimeMeshComponentEditorPlugin::IssuesActionClicked), 75 | FCanExecuteAction()); 76 | PluginCommands->MapAction( 77 | FRuntimeMeshComponentEditorCommands::Get().DiscordAction, 78 | FExecuteAction::CreateRaw(this, &FRuntimeMeshComponentEditorPlugin::DiscordActionClicked), 79 | FCanExecuteAction()); 80 | PluginCommands->MapAction( 81 | FRuntimeMeshComponentEditorCommands::Get().MarketplaceAction, 82 | FExecuteAction::CreateRaw(this, &FRuntimeMeshComponentEditorPlugin::MarketplaceActionClicked), 83 | FCanExecuteAction()); 84 | 85 | FLevelEditorModule& LevelEditorModule = FModuleManager::LoadModuleChecked("LevelEditor"); 86 | 87 | { 88 | TSharedPtr MenuExtender = MakeShareable(new FExtender()); 89 | MenuExtender->AddMenuBarExtension("Window", EExtensionHook::After, PluginCommands, FMenuBarExtensionDelegate::CreateRaw(this, &FRuntimeMeshComponentEditorPlugin::AddMenuBarExtension)); 90 | LevelEditorModule.GetMenuExtensibilityManager()->AddExtender(MenuExtender); 91 | } 92 | } 93 | 94 | void FRuntimeMeshComponentEditorPlugin::ShutdownModule() 95 | { 96 | FRuntimeMeshComponentEditorStyle::Shutdown(); 97 | 98 | FRuntimeMeshComponentEditorCommands::Unregister(); 99 | } 100 | 101 | void FRuntimeMeshComponentEditorPlugin::DonateActionClicked() 102 | { 103 | FPlatformProcess::LaunchURL(TEXT("https://www.paypal.com/paypalme/Koderz"), NULL, NULL); 104 | 105 | } 106 | 107 | void FRuntimeMeshComponentEditorPlugin::HelpActionClicked() 108 | { 109 | FPlatformProcess::LaunchURL(TEXT("https://runtimemesh.koderz.io/"), NULL, NULL); 110 | } 111 | 112 | void FRuntimeMeshComponentEditorPlugin::ForumsActionClicked() 113 | { 114 | FPlatformProcess::LaunchURL(TEXT("https://forums.unrealengine.com/unreal-engine/marketplace/85617-runtime-mesh-component"), NULL, NULL); 115 | 116 | } 117 | 118 | void FRuntimeMeshComponentEditorPlugin::IssuesActionClicked() 119 | { 120 | FPlatformProcess::LaunchURL(TEXT("https://github.com/TriAxis-Games/RuntimeMeshComponent/issues"), NULL, NULL); 121 | 122 | } 123 | 124 | void FRuntimeMeshComponentEditorPlugin::DiscordActionClicked() 125 | { 126 | 127 | FPlatformProcess::LaunchURL(TEXT("https://discord.gg/KGvBBTv"), NULL, NULL); 128 | } 129 | 130 | void FRuntimeMeshComponentEditorPlugin::MarketplaceActionClicked() 131 | { 132 | FPlatformProcess::LaunchURL(TEXT("https://www.unrealengine.com/marketplace/en-US/product/runtime-mesh-component"), NULL, NULL); 133 | } 134 | 135 | void FRuntimeMeshComponentEditorPlugin::AddMenuBarExtension(FMenuBarBuilder& Builder) 136 | { 137 | Builder.AddPullDownMenu( 138 | LOCTEXT("RuntimeMeshComponentMenu", "Runtime Mesh Component"), 139 | LOCTEXT("RuntimeMeshComponentMenu_ToolTip", "Open Runtime Mesh Component Help and Documentation"), 140 | FNewMenuDelegate::CreateRaw(this, &FRuntimeMeshComponentEditorPlugin::AddMenuExtension), 141 | "Runtime Mesh Component"); 142 | } 143 | 144 | void FRuntimeMeshComponentEditorPlugin::AddMenuExtension(FMenuBuilder& Builder) 145 | { 146 | Builder.BeginSection("Help", LOCTEXT("RuntimeMeshComponentMenu_Help", "Help")); 147 | Builder.AddMenuEntry(FRuntimeMeshComponentEditorCommands::Get().MarketplaceAction); 148 | Builder.AddMenuEntry(FRuntimeMeshComponentEditorCommands::Get().ForumsAction); 149 | Builder.AddMenuEntry(FRuntimeMeshComponentEditorCommands::Get().HelpAction); 150 | Builder.AddMenuEntry(FRuntimeMeshComponentEditorCommands::Get().IssuesAction); 151 | Builder.AddMenuEntry(FRuntimeMeshComponentEditorCommands::Get().DiscordAction); 152 | Builder.EndSection(); 153 | 154 | Builder.BeginSection("Support", LOCTEXT("RuntimeMeshComponentMenu_Support", "Support")); 155 | Builder.AddMenuEntry(FRuntimeMeshComponentEditorCommands::Get().DonateAction); 156 | Builder.EndSection(); 157 | } 158 | 159 | 160 | #undef LOCTEXT_NAMESPACE -------------------------------------------------------------------------------- /Plugins/RuntimeMeshComponent/Source/RuntimeMeshComponentEditor/Private/RuntimeMeshComponentEditorStyle.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2020 TriAxis Games L.L.C. All Rights Reserved. 2 | 3 | #include "RuntimeMeshComponentEditorStyle.h" 4 | #include "Framework/Application/SlateApplication.h" 5 | #include "Styling/SlateStyleRegistry.h" 6 | #include "Slate/SlateGameResources.h" 7 | #include "Interfaces/IPluginManager.h" 8 | 9 | TSharedPtr< FSlateStyleSet > FRuntimeMeshComponentEditorStyle::StyleInstance = NULL; 10 | 11 | void FRuntimeMeshComponentEditorStyle::Initialize() 12 | { 13 | if (!StyleInstance.IsValid()) 14 | { 15 | StyleInstance = Create(); 16 | FSlateStyleRegistry::RegisterSlateStyle(*StyleInstance); 17 | } 18 | } 19 | 20 | void FRuntimeMeshComponentEditorStyle::Shutdown() 21 | { 22 | FSlateStyleRegistry::UnRegisterSlateStyle(*StyleInstance); 23 | ensure(StyleInstance.IsUnique()); 24 | StyleInstance.Reset(); 25 | } 26 | 27 | FName FRuntimeMeshComponentEditorStyle::GetStyleSetName() 28 | { 29 | static FName StyleSetName(TEXT("RuntimeMeshComponentEditorStyle")); 30 | return StyleSetName; 31 | } 32 | 33 | #define IMAGE_BRUSH( RelativePath, ... ) FSlateImageBrush( Style->RootToContentDir( RelativePath, TEXT(".png") ), __VA_ARGS__ ) 34 | #define BOX_BRUSH( RelativePath, ... ) FSlateBoxBrush( Style->RootToContentDir( RelativePath, TEXT(".png") ), __VA_ARGS__ ) 35 | #define BORDER_BRUSH( RelativePath, ... ) FSlateBorderBrush( Style->RootToContentDir( RelativePath, TEXT(".png") ), __VA_ARGS__ ) 36 | #define TTF_FONT( RelativePath, ... ) FSlateFontInfo( Style->RootToContentDir( RelativePath, TEXT(".ttf") ), __VA_ARGS__ ) 37 | #define OTF_FONT( RelativePath, ... ) FSlateFontInfo( Style->RootToContentDir( RelativePath, TEXT(".otf") ), __VA_ARGS__ ) 38 | 39 | const FVector2D Icon128x128(128.0f, 128.0f); 40 | 41 | TSharedRef< FSlateStyleSet > FRuntimeMeshComponentEditorStyle::Create() 42 | { 43 | TSharedRef< FSlateStyleSet > Style = MakeShareable(new FSlateStyleSet("RuntimeMeshComponentEditorStyle")); 44 | Style->SetContentRoot(IPluginManager::Get().FindPlugin("RuntimeMeshComponent")->GetBaseDir() / TEXT("Resources")); 45 | 46 | Style->Set("RuntimeMeshComponentEditor.PluginAction", new IMAGE_BRUSH(TEXT("Icon128"), Icon128x128)); 47 | 48 | return Style; 49 | } 50 | 51 | #undef IMAGE_BRUSH 52 | #undef BOX_BRUSH 53 | #undef BORDER_BRUSH 54 | #undef TTF_FONT 55 | #undef OTF_FONT 56 | 57 | void FRuntimeMeshComponentEditorStyle::ReloadTextures() 58 | { 59 | if (FSlateApplication::IsInitialized()) 60 | { 61 | FSlateApplication::Get().GetRenderer()->ReloadTextureResources(); 62 | } 63 | } 64 | 65 | const ISlateStyle& FRuntimeMeshComponentEditorStyle::Get() 66 | { 67 | return *StyleInstance; 68 | } 69 | -------------------------------------------------------------------------------- /Plugins/RuntimeMeshComponent/Source/RuntimeMeshComponentEditor/Public/IRuntimeMeshComponentEditorPlugin.h: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2020 TriAxis Games L.L.C. All Rights Reserved. 2 | 3 | #pragma once 4 | 5 | #include "Modules/ModuleManager.h" 6 | 7 | 8 | /** 9 | * The public interface to this module 10 | */ 11 | class IRuntimeMeshComponentEditorPlugin : public IModuleInterface 12 | { 13 | 14 | public: 15 | 16 | /** 17 | * Singleton-like access to this module's interface. This is just for convenience! 18 | * Beware of calling this during the shutdown phase, though. Your module might have been unloaded already. 19 | * 20 | * @return Returns singleton instance, loading the module on demand if needed 21 | */ 22 | static inline IRuntimeMeshComponentEditorPlugin& Get() 23 | { 24 | return FModuleManager::LoadModuleChecked< IRuntimeMeshComponentEditorPlugin >("RuntimeMeshComponentEditorPlugin"); 25 | } 26 | 27 | /** 28 | * Checks to see if this module is loaded and ready. It is only valid to call Get() if IsAvailable() returns true. 29 | * 30 | * @return True if the module is loaded and ready to use 31 | */ 32 | static inline bool IsAvailable() 33 | { 34 | return FModuleManager::Get().IsModuleLoaded("RuntimeMeshComponentEditorPlugin"); 35 | } 36 | }; -------------------------------------------------------------------------------- /Plugins/RuntimeMeshComponent/Source/RuntimeMeshComponentEditor/Public/RuntimeMeshComponentEditorCommands.h: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2020 TriAxis Games L.L.C. All Rights Reserved. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "Framework/Commands/Commands.h" 7 | #include "RuntimeMeshComponentEditorStyle.h" 8 | 9 | class FRuntimeMeshComponentEditorCommands : public TCommands 10 | { 11 | public: 12 | 13 | FRuntimeMeshComponentEditorCommands() 14 | : TCommands(TEXT("RuntimeMeshComponentEditor"), NSLOCTEXT("Contexts", "RuntimeMeshComponentEditor", "RuntimeMeshComponentEditor Plugin"), NAME_None, FRuntimeMeshComponentEditorStyle::GetStyleSetName()) 15 | { 16 | } 17 | 18 | // TCommands<> interface 19 | virtual void RegisterCommands() override; 20 | 21 | public: 22 | TSharedPtr DonateAction; 23 | TSharedPtr HelpAction; 24 | TSharedPtr ForumsAction; 25 | TSharedPtr IssuesAction; 26 | TSharedPtr DiscordAction; 27 | TSharedPtr MarketplaceAction; 28 | }; 29 | -------------------------------------------------------------------------------- /Plugins/RuntimeMeshComponent/Source/RuntimeMeshComponentEditor/Public/RuntimeMeshComponentEditorStyle.h: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2020 TriAxis Games L.L.C. All Rights Reserved. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "Styling/SlateStyle.h" 7 | 8 | class FRuntimeMeshComponentEditorStyle 9 | { 10 | public: 11 | 12 | static void Initialize(); 13 | 14 | static void Shutdown(); 15 | 16 | /** reloads textures used by slate renderer */ 17 | static void ReloadTextures(); 18 | 19 | /** @return The Slate style set for the Shooter game */ 20 | static const ISlateStyle& Get(); 21 | 22 | static FName GetStyleSetName(); 23 | 24 | private: 25 | 26 | static TSharedRef< class FSlateStyleSet > Create(); 27 | 28 | private: 29 | 30 | static TSharedPtr< class FSlateStyleSet > StyleInstance; 31 | }; -------------------------------------------------------------------------------- /Plugins/RuntimeMeshComponent/Source/RuntimeMeshComponentEditor/RuntimeMeshComponentEditor.Build.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2020 TriAxis Games L.L.C. All Rights Reserved. 2 | 3 | using System.IO; 4 | using UnrealBuildTool; 5 | 6 | public class RuntimeMeshComponentEditor : ModuleRules 7 | { 8 | public RuntimeMeshComponentEditor(ReadOnlyTargetRules rules) : base(rules) 9 | { 10 | bEnforceIWYU = true; 11 | bLegacyPublicIncludePaths = false; 12 | 13 | #if UE_4_23_OR_LATER 14 | PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; 15 | #endif 16 | 17 | #if UE_4_24_OR_LATER 18 | #else 19 | #endif 20 | 21 | 22 | PublicDependencyModuleNames.AddRange( 23 | new string[] 24 | { 25 | "Core", 26 | // ... add other public dependencies that you statically link with here ... 27 | 28 | } 29 | ); 30 | 31 | PrivateDependencyModuleNames.AddRange( 32 | new string[] 33 | { 34 | "CoreUObject", 35 | // ... add private dependencies that you statically link with here ... 36 | "Engine", 37 | "Slate", 38 | "SlateCore", 39 | "RenderCore", 40 | "RHI", 41 | "NavigationSystem", 42 | "UnrealEd", 43 | "LevelEditor", 44 | "PropertyEditor", 45 | "RawMesh", 46 | "AssetTools", 47 | "AssetRegistry", 48 | "Projects", 49 | "EditorStyle", 50 | "InputCore", 51 | 52 | "RuntimeMeshComponent", 53 | } 54 | ); 55 | } 56 | } -------------------------------------------------------------------------------- /ProceduralMeshDemos.uproject: -------------------------------------------------------------------------------- 1 | { 2 | "FileVersion": 3, 3 | "EngineAssociation": "4.26", 4 | "Category": "", 5 | "Description": "", 6 | "Modules": [ 7 | { 8 | "Name": "ProceduralMeshDemos", 9 | "Type": "Runtime", 10 | "LoadingPhase": "Default" 11 | } 12 | ], 13 | "Plugins": [ 14 | { 15 | "Name": "OculusVR", 16 | "Enabled": false 17 | }, 18 | { 19 | "Name": "SteamVR", 20 | "Enabled": false 21 | } 22 | ] 23 | } -------------------------------------------------------------------------------- /Source/ProceduralMeshDemos.Target.cs: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | using UnrealBuildTool; 4 | using System.Collections.Generic; 5 | 6 | public class ProceduralMeshDemosTarget : TargetRules 7 | { 8 | public ProceduralMeshDemosTarget(TargetInfo Target) : base(Target) 9 | { 10 | Type = TargetType.Game; 11 | DefaultBuildSettings = BuildSettingsVersion.V2; 12 | 13 | ExtraModuleNames.AddRange(new string[] { "ProceduralMeshDemos" }); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Source/ProceduralMeshDemos/ProceduralMeshDemos.Build.cs: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | using UnrealBuildTool; 4 | 5 | public class ProceduralMeshDemos : ModuleRules 6 | { 7 | public ProceduralMeshDemos(ReadOnlyTargetRules Target) : base(Target) 8 | { 9 | PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; 10 | 11 | PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "ProceduralMeshes", "RuntimeMeshComponent" }); 12 | PrivateDependencyModuleNames.AddRange(new string[] { }); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Source/ProceduralMeshDemos/ProceduralMeshDemos.cpp: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #include "ProceduralMeshDemos.h" 4 | #include "Modules/ModuleManager.h" 5 | 6 | IMPLEMENT_PRIMARY_GAME_MODULE( FDefaultGameModuleImpl, ProceduralMeshDemos, "ProceduralMeshDemos" ); 7 | -------------------------------------------------------------------------------- /Source/ProceduralMeshDemos/ProceduralMeshDemos.h: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | 7 | -------------------------------------------------------------------------------- /Source/ProceduralMeshDemos/ProceduralMeshDemosGameMode.cpp: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #include "ProceduralMeshDemosGameMode.h" 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Source/ProceduralMeshDemos/ProceduralMeshDemosGameMode.h: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #pragma once 4 | 5 | #include "GameFramework/GameMode.h" 6 | #include "ProceduralMeshDemosGameMode.generated.h" 7 | 8 | /** 9 | * 10 | */ 11 | UCLASS() 12 | class PROCEDURALMESHDEMOS_API AProceduralMeshDemosGameMode : public AGameMode 13 | { 14 | GENERATED_BODY() 15 | 16 | 17 | 18 | 19 | }; 20 | -------------------------------------------------------------------------------- /Source/ProceduralMeshDemosEditor.Target.cs: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | using UnrealBuildTool; 4 | using System.Collections.Generic; 5 | 6 | public class ProceduralMeshDemosEditorTarget : TargetRules 7 | { 8 | public ProceduralMeshDemosEditorTarget(TargetInfo Target) : base(Target) 9 | { 10 | Type = TargetType.Editor; 11 | DefaultBuildSettings = BuildSettingsVersion.V2; 12 | 13 | ExtraModuleNames.AddRange(new string[] { "ProceduralMeshDemos" }); 14 | } 15 | } 16 | --------------------------------------------------------------------------------