protected override Task <ResultStatus> DoCommandOverride(ICommandContext commandContext)
            {
                var result = new GameSettings
                {
                    PackageId       = package.Id,
                    DefaultSceneUrl = AssetParameters.DefaultScene != null?AttachedReferenceManager.GetUrl(AssetParameters.DefaultScene) : null,
                                          DefaultBackBufferWidth     = AssetParameters.BackBufferWidth,
                                          DefaultBackBufferHeight    = AssetParameters.BackBufferHeight,
                                          DefaultGraphicsProfileUsed = AssetParameters.DefaultGraphicsProfile,
                                          ColorSpace        = AssetParameters.ColorSpace,
                                          EffectCompilation = package.UserSettings.GetValue(GameUserSettings.Effect.EffectCompilation),
                                          RecordUsedEffects = package.UserSettings.GetValue(GameUserSettings.Effect.RecordUsedEffects)
                };

                // TODO: Platform-specific settings have priority
                //if (platform != PlatformType.Shared)
                //{
                //    var platformProfile = package.Profiles.FirstOrDefault(o => o.Platform == platform);
                //    if (platformProfile != null && platformProfile.Properties.ContainsKey(DefaultGraphicsProfile))
                //    {
                //        var customProfile = platformProfile.Properties.Get(DefaultGraphicsProfile);
                //        result.DefaultGraphicsProfileUsed = customProfile;
                //    }
                //}

                var assetManager = new AssetManager();

                assetManager.Save(Url, result);

                return(Task.FromResult(ResultStatus.Successful));
            }
        public override IEnumerable <ObjectUrl> GetInputFiles(AssetItem assetItem)
        {
            var asset = (ColliderShapeAsset)assetItem.Asset;

            foreach (var desc in asset.ColliderShapes)
            {
                if (desc is ConvexHullColliderShapeDesc convexHullDesc)
                {
                    if (convexHullDesc.Model is not null)
                    {
                        var url = AttachedReferenceManager.GetUrl(convexHullDesc.Model);

                        if (!string.IsNullOrEmpty(url))
                        {
                            yield return(new ObjectUrl(UrlType.Content, url));
                        }
                    }
                }
                else if (desc is HeightfieldColliderShapeDesc heightfieldDesc)
                {
                    if (heightfieldDesc.HeightStickArraySource is HeightStickArraySourceFromHeightmap heightmapSource &&
                        heightmapSource.Heightmap is not null)
                    {
                        var url = AttachedReferenceManager.GetUrl(heightmapSource.Heightmap);

                        if (!string.IsNullOrEmpty(url))
                        {
                            yield return(new ObjectUrl(UrlType.Content, url));
                        }
                    }
                }
            }
        }
Beispiel #3
0
        public void SimpleSaveData()
        {
            var b1 = new B();

            b1.A = new A {
                I = 18
            };

            var databaseProvider = CreateDatabaseProvider();
            var assetManager1    = new ContentManager(databaseProvider);
            var assetManager2    = new ContentManager(databaseProvider);

            assetManager1.Save("test", b1);

            Assert.NotNull(AttachedReferenceManager.GetUrl(b1.A));

            var b2 = new B();

            b2.A = new A();
            var attachedReference = AttachedReferenceManager.GetOrCreateAttachedReference(b2.A);

            attachedReference.Url     = AttachedReferenceManager.GetUrl(b1.A);
            attachedReference.IsProxy = true;
            assetManager1.Save("test2", b2);

            var b3 = assetManager2.Load <B>("test2");

            Assert.Equal(b1.A.I, b3.A.I);
        }
Beispiel #4
0
        public void SimpleLoadData()
        {
            var b1 = new B();

            b1.A = new A {
                I = 18
            };

            var assetManager1 = new AssetManager();
            var assetManager2 = new AssetManager();
            var assetManager3 = new AssetManager();

            assetManager1.Save("test", b1);

            // Use new asset manager
            var b2 = assetManager2.Load <B>("test");

            Assert.That(b2, Is.Not.EqualTo(b1));
            Assert.That(b2.A.I, Is.EqualTo(b1.A.I));

            // Try to load without references
            var b3 = assetManager3.Load <B>("test", new AssetManagerLoaderSettings {
                LoadContentReferences = false
            });

            Assert.That(b3, Is.Not.EqualTo(b1));

            // b3.A should be default initialized
            Assert.That(b3.A.I, Is.EqualTo(0));

            Assert.That(AttachedReferenceManager.GetUrl(b3.A), Is.Not.Null);
        }
        protected override IEnumerable <ObjectUrl> GetInputFilesImpl()
        {
            // Add game settings asset URL
            yield return(new ObjectUrl(UrlType.Content, GameSettingsAsset.GameSettingsLocation));

            var gameSettings = context.GetGameSettingsAsset();

            var defaultSceneUrl = gameSettings.DefaultScene != null?AttachedReferenceManager.GetUrl(gameSettings.DefaultScene) : null;

            if (defaultSceneUrl == null)
            {
                yield break;
            }

            // Add scene
            yield return(new ObjectUrl(UrlType.Content, defaultSceneUrl));

            // And all its dependencies (TODO: restrict ourselves on what affect rendering?)
            var sceneAssetItem = package.Session.FindAsset(defaultSceneUrl);
            var dependencies   = package.Session.DependencyManager.ComputeDependencies(sceneAssetItem.Id, AssetDependencySearchOptions.Out | AssetDependencySearchOptions.Recursive, ContentLinkType.Reference);

            foreach (var dependency in dependencies.LinksOut)
            {
                yield return(new ObjectUrl(UrlType.Content, dependency.Item.Location));
            }
        }
Beispiel #6
0
        public void SimpleSaveData()
        {
            var b1 = new B();

            b1.A = new A {
                I = 18
            };

            var assetManager1 = new AssetManager();
            var assetManager2 = new AssetManager();

            assetManager1.Save("test", b1);

            Assert.That(AttachedReferenceManager.GetUrl(b1.A), Is.Not.Null);

            var b2 = new B();

            b2.A = new A();
            var attachedReference = AttachedReferenceManager.GetOrCreateAttachedReference(b2.A);

            attachedReference.Url     = AttachedReferenceManager.GetUrl(b1.A);
            attachedReference.IsProxy = true;
            assetManager1.Save("test2", b2);

            var b3 = assetManager2.Load <B>("test2");

            Assert.That(b3.A.I, Is.EqualTo(b1.A.I));
        }
        /// <inheritdoc/>
        protected override Task <ResultStatus> DoCommandOverride(ICommandContext commandContext)
        {
            var gameSettings = context.GetGameSettingsAsset();

            // Find default scene URL
            var defaultSceneUrl = gameSettings.DefaultScene != null?AttachedReferenceManager.GetUrl(gameSettings.DefaultScene) : null;

            if (defaultSceneUrl == null)
            {
                return(Task.FromResult(ResultStatus.Successful));
            }

            var baseUrl = new UFile(defaultSceneUrl).GetParent();

            try
            {
                commandContext.Logger.Info($"Trying to compile effects for scene '{defaultSceneUrl}'");

                using (var sceneRenderer = new SceneRenderer(gameSettings))
                {
                    // Effect can be compiled asynchronously (since we don't have any fallback, they will have to be compiled in the same frame anyway)
                    // Also set the file provider to the current transaction
                    ((EffectCompilerCache)sceneRenderer.EffectSystem.Compiler).CompileEffectAsynchronously = true;
                    ((EffectCompilerCache)sceneRenderer.EffectSystem.Compiler).FileProvider = MicrothreadLocalDatabases.DatabaseFileProvider;
                    ((EffectCompilerCache)sceneRenderer.EffectSystem.Compiler).CurrentCache = EffectBytecodeCacheLoadSource.StartupCache;
                    sceneRenderer.EffectSystem.EffectUsed += (effectCompileRequest, result) => compilerResult.BuildSteps.Add(EffectCompileCommand.FromRequest(context, package, baseUrl, effectCompileRequest));

                    sceneRenderer.GameSystems.LoadContent();

                    // Load the scene
                    var scene = sceneRenderer.ContentManager.Load <Scene>(defaultSceneUrl);
                    sceneRenderer.SceneSystem.SceneInstance = new SceneInstance(sceneRenderer.Services, scene, ExecutionMode.EffectCompile);

                    // Disable culling
                    sceneRenderer.SceneSystem.SceneInstance.VisibilityGroups.CollectionChanged += (sender, e) =>
                    {
                        if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add)
                        {
                            ((VisibilityGroup)e.Item).DisableCulling = true;
                        }
                    };

                    // Update and draw
                    // This will force effects to be generated and saved in the object database
                    var time = new GameTime();
                    sceneRenderer.GameSystems.Update(time);
                    sceneRenderer.GraphicsContext.ResourceGroupAllocator.Reset(sceneRenderer.GraphicsContext.CommandList);
                    sceneRenderer.GameSystems.Draw(time);
                }
            }
            catch (Exception e)
            {
                commandContext.Logger.Warning($"Could not compile effects for scene '{defaultSceneUrl}': {e.Message + e.StackTrace}", e);
            }

            return(Task.FromResult(ResultStatus.Successful));
        }
        public override IEnumerable <ObjectUrl> GetInputFiles(AssetItem assetItem)
        {
            var asset = (NavigationMeshAsset)assetItem.Asset;

            if (asset.Scene != null)
            {
                string sceneUrl   = AttachedReferenceManager.GetUrl(asset.Scene);
                var    sceneAsset = (SceneAsset)assetItem.Package.Session.FindAsset(sceneUrl)?.Asset;
                if (sceneAsset == null)
                {
                    yield break;
                }

                var sceneEntities = sceneAsset.Hierarchy.Parts.Select(x => x.Value.Entity).ToList();
                foreach (var entity in sceneEntities)
                {
                    var collider = entity.Get <StaticColliderComponent>();

                    // Only process enabled colliders
                    bool colliderEnabled = collider != null && ((CollisionFilterGroupFlags)collider.CollisionGroup & asset.IncludedCollisionGroups) != 0 && collider.Enabled;
                    if (colliderEnabled) // Removed or disabled
                    {
                        foreach (var desc in collider.ColliderShapes)
                        {
                            var shapeAssetDesc = desc as ColliderShapeAssetDesc;
                            if (shapeAssetDesc?.Shape != null)
                            {
                                var assetReference = AttachedReferenceManager.GetAttachedReference(shapeAssetDesc.Shape);
                                if (assetReference != null)
                                {
                                    yield return(new ObjectUrl(UrlType.Content, assetReference.Url));
                                }
                            }
                            else if (desc is HeightfieldColliderShapeDesc)
                            {
                                var heightfieldDesc = desc as HeightfieldColliderShapeDesc;
                                var heightmapSource = heightfieldDesc?.HeightStickArraySource as HeightStickArraySourceFromHeightmap;

                                if (heightmapSource?.Heightmap != null)
                                {
                                    var url = AttachedReferenceManager.GetUrl(heightmapSource.Heightmap);

                                    if (!string.IsNullOrEmpty(url))
                                    {
                                        yield return(new ObjectUrl(UrlType.Content, url));
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
            private void EnsureClonedSceneAndHash()
            {
                if (!sceneCloned)
                {
                    // Hash relevant scene objects
                    if (asset.Scene != null)
                    {
                        string sceneUrl   = AttachedReferenceManager.GetUrl(asset.Scene);
                        var    sceneAsset = (SceneAsset)package.Session.FindAsset(sceneUrl)?.Asset;

                        // Clone scene asset because we update the world transformation matrices
                        clonedSceneAsset = (SceneAsset)AssetCloner.Clone(sceneAsset);

                        // Turn the entire entity hierarchy into a single list
                        sceneEntities = clonedSceneAsset.Hierarchy.Parts.Select(x => x.Entity).ToList();

                        sceneHash = 0;
                        foreach (var entity in sceneEntities)
                        {
                            StaticColliderComponent collider = entity.Get <StaticColliderComponent>();

                            // Only process enabled colliders
                            bool colliderEnabled = collider != null && ((CollisionFilterGroupFlags)collider.CollisionGroup & asset.IncludedCollisionGroups) != 0 && collider.Enabled;
                            if (colliderEnabled) // Removed or disabled
                            {
                                // Update world transform before hashing
                                entity.Transform.UpdateWorldMatrix();

                                // Load collider shape assets since the scene asset is being used, which does not have these loaded by default
                                foreach (var desc in collider.ColliderShapes)
                                {
                                    var shapeAssetDesc = desc as ColliderShapeAssetDesc;
                                    if (shapeAssetDesc?.Shape != null)
                                    {
                                        var assetReference = AttachedReferenceManager.GetAttachedReference(shapeAssetDesc.Shape);
                                        PhysicsColliderShape loadedColliderShape;
                                        if (!loadedColliderShapes.TryGetValue(assetReference.Url, out loadedColliderShape))
                                        {
                                            loadedColliderShape = contentManager.Load <PhysicsColliderShape>(assetReference.Url);
                                            loadedColliderShapes.Add(assetReference.Url, loadedColliderShape); // Store where we loaded the shapes from
                                        }
                                        shapeAssetDesc.Shape = loadedColliderShape;
                                    }
                                }

                                // Finally compute the hash for this collider
                                sceneHash += NavigationMeshBuildUtils.HashEntityCollider(collider);
                            }
                        }
                    }
                    sceneCloned = true;
                }
            }
        private IModelAsset GetReferencedModel()
        {
            var modelReference = entity.AssetSideEntity.Get <ModelComponent>()?.Model;

            if (modelReference == null)
            {
                return(null);
            }

            var modelUrl = AttachedReferenceManager.GetUrl(modelReference);

            return(entity.Editor.Session.AllAssets.FirstOrDefault(x => x.Url == modelUrl)?.Asset as IModelAsset);
        }
Beispiel #11
0
            protected override Task <ResultStatus> DoCommandOverride(ICommandContext commandContext)
            {
                var result = new GameSettings
                {
                    PackageName     = package.Meta.Name,
                    DefaultSceneUrl = Parameters.DefaultScene != null?AttachedReferenceManager.GetUrl(Parameters.DefaultScene) : null,
                                          DefaultGraphicsCompositorUrl = Parameters.GraphicsCompositor != null?AttachedReferenceManager.GetUrl(Parameters.GraphicsCompositor) : null,
                                                                             SplashScreenUrl        = Parameters.SplashScreenTexture != null && (compilationMode == CompilationMode.Release || compilationMode == CompilationMode.AppStore) ? AttachedReferenceManager.GetUrl(Parameters.SplashScreenTexture) : null,
                                                                             SplashScreenColor      = Parameters.SplashScreenColor,
                                                                             DoubleViewSplashScreen = Parameters.DoubleViewSplashScreen,
                                                                             EffectCompilation      = package.UserSettings.GetValue(GameUserSettings.Effect.EffectCompilation),
                                                                             RecordUsedEffects      = package.UserSettings.GetValue(GameUserSettings.Effect.RecordUsedEffects),
                                                                             Configurations         = new PlatformConfigurations(),
                                                                             CompilationMode        = compilationMode
                };

                //start from the default platform and go down overriding

                foreach (var configuration in Parameters.Defaults.Where(x => !x.OfflineOnly))
                {
                    result.Configurations.Configurations.Add(new ConfigurationOverride
                    {
                        Platforms      = ConfigPlatforms.None,
                        SpecificFilter = -1,
                        Configuration  = configuration
                    });
                }

                foreach (var configurationOverride in Parameters.Overrides.Where(x => x.Configuration != null && !x.Configuration.OfflineOnly))
                {
                    result.Configurations.Configurations.Add(configurationOverride);
                }

                result.Configurations.PlatformFilters = Parameters.PlatformFilters;

                //make sure we modify platform specific files to set the wanted orientation
                if (package.Container is SolutionProject solutionProject)
                {
                    SetPlatformOrientation(solutionProject, Parameters.GetOrCreate <RenderingSettings>().DisplayOrientation);
                }

                var assetManager = new ContentManager(MicrothreadLocalDatabases.ProviderService);

                assetManager.Save(Url, result);

                return(Task.FromResult(ResultStatus.Successful));
            }
Beispiel #12
0
            protected override Task <ResultStatus> DoCommandOverride(ICommandContext commandContext)
            {
                var result = new GameSettings
                {
                    PackageId       = package.Id,
                    PackageName     = package.Meta.Name,
                    DefaultSceneUrl = AssetParameters.DefaultScene != null?AttachedReferenceManager.GetUrl(AssetParameters.DefaultScene) : null,
                                          EffectCompilation = package.UserSettings.GetValue(GameUserSettings.Effect.EffectCompilation),
                                          RecordUsedEffects = package.UserSettings.GetValue(GameUserSettings.Effect.RecordUsedEffects),
                                          Configurations    = new PlatformConfigurations(),
                                          CompilationMode   = compilationMode
                };

                //start from the default platform and go down overriding

                foreach (var configuration in AssetParameters.Defaults.Where(x => !x.OfflineOnly))
                {
                    result.Configurations.Configurations.Add(new ConfigurationOverride
                    {
                        Platforms      = ConfigPlatforms.None,
                        SpecificFilter = -1,
                        Configuration  = configuration
                    });
                }

                foreach (var configurationOverride in AssetParameters.Overrides.Where(x => x.Configuration != null && !x.Configuration.OfflineOnly))
                {
                    result.Configurations.Configurations.Add(configurationOverride);
                }

                result.Configurations.PlatformFilters = AssetParameters.PlatformFilters;

                //make sure we modify platform specific files to set the wanted orientation
                SetPlatformOrientation(package, platform, AssetParameters.Get <RenderingSettings>().DisplayOrientation);

                var assetManager = new ContentManager();

                assetManager.Save(Url, result);

                return(Task.FromResult(ResultStatus.Successful));
            }
        public override IEnumerable <ObjectUrl> GetInputFiles(AssetItem assetItem)
        {
            var asset = (ColliderShapeAsset)assetItem.Asset;

            foreach (var desc in asset.ColliderShapes)
            {
                if (desc is ConvexHullColliderShapeDesc)
                {
                    var convexHullDesc = desc as ConvexHullColliderShapeDesc;

                    if (convexHullDesc.Model != null)
                    {
                        var url = AttachedReferenceManager.GetUrl(convexHullDesc.Model);

                        if (!string.IsNullOrEmpty(url))
                        {
                            yield return(new ObjectUrl(UrlType.Content, url));
                        }
                    }
                }
            }
        }
        public override IEnumerable <ObjectUrl> GetInputFiles(AssetItem assetItem)
        {
            var asset = (NavigationMeshAsset)assetItem.Asset;

            if (asset.Scene != null)
            {
                string sceneUrl   = AttachedReferenceManager.GetUrl(asset.Scene);
                var    sceneAsset = (SceneAsset)assetItem.Package.Session.FindAsset(sceneUrl)?.Asset;
                if (sceneAsset == null)
                {
                    yield break;
                }

                var sceneEntities = sceneAsset.Hierarchy.Parts.Select(x => x.Value.Entity).ToList();
                foreach (var entity in sceneEntities)
                {
                    var collider = entity.Get <StaticColliderComponent>();

                    // Only process enabled colliders
                    // TODO: Update navmesh to use the new collision types
                    bool colliderEnabled = collider != null && collider.Enabled; //((CollisionFilterGroupFlags)collider.CollisionGroup & asset.IncludedCollisionGroups) != 0 && collider.Enabled;
                    if (colliderEnabled)                                         // Removed or disabled
                    {
                        foreach (var desc in collider.ColliderShapes)
                        {
                            var shapeAssetDesc = desc as ColliderShapeAssetDesc;
                            if (shapeAssetDesc?.Shape != null)
                            {
                                var assetReference = AttachedReferenceManager.GetAttachedReference(shapeAssetDesc.Shape);
                                if (assetReference != null)
                                {
                                    yield return(new ObjectUrl(UrlType.Content, assetReference.Url));
                                }
                            }
                        }
                    }
                }
            }
        }
Beispiel #15
0
        public override IEnumerable <ObjectUrl> GetInputFiles(AssetItem assetItem)
        {
            var asset = (ColliderShapeAsset)assetItem.Asset;

            foreach (var desc in asset.ColliderShapes)
            {
                if (desc is ConvexHullColliderShapeDesc)
                {
                    var convexHullDesc = desc as ConvexHullColliderShapeDesc;

                    if (convexHullDesc.Model != null)
                    {
                        var url = AttachedReferenceManager.GetUrl(convexHullDesc.Model);

                        if (!string.IsNullOrEmpty(url))
                        {
                            yield return(new ObjectUrl(UrlType.Content, url));
                        }
                    }
                }
                else if (desc is HeightfieldColliderShapeDesc)
                {
                    var heightfieldDesc = desc as HeightfieldColliderShapeDesc;
                    var initialHeights  = heightfieldDesc?.InitialHeights as HeightfieldHeightDataFromHeightmap;

                    if (initialHeights?.Heightmap != null)
                    {
                        var url = AttachedReferenceManager.GetUrl(initialHeights.Heightmap);

                        if (!string.IsNullOrEmpty(url))
                        {
                            yield return(new ObjectUrl(UrlType.Content, url));
                        }
                    }
                }
            }
        }
Beispiel #16
0
            private void EnsureClonedSceneAndHash()
            {
                if (!sceneCloned)
                {
                    // Hash relevant scene objects
                    if (asset.Scene != null)
                    {
                        string sceneUrl   = AttachedReferenceManager.GetUrl(asset.Scene);
                        var    sceneAsset = (SceneAsset)AssetFinder.FindAsset(sceneUrl)?.Asset;

                        // Clone scene asset because we update the world transformation matrices
                        clonedSceneAsset = (SceneAsset)AssetCloner.Clone(sceneAsset);

                        // Turn the entire entity hierarchy into a single list
                        var sceneEntities = clonedSceneAsset.Hierarchy.Parts.Select(x => x.Value.Entity).ToList();

                        sceneHash = 0;
                        foreach (var entity in sceneEntities)
                        {
                            // Collect bounding box entities
                            NavigationBoundingBoxComponent boundingBoxComponent = entity.Get <NavigationBoundingBoxComponent>();
                            // Collect static collider entities
                            StaticColliderComponent colliderComponent = entity.Get <StaticColliderComponent>();

                            if (boundingBoxComponent == null && colliderComponent == null)
                            {
                                continue;
                            }

                            // Update world transform
                            entity.Transform.UpdateWorldMatrix();

                            if (boundingBoxComponent != null)
                            {
                                Vector3    scale;
                                Quaternion rotation;
                                Vector3    translation;
                                boundingBoxComponent.Entity.Transform.WorldMatrix.Decompose(out scale, out rotation, out translation);
                                var boundingBox = new BoundingBox(translation - boundingBoxComponent.Size * scale, translation + boundingBoxComponent.Size * scale);
                                boundingBoxes.Add(boundingBox);

                                // Hash collider for ComputeParameterHash
                                sceneHash = (sceneHash * 397) ^ boundingBox.GetHashCode();
                            }

                            if (colliderComponent != null)
                            {
                                staticColliderDatas.Add(new StaticColliderData
                                {
                                    Component = colliderComponent
                                });

                                if (colliderComponent.Enabled && !colliderComponent.IsTrigger && ((int)asset.IncludedCollisionGroups & (int)colliderComponent.CollisionGroup) != 0)
                                {
                                    // Load collider shape assets since the scene asset is being used, which does not have these loaded by default
                                    foreach (var desc in colliderComponent.ColliderShapes)
                                    {
                                        var shapeAssetDesc = desc as ColliderShapeAssetDesc;
                                        if (shapeAssetDesc?.Shape != null)
                                        {
                                            var assetReference = AttachedReferenceManager.GetAttachedReference(shapeAssetDesc.Shape);
                                            PhysicsColliderShape loadedColliderShape;
                                            if (!loadedColliderShapes.TryGetValue(assetReference.Url, out loadedColliderShape))
                                            {
                                                loadedColliderShape = contentManager.Load <PhysicsColliderShape>(assetReference.Url);
                                                loadedColliderShapes.Add(assetReference.Url, loadedColliderShape); // Store where we loaded the shapes from
                                            }
                                            shapeAssetDesc.Shape = loadedColliderShape;
                                        }
                                    }
                                }

                                // Hash collider for ComputeParameterHash
                                sceneHash = (sceneHash * 397) ^ Xenko.Navigation.NavigationMeshBuildUtils.HashEntityCollider(colliderComponent, asset.IncludedCollisionGroups);
                            }
                        }
                    }
                    sceneCloned = true;
                }
            }
Beispiel #17
0
            protected override Task <ResultStatus> DoCommandOverride(ICommandContext commandContext)
            {
                var assetManager = new AssetManager();

                AssetParameters.ColliderShapes = AssetParameters.ColliderShapes.Where(x => x != null &&
                                                                                      (x.GetType() != typeof(ConvexHullColliderShapeDesc) || ((ConvexHullColliderShapeDesc)x).Model != null)).ToList();

                //pre process special types
                foreach (var convexHullDesc in
                         (from shape in AssetParameters.ColliderShapes let type = shape.GetType() where type == typeof(ConvexHullColliderShapeDesc) select shape)
                         .Cast <ConvexHullColliderShapeDesc>())
                {
                    //decompose and fill vertex data

                    var loadSettings = new AssetManagerLoaderSettings
                    {
                        ContentFilter = AssetManagerLoaderSettings.NewContentFilterByType(typeof(Mesh))
                    };

                    var modelAsset = assetManager.Load <Model>(AttachedReferenceManager.GetUrl(convexHullDesc.Model), loadSettings);
                    if (modelAsset == null)
                    {
                        continue;
                    }

                    convexHullDesc.ConvexHulls        = new List <List <List <Vector3> > >();
                    convexHullDesc.ConvexHullsIndices = new List <List <List <uint> > >();

                    commandContext.Logger.Info("Processing convex hull generation, this might take a while!");

                    var nodeTransforms = new List <Matrix>();

                    //pre-compute all node transforms, assuming nodes are ordered... see ModelViewHierarchyUpdater
                    var nodesLength = modelAsset.Hierarchy.Nodes.Length;
                    for (var i = 0; i < nodesLength; i++)
                    {
                        Matrix localMatrix;
                        TransformComponent.CreateMatrixTRS(
                            ref modelAsset.Hierarchy.Nodes[i].Transform.Translation,
                            ref modelAsset.Hierarchy.Nodes[i].Transform.Rotation,
                            ref modelAsset.Hierarchy.Nodes[i].Transform.Scaling, out localMatrix);

                        Matrix worldMatrix;
                        if (modelAsset.Hierarchy.Nodes[i].ParentIndex != -1)
                        {
                            var nodeTransform = nodeTransforms[modelAsset.Hierarchy.Nodes[i].ParentIndex];
                            Matrix.Multiply(ref localMatrix, ref nodeTransform, out worldMatrix);
                        }
                        else
                        {
                            worldMatrix = localMatrix;
                        }

                        nodeTransforms.Add(worldMatrix);
                    }

                    for (var i = 0; i < nodesLength; i++)
                    {
                        var i1 = i;
                        if (modelAsset.Meshes.All(x => x.NodeIndex != i1))
                        {
                            continue;                                                // no geometry in the node
                        }
                        var combinedVerts   = new List <float>();
                        var combinedIndices = new List <uint>();

                        var hullsList = new List <List <Vector3> >();
                        convexHullDesc.ConvexHulls.Add(hullsList);

                        var indicesList = new List <List <uint> >();
                        convexHullDesc.ConvexHullsIndices.Add(indicesList);

                        foreach (var meshData in modelAsset.Meshes.Where(x => x.NodeIndex == i1))
                        {
                            var indexOffset = (uint)combinedVerts.Count / 3;

                            var stride          = meshData.Draw.VertexBuffers[0].Declaration.VertexStride;
                            var vertexDataAsset = assetManager.Load <Graphics.Buffer>(AttachedReferenceManager.GetUrl(meshData.Draw.VertexBuffers[0].Buffer));
                            var vertexData      = vertexDataAsset.GetSerializationData().Content;
                            var vertexIndex     = meshData.Draw.VertexBuffers[0].Offset;
                            for (var v = 0; v < meshData.Draw.VertexBuffers[0].Count; v++)
                            {
                                var posMatrix = Matrix.Translation(new Vector3(BitConverter.ToSingle(vertexData, vertexIndex + 0), BitConverter.ToSingle(vertexData, vertexIndex + 4), BitConverter.ToSingle(vertexData, vertexIndex + 8)));

                                Matrix rotatedMatrix;
                                var    nodeTransform = nodeTransforms[i];
                                Matrix.Multiply(ref posMatrix, ref nodeTransform, out rotatedMatrix);

                                combinedVerts.Add(rotatedMatrix.TranslationVector.X);
                                combinedVerts.Add(rotatedMatrix.TranslationVector.Y);
                                combinedVerts.Add(rotatedMatrix.TranslationVector.Z);

                                vertexIndex += stride;
                            }

                            var indexDataAsset = assetManager.Load <Graphics.Buffer>(AttachedReferenceManager.GetUrl(meshData.Draw.IndexBuffer.Buffer));
                            var indexData      = indexDataAsset.GetSerializationData().Content;
                            var indexIndex     = meshData.Draw.IndexBuffer.Offset;
                            for (var v = 0; v < meshData.Draw.IndexBuffer.Count; v++)
                            {
                                if (meshData.Draw.IndexBuffer.Is32Bit)
                                {
                                    combinedIndices.Add(BitConverter.ToUInt32(indexData, indexIndex) + indexOffset);
                                    indexIndex += 4;
                                }
                                else
                                {
                                    combinedIndices.Add(BitConverter.ToUInt16(indexData, indexIndex) + indexOffset);
                                    indexIndex += 2;
                                }
                            }
                        }

                        var decompositionDesc = new ConvexHullMesh.DecompositionDesc
                        {
                            VertexCount   = (uint)combinedVerts.Count / 3,
                            IndicesCount  = (uint)combinedIndices.Count,
                            Vertexes      = combinedVerts.ToArray(),
                            Indices       = combinedIndices.ToArray(),
                            Depth         = convexHullDesc.Depth,
                            PosSampling   = convexHullDesc.PosSampling,
                            PosRefine     = convexHullDesc.PosRefine,
                            AngleSampling = convexHullDesc.AngleSampling,
                            AngleRefine   = convexHullDesc.AngleRefine,
                            Alpha         = convexHullDesc.Alpha,
                            Threshold     = convexHullDesc.Threshold,
                            SimpleHull    = convexHullDesc.SimpleWrap
                        };

                        lock (this)
                        {
                            convexHullMesh = new ConvexHullMesh();
                        }

                        convexHullMesh.Generate(decompositionDesc);

                        var count = convexHullMesh.Count;

                        commandContext.Logger.Info("Node generated " + count + " convex hulls");

                        var vertexCountHull = 0;

                        for (uint h = 0; h < count; h++)
                        {
                            float[] points;
                            convexHullMesh.CopyPoints(h, out points);

                            var pointList = new List <Vector3>();

                            for (var v = 0; v < points.Length; v += 3)
                            {
                                var vert = new Vector3(points[v + 0], points[v + 1], points[v + 2]);
                                pointList.Add(vert);

                                vertexCountHull++;
                            }

                            hullsList.Add(pointList);

                            uint[] indices;
                            convexHullMesh.CopyIndices(h, out indices);

                            for (var t = 0; t < indices.Length; t += 3)
                            {
                                Utilities.Swap(ref indices[t], ref indices[t + 2]);
                            }

                            var indexList = new List <uint>(indices);

                            indicesList.Add(indexList);
                        }

                        lock (this)
                        {
                            convexHullMesh.Dispose();
                            convexHullMesh = null;
                        }

                        commandContext.Logger.Info("For a total of " + vertexCountHull + " vertexes");
                    }
                }

                var runtimeShape = new PhysicsColliderShape {
                    Descriptions = AssetParameters.ColliderShapes
                };

                assetManager.Save(Url, runtimeShape);

                return(Task.FromResult(ResultStatus.Successful));
            }
Beispiel #18
0
            protected override Task <ResultStatus> DoCommandOverride(ICommandContext commandContext)
            {
                var assetManager = new ContentManager();

                // Cloned list of collider shapes
                var descriptions = Parameters.ColliderShapes.ToList();

                Parameters.ColliderShapes = Parameters.ColliderShapes.Where(x => x != null &&
                                                                            (x.GetType() != typeof(ConvexHullColliderShapeDesc) || ((ConvexHullColliderShapeDesc)x).Model != null)).ToList();

                //pre process special types
                foreach (var convexHullDesc in
                         (from shape in Parameters.ColliderShapes let type = shape.GetType() where type == typeof(ConvexHullColliderShapeDesc) select shape)
                         .Cast <ConvexHullColliderShapeDesc>())
                {
                    // Clone the convex hull shape description so the fields that should not be serialized can be cleared (Model in this case)
                    ConvexHullColliderShapeDesc convexHullDescClone = new ConvexHullColliderShapeDesc
                    {
                        Scaling       = convexHullDesc.Scaling,
                        LocalOffset   = convexHullDesc.LocalOffset,
                        LocalRotation = convexHullDesc.LocalRotation,
                        Depth         = convexHullDesc.Depth,
                        PosSampling   = convexHullDesc.PosSampling,
                        AngleSampling = convexHullDesc.AngleSampling,
                        PosRefine     = convexHullDesc.PosRefine,
                        AngleRefine   = convexHullDesc.AngleRefine,
                        Alpha         = convexHullDesc.Alpha,
                        Threshold     = convexHullDesc.Threshold,
                    };

                    // Replace shape in final result with cloned description
                    int replaceIndex = descriptions.IndexOf(convexHullDesc);
                    descriptions[replaceIndex] = convexHullDescClone;

                    var loadSettings = new ContentManagerLoaderSettings
                    {
                        ContentFilter = ContentManagerLoaderSettings.NewContentFilterByType(typeof(Mesh), typeof(Skeleton))
                    };

                    var modelAsset = assetManager.Load <Model>(AttachedReferenceManager.GetUrl(convexHullDesc.Model), loadSettings);
                    if (modelAsset == null)
                    {
                        continue;
                    }

                    convexHullDescClone.ConvexHulls        = new List <List <List <Vector3> > >();
                    convexHullDescClone.ConvexHullsIndices = new List <List <List <uint> > >();

                    commandContext.Logger.Info("Processing convex hull generation, this might take a while!");

                    var nodeTransforms = new List <Matrix>();

                    //pre-compute all node transforms, assuming nodes are ordered... see ModelViewHierarchyUpdater

                    if (modelAsset.Skeleton == null)
                    {
                        Matrix baseMatrix;
                        Matrix.Transformation(ref convexHullDescClone.Scaling, ref convexHullDescClone.LocalRotation, ref convexHullDescClone.LocalOffset, out baseMatrix);
                        nodeTransforms.Add(baseMatrix);
                    }
                    else
                    {
                        var nodesLength = modelAsset.Skeleton.Nodes.Length;
                        for (var i = 0; i < nodesLength; i++)
                        {
                            Matrix localMatrix;
                            Matrix.Transformation(
                                ref modelAsset.Skeleton.Nodes[i].Transform.Scale,
                                ref modelAsset.Skeleton.Nodes[i].Transform.Rotation,
                                ref modelAsset.Skeleton.Nodes[i].Transform.Position, out localMatrix);

                            Matrix worldMatrix;
                            if (modelAsset.Skeleton.Nodes[i].ParentIndex != -1)
                            {
                                var nodeTransform = nodeTransforms[modelAsset.Skeleton.Nodes[i].ParentIndex];
                                Matrix.Multiply(ref localMatrix, ref nodeTransform, out worldMatrix);
                            }
                            else
                            {
                                worldMatrix = localMatrix;
                            }

                            if (i == 0)
                            {
                                Matrix baseMatrix;
                                Matrix.Transformation(ref convexHullDescClone.Scaling, ref convexHullDescClone.LocalRotation, ref convexHullDescClone.LocalOffset, out baseMatrix);
                                nodeTransforms.Add(baseMatrix * worldMatrix);
                            }
                            else
                            {
                                nodeTransforms.Add(worldMatrix);
                            }
                        }
                    }

                    for (var i = 0; i < nodeTransforms.Count; i++)
                    {
                        var i1 = i;
                        if (modelAsset.Meshes.All(x => x.NodeIndex != i1))
                        {
                            continue;                                                // no geometry in the node
                        }
                        var combinedVerts   = new List <float>();
                        var combinedIndices = new List <uint>();

                        var hullsList = new List <List <Vector3> >();
                        convexHullDescClone.ConvexHulls.Add(hullsList);

                        var indicesList = new List <List <uint> >();
                        convexHullDescClone.ConvexHullsIndices.Add(indicesList);

                        foreach (var meshData in modelAsset.Meshes.Where(x => x.NodeIndex == i1))
                        {
                            var indexOffset = (uint)combinedVerts.Count / 3;

                            var stride = meshData.Draw.VertexBuffers[0].Declaration.VertexStride;

                            var    vertexBufferRef = AttachedReferenceManager.GetAttachedReference(meshData.Draw.VertexBuffers[0].Buffer);
                            byte[] vertexData;
                            if (vertexBufferRef.Data != null)
                            {
                                vertexData = ((BufferData)vertexBufferRef.Data).Content;
                            }
                            else if (!vertexBufferRef.Url.IsNullOrEmpty())
                            {
                                var dataAsset = assetManager.Load <Buffer>(vertexBufferRef.Url);
                                vertexData = dataAsset.GetSerializationData().Content;
                            }
                            else
                            {
                                continue;
                            }

                            var vertexIndex = meshData.Draw.VertexBuffers[0].Offset;
                            for (var v = 0; v < meshData.Draw.VertexBuffers[0].Count; v++)
                            {
                                var posMatrix = Matrix.Translation(new Vector3(BitConverter.ToSingle(vertexData, vertexIndex + 0), BitConverter.ToSingle(vertexData, vertexIndex + 4), BitConverter.ToSingle(vertexData, vertexIndex + 8)));

                                Matrix rotatedMatrix;
                                var    nodeTransform = nodeTransforms[i];
                                Matrix.Multiply(ref posMatrix, ref nodeTransform, out rotatedMatrix);

                                combinedVerts.Add(rotatedMatrix.TranslationVector.X);
                                combinedVerts.Add(rotatedMatrix.TranslationVector.Y);
                                combinedVerts.Add(rotatedMatrix.TranslationVector.Z);

                                vertexIndex += stride;
                            }

                            var    indexBufferRef = AttachedReferenceManager.GetAttachedReference(meshData.Draw.IndexBuffer.Buffer);
                            byte[] indexData;
                            if (indexBufferRef.Data != null)
                            {
                                indexData = ((BufferData)indexBufferRef.Data).Content;
                            }
                            else if (!indexBufferRef.Url.IsNullOrEmpty())
                            {
                                var dataAsset = assetManager.Load <Buffer>(indexBufferRef.Url);
                                indexData = dataAsset.GetSerializationData().Content;
                            }
                            else
                            {
                                throw new Exception("Failed to find index buffer while building a convex hull.");
                            }

                            var indexIndex = meshData.Draw.IndexBuffer.Offset;
                            for (var v = 0; v < meshData.Draw.IndexBuffer.Count; v++)
                            {
                                if (meshData.Draw.IndexBuffer.Is32Bit)
                                {
                                    combinedIndices.Add(BitConverter.ToUInt32(indexData, indexIndex) + indexOffset);
                                    indexIndex += 4;
                                }
                                else
                                {
                                    combinedIndices.Add(BitConverter.ToUInt16(indexData, indexIndex) + indexOffset);
                                    indexIndex += 2;
                                }
                            }
                        }

                        var decompositionDesc = new ConvexHullMesh.DecompositionDesc
                        {
                            VertexCount   = (uint)combinedVerts.Count / 3,
                            IndicesCount  = (uint)combinedIndices.Count,
                            Vertexes      = combinedVerts.ToArray(),
                            Indices       = combinedIndices.ToArray(),
                            Depth         = convexHullDesc.Depth,
                            PosSampling   = convexHullDesc.PosSampling,
                            PosRefine     = convexHullDesc.PosRefine,
                            AngleSampling = convexHullDesc.AngleSampling,
                            AngleRefine   = convexHullDesc.AngleRefine,
                            Alpha         = convexHullDesc.Alpha,
                            Threshold     = convexHullDesc.Threshold,
                            SimpleHull    = convexHullDesc.SimpleWrap
                        };

                        var convexHullMesh = new ConvexHullMesh();

                        convexHullMesh.Generate(decompositionDesc);

                        var count = convexHullMesh.Count;

                        commandContext.Logger.Info("Node generated " + count + " convex hulls");

                        var vertexCountHull = 0;

                        for (uint h = 0; h < count; h++)
                        {
                            float[] points;
                            convexHullMesh.CopyPoints(h, out points);

                            var pointList = new List <Vector3>();

                            for (var v = 0; v < points.Length; v += 3)
                            {
                                var vert = new Vector3(points[v + 0], points[v + 1], points[v + 2]);
                                pointList.Add(vert);

                                vertexCountHull++;
                            }

                            hullsList.Add(pointList);

                            uint[] indices;
                            convexHullMesh.CopyIndices(h, out indices);

                            for (var t = 0; t < indices.Length; t += 3)
                            {
                                Utilities.Swap(ref indices[t], ref indices[t + 2]);
                            }

                            var indexList = new List <uint>(indices);

                            indicesList.Add(indexList);
                        }

                        convexHullMesh.Dispose();

                        commandContext.Logger.Info("For a total of " + vertexCountHull + " vertexes");
                    }
                }

                var runtimeShape = new PhysicsColliderShape {
                    Descriptions = descriptions
                };

                assetManager.Save(Url, runtimeShape);

                return(Task.FromResult(ResultStatus.Successful));
            }
Beispiel #19
0
            protected override Task <ResultStatus> DoCommandOverride(ICommandContext commandContext)
            {
                var contentManager = new ContentManager();

                var device = GraphicsDevice.New();

                var fallbackMaterial = Material.New(device, new MaterialDescriptor
                {
                    Attributes =
                    {
                        Diffuse      = new MaterialDiffuseMapFeature(new ComputeTextureColor()),
                        DiffuseModel = new MaterialDiffuseLambertModelFeature()
                    }
                });

                var loadSettings = new ContentManagerLoaderSettings
                {
                    ContentFilter = ContentManagerLoaderSettings.NewContentFilterByType(typeof(Mesh), typeof(Skeleton), typeof(Material), typeof(Prefab))
                };

                Prefab prefab;

                if (Parameters.Prefab == null)
                {
                    prefab = new Prefab();
                }
                else
                {
                    prefab = contentManager.Load <Prefab>(Parameters.Prefab.Location, loadSettings);
                    if (prefab == null)
                    {
                        throw new Exception("Failed to load prefab.");
                    }
                }

                var prefabModel = new Model();

                //The objective is to create 1 mesh per material/shadow params
                //1. We group by materials
                //2. Create a mesh per material (might need still more meshes if 16bit indexes or more then 32bit)

                var materials = new Dictionary <MaterialInstance, List <EntityChunk> >();

                var validEntities = new List <Entity>();

                foreach (var rootEntity in prefab.Entities)
                {
                    //collect sub entities as well
                    var collected = IterateTree(rootEntity, subEntity => subEntity.GetChildren()).ToArray();

                    //first pass, check if compatible with prefabmodel
                    foreach (var subEntity in collected)
                    {
                        //todo for now we collect everything with a model component
                        var modelComponent = subEntity.Get <ModelComponent>();

                        if (modelComponent?.Model == null || (modelComponent.Skeleton != null && modelComponent.Skeleton.Nodes.Length != 1))
                        {
                            continue;
                        }

                        var modelAsset = contentManager.Load <Model>(AttachedReferenceManager.GetUrl(modelComponent.Model), loadSettings);
                        if (modelAsset == null ||
                            modelAsset.Meshes.Any(x => x.Draw.PrimitiveType != PrimitiveType.TriangleList || x.Draw.VertexBuffers == null || x.Draw.VertexBuffers.Length != 1) ||
                            modelAsset.Materials.Any(x => x.Material != null && x.Material.HasTransparency) ||
                            modelComponent.Materials.Values.Any(x => x.HasTransparency)) //For now we limit only to TriangleList types and interleaved vertex buffers, also we skip transparent
                        {
                            commandContext.Logger.Info($"Skipped entity {subEntity.Name} since it's not compatible with PrefabModel.");
                            continue;
                        }

                        validEntities.Add(subEntity);
                    }
                }

                foreach (var subEntity in validEntities)
                {
                    var modelComponent = subEntity.Get <ModelComponent>();
                    var modelAsset     = contentManager.Load <Model>(AttachedReferenceManager.GetUrl(modelComponent.Model), loadSettings);
                    for (var index = 0; index < modelAsset.Materials.Count; index++)
                    {
                        var material = modelAsset.Materials[index];
                        var mat      = ExtractMaterialInstance(material, index, modelComponent, fallbackMaterial);

                        var chunk = new EntityChunk {
                            Entity = subEntity, Model = modelAsset, MaterialIndex = index
                        };

                        List <EntityChunk> entities;
                        if (materials.TryGetValue(mat, out entities))
                        {
                            entities.Add(chunk);
                        }
                        else
                        {
                            materials.Add(mat, new List <EntityChunk> {
                                chunk
                            });
                        }
                    }
                }

                foreach (var material in materials)
                {
                    ProcessMaterial(contentManager, material.Value, material.Key, prefabModel);
                }

                // split the meshes if necessary
                prefabModel.Meshes = SplitExtensions.SplitMeshes(prefabModel.Meshes, renderingSettings.DefaultGraphicsProfile > GraphicsProfile.Level_9_3);

                //handle boundng box/sphere
                var modelBoundingBox    = prefabModel.BoundingBox;
                var modelBoundingSphere = prefabModel.BoundingSphere;

                foreach (var mesh in prefabModel.Meshes)
                {
                    var vertexBuffers = mesh.Draw.VertexBuffers;
                    if (vertexBuffers.Length > 0)
                    {
                        // Compute local mesh bounding box (no node transformation)
                        var matrix = Matrix.Identity;
                        mesh.BoundingBox = vertexBuffers[0].ComputeBounds(ref matrix, out mesh.BoundingSphere);

                        // Compute model bounding box (includes node transformation)
                        BoundingSphere meshBoundingSphere;
                        var            meshBoundingBox = vertexBuffers[0].ComputeBounds(ref matrix, out meshBoundingSphere);
                        BoundingBox.Merge(ref modelBoundingBox, ref meshBoundingBox, out modelBoundingBox);
                        BoundingSphere.Merge(ref modelBoundingSphere, ref meshBoundingSphere, out modelBoundingSphere);
                    }

                    mesh.Draw.CompactIndexBuffer();
                }
                prefabModel.BoundingBox    = modelBoundingBox;
                prefabModel.BoundingSphere = modelBoundingSphere;

                //save
                contentManager.Save(Url, prefabModel);

                device.Dispose();

                return(Task.FromResult(ResultStatus.Successful));
            }