Beispiel #1
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,
                                    CacheSettings = new StaticColliderCacheSettings(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;
                                        }
                                        else if (desc is HeightfieldColliderShapeDesc)
                                        {
                                            var heightfieldDesc = desc as HeightfieldColliderShapeDesc;
                                            var initialHeights  = heightfieldDesc?.InitialHeights as HeightfieldHeightDataFromHeightmap;

                                            if (initialHeights?.Heightmap != null)
                                            {
                                                var    assetReference = AttachedReferenceManager.GetAttachedReference(initialHeights.Heightmap);
                                                object loadedHeightfieldInitialData;
                                                if (!loadedHeightfieldInitialDatas.TryGetValue(assetReference.Url, out loadedHeightfieldInitialData))
                                                {
                                                    loadedHeightfieldInitialData = contentManager.Load(typeof(Heightmap), assetReference.Url);
                                                    loadedHeightfieldInitialDatas.Add(assetReference.Url, loadedHeightfieldInitialData);
                                                }
                                                initialHeights.Heightmap = loadedHeightfieldInitialData as Heightmap;
                                            }
                                        }
                                    }
                                }

                                // Hash collider for ComputeParameterHash
                                sceneHash = (sceneHash * 397) ^ Xenko.Navigation.NavigationMeshBuildUtils.HashEntityCollider(colliderComponent, asset.IncludedCollisionGroups);
                            }
                        }
                    }
                    sceneCloned = true;
                }
            }
        /// <summary>
        /// Gets the serialized data version of this <see cref="Texture"/>.
        /// </summary>
        /// <param name="texture">The texture.</param>
        /// <returns></returns>
        public static Image GetSerializationData(this Texture texture)
        {
            var attachedReference = AttachedReferenceManager.GetAttachedReference(texture);

            return((Image)attachedReference?.Data);
        }
Beispiel #3
0
        private async void OpenDefaultScene(SessionViewModel session)
        {
            var startupPackage = session.LocalPackages.OfType <ProjectViewModel>().SingleOrDefault(x => x.IsCurrentProject);

            if (startupPackage == null)
            {
                return;
            }

            var gameSettingsAsset = startupPackage.Assets.FirstOrDefault(x => x.Url == Assets.GameSettingsAsset.GameSettingsLocation);

            if (gameSettingsAsset == null)
            {
                // Scan dependencies for game settings
                // TODO: Scanning order? (direct dependencies first)
                // TODO: Switch to using startupPackage.Dependencies view model instead
                foreach (var dependency in startupPackage.PackageContainer.FlattenedDependencies)
                {
                    if (dependency.Package == null)
                    {
                        continue;
                    }

                    var dependencyPackageViewModel = session.AllPackages.First(x => x.Package == dependency.Package);
                    if (dependencyPackageViewModel == null)
                    {
                        continue;
                    }

                    gameSettingsAsset = dependencyPackageViewModel.Assets.FirstOrDefault(x => x.Url == Assets.GameSettingsAsset.GameSettingsLocation);
                    if (gameSettingsAsset != null)
                    {
                        break;
                    }
                }
            }

            if (gameSettingsAsset == null)
            {
                return;
            }

            var defaultScene = ((Assets.GameSettingsAsset)gameSettingsAsset?.Asset)?.DefaultScene;

            if (defaultScene is null)
            {
                return;
            }

            var defaultSceneReference = AttachedReferenceManager.GetAttachedReference(defaultScene);

            if (defaultSceneReference is null)
            {
                return;
            }

            var asset = session.GetAssetById(defaultSceneReference.Id);

            if (asset is null)
            {
                return;
            }

            Editor.Session.ActiveAssetView.SelectAssets(asset.Yield());

            await assetEditorsManager.OpenAssetEditorWindow(asset);
        }
        private object ExportModel(ICommandContext commandContext, ContentManager contentManager)
        {
            // Read from model file
            var modelSkeleton = LoadSkeleton(commandContext, contentManager); // we get model skeleton to compare it to real skeleton we need to map to

            AdjustSkeleton(modelSkeleton);
            var model = LoadModel(commandContext, contentManager);

            if (!CheckInputSlots(commandContext, model))
            {
                return(null);
            }

            // Apply materials
            foreach (var modelMaterial in Materials)
            {
                if (modelMaterial.MaterialInstance?.Material == null)
                {
                    commandContext.Logger.Verbose($"The material [{modelMaterial.Name}] is null in the list of materials.");
                }
                model.Materials.Add(modelMaterial.MaterialInstance);
            }

            model.BoundingBox = BoundingBox.Empty;

            Skeleton skeleton;

            if (SkeletonUrl != null)
            {
                // Load skeleton and process it
                skeleton = contentManager.Load <Skeleton>(SkeletonUrl);

                // Assign skeleton to model
                model.Skeleton = AttachedReferenceManager.CreateProxyObject <Skeleton>(AssetId.Empty, SkeletonUrl);
            }
            else
            {
                skeleton = null;
            }

            var skeletonMapping = new SkeletonMapping(skeleton, modelSkeleton);

            // Refresh skeleton updater with model skeleton
            var hierarchyUpdater = new SkeletonUpdater(modelSkeleton);

            hierarchyUpdater.UpdateMatrices();

            // Move meshes in the new nodes
            foreach (var mesh in model.Meshes)
            {
                // Apply scale import on meshes
                if (!MathUtil.NearEqual(ScaleImport, 1.0f))
                {
                    var transformationMatrix = Matrix.Scaling(ScaleImport);
                    for (int vbIdx = 0; vbIdx < mesh.Draw.VertexBuffers.Length; vbIdx++)
                    {
                        mesh.Draw.VertexBuffers[vbIdx].TransformBuffer(ref transformationMatrix);
                    }
                }

                var skinning = mesh.Skinning;
                if (skinning != null)
                {
                    // Update node mapping
                    // Note: we only remap skinning matrices, but we could directly remap skinning bones instead
                    for (int i = 0; i < skinning.Bones.Length; ++i)
                    {
                        var linkNodeIndex    = skinning.Bones[i].NodeIndex;
                        var newLinkNodeIndex = skeletonMapping.SourceToSource[linkNodeIndex];

                        var nodeIndex    = mesh.NodeIndex;
                        var newNodeIndex = skeletonMapping.SourceToSource[mesh.NodeIndex];

                        skinning.Bones[i].NodeIndex = skeletonMapping.SourceToTarget[linkNodeIndex];

                        // Adjust scale import
                        if (!MathUtil.NearEqual(ScaleImport, 1.0f))
                        {
                            skinning.Bones[i].LinkToMeshMatrix.TranslationVector = skinning.Bones[i].LinkToMeshMatrix.TranslationVector * ScaleImport;
                        }

                        // If it was remapped, we also need to update matrix
                        if (nodeIndex != newNodeIndex)
                        {
                            // Update mesh part
                            var transformMatrix = CombineMatricesFromNodeIndices(hierarchyUpdater.NodeTransformations, newNodeIndex, nodeIndex);
                            transformMatrix.Invert();
                            skinning.Bones[i].LinkToMeshMatrix = Matrix.Multiply(transformMatrix, skinning.Bones[i].LinkToMeshMatrix);
                        }

                        if (newLinkNodeIndex != linkNodeIndex)
                        {
                            // Update link part
                            var transformLinkMatrix = CombineMatricesFromNodeIndices(hierarchyUpdater.NodeTransformations, newLinkNodeIndex, linkNodeIndex);
                            skinning.Bones[i].LinkToMeshMatrix = Matrix.Multiply(skinning.Bones[i].LinkToMeshMatrix, transformLinkMatrix);
                        }
                    }
                }

                // Check if there was a remap using model skeleton
                if (skeletonMapping.SourceToSource[mesh.NodeIndex] != mesh.NodeIndex)
                {
                    // Transform vertices
                    var transformationMatrix = CombineMatricesFromNodeIndices(hierarchyUpdater.NodeTransformations, skeletonMapping.SourceToSource[mesh.NodeIndex], mesh.NodeIndex);
                    for (int vbIdx = 0; vbIdx < mesh.Draw.VertexBuffers.Length; vbIdx++)
                    {
                        mesh.Draw.VertexBuffers[vbIdx].TransformBuffer(ref transformationMatrix);
                    }

                    // Check if geometry is inverted, to know if we need to reverse winding order
                    // TODO: What to do if there is no index buffer? We should create one... (not happening yet)
                    if (mesh.Draw.IndexBuffer == null)
                    {
                        throw new InvalidOperationException();
                    }

                    Matrix  rotation;
                    Vector3 scale, translation;
                    if (transformationMatrix.Decompose(out scale, out rotation, out translation) &&
                        scale.X * scale.Y * scale.Z < 0)
                    {
                        mesh.Draw.ReverseWindingOrder();
                    }
                }

                // Update new node index using real asset skeleton
                mesh.NodeIndex = skeletonMapping.SourceToTarget[mesh.NodeIndex];
            }

            // Merge meshes with same parent nodes, material and skinning
            var meshesByNodes = model.Meshes.GroupBy(x => x.NodeIndex).ToList();

            foreach (var meshesByNode in meshesByNodes)
            {
                // This logic to detect similar material is kept from old code; this should be reviewed/improved at some point
                foreach (var meshesPerDrawCall in meshesByNode.GroupBy(x => x,
                                                                       new AnonymousEqualityComparer <Mesh>((x, y) =>
                                                                                                            x.MaterialIndex == y.MaterialIndex && // Same material
                                                                                                            ArrayExtensions.ArraysEqual(x.Skinning?.Bones, y.Skinning?.Bones) && // Same bones
                                                                                                            CompareParameters(model, x, y) && // Same parameters
                                                                                                            CompareShadowOptions(model, x, y), // Same shadow parameters
                                                                                                            x => 0)).ToList())
                {
                    if (meshesPerDrawCall.Count() == 1)
                    {
                        // Nothing to group, skip to next entry
                        continue;
                    }

                    // Remove old meshes
                    foreach (var mesh in meshesPerDrawCall)
                    {
                        model.Meshes.Remove(mesh);
                    }

                    // Add new combined mesh(es)
                    var baseMesh    = meshesPerDrawCall.First();
                    var newMeshList = meshesPerDrawCall.Select(x => x.Draw).ToList().GroupDrawData(Allow32BitIndex);

                    foreach (var generatedMesh in newMeshList)
                    {
                        model.Meshes.Add(new Mesh(generatedMesh, baseMesh.Parameters)
                        {
                            MaterialIndex = baseMesh.MaterialIndex,
                            Name          = baseMesh.Name,
                            Draw          = generatedMesh,
                            NodeIndex     = baseMesh.NodeIndex,
                            Skinning      = baseMesh.Skinning,
                        });
                    }
                }
            }

            // split the meshes if necessary
            model.Meshes = SplitExtensions.SplitMeshes(model.Meshes, Allow32BitIndex);

            // Refresh skeleton updater with asset skeleton
            hierarchyUpdater = new SkeletonUpdater(skeleton);
            hierarchyUpdater.UpdateMatrices();

            // bounding boxes
            var modelBoundingBox    = model.BoundingBox;
            var modelBoundingSphere = model.BoundingSphere;

            foreach (var mesh in model.Meshes)
            {
                var vertexBuffers = mesh.Draw.VertexBuffers;
                for (int vbIdx = 0; vbIdx < vertexBuffers.Length; vbIdx++)
                {
                    // Compute local mesh bounding box (no node transformation)
                    Matrix matrix = Matrix.Identity;
                    mesh.BoundingBox = vertexBuffers[vbIdx].ComputeBounds(ref matrix, out mesh.BoundingSphere);

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

                // TODO: temporary Always try to compact
                mesh.Draw.CompactIndexBuffer();
            }
            model.BoundingBox    = modelBoundingBox;
            model.BoundingSphere = modelBoundingSphere;

            // Count unique meshes (they can be shared)
            var uniqueDrawMeshes = model.Meshes.Select(x => x.Draw).Distinct();

            // Count unique vertex buffers and squish them together in a single buffer
            var uniqueVB = uniqueDrawMeshes.SelectMany(x => x.VertexBuffers).Distinct().ToList();

            var vbMap                    = new Dictionary <VertexBufferBinding, VertexBufferBinding>();
            var sizeVertexBuffer         = uniqueVB.Select(x => x.Buffer.GetSerializationData().Content.Length).Sum();
            var vertexBuffer             = new BufferData(BufferFlags.VertexBuffer, new byte[sizeVertexBuffer]);
            var vertexBufferSerializable = vertexBuffer.ToSerializableVersion();

            var vertexBufferNextIndex = 0;

            foreach (var vbBinding in uniqueVB)
            {
                var oldVertexBuffer = vbBinding.Buffer.GetSerializationData().Content;
                Array.Copy(oldVertexBuffer, 0, vertexBuffer.Content, vertexBufferNextIndex, oldVertexBuffer.Length);

                vbMap.Add(vbBinding, new VertexBufferBinding(vertexBufferSerializable, vbBinding.Declaration, vbBinding.Count, vbBinding.Stride, vertexBufferNextIndex));

                vertexBufferNextIndex += oldVertexBuffer.Length;
            }

            // Count unique index buffers and squish them together in a single buffer
            var uniqueIB        = uniqueDrawMeshes.Select(x => x.IndexBuffer).Distinct().ToList();
            var sizeIndexBuffer = 0;

            foreach (var ibBinding in uniqueIB)
            {
                // Make sure 32bit indices are properly aligned to 4 bytes in case the last alignment was 2 bytes
                if (ibBinding.Is32Bit && sizeIndexBuffer % 4 != 0)
                {
                    sizeIndexBuffer += 2;
                }

                sizeIndexBuffer += ibBinding.Buffer.GetSerializationData().Content.Length;
            }

            var ibMap                   = new Dictionary <IndexBufferBinding, IndexBufferBinding>();
            var indexBuffer             = new BufferData(BufferFlags.IndexBuffer, new byte[sizeIndexBuffer]);
            var indexBufferSerializable = indexBuffer.ToSerializableVersion();
            var indexBufferNextIndex    = 0;

            foreach (var ibBinding in uniqueIB)
            {
                var oldIndexBuffer = ibBinding.Buffer.GetSerializationData().Content;

                // Make sure 32bit indices are properly aligned to 4 bytes in case the last alignment was 2 bytes
                if (ibBinding.Is32Bit && indexBufferNextIndex % 4 != 0)
                {
                    indexBufferNextIndex += 2;
                }

                Array.Copy(oldIndexBuffer, 0, indexBuffer.Content, indexBufferNextIndex, oldIndexBuffer.Length);

                ibMap.Add(ibBinding, new IndexBufferBinding(indexBufferSerializable, ibBinding.Is32Bit, ibBinding.Count, indexBufferNextIndex));

                indexBufferNextIndex += oldIndexBuffer.Length;
            }

            // Assign new vertex and index buffer bindings
            foreach (var drawMesh in uniqueDrawMeshes)
            {
                for (int i = 0; i < drawMesh.VertexBuffers.Length; i++)
                {
                    drawMesh.VertexBuffers[i] = vbMap[drawMesh.VertexBuffers[i]];
                }

                drawMesh.IndexBuffer = ibMap[drawMesh.IndexBuffer];
            }

            vbMap.Clear();
            ibMap.Clear();

            // Convert to Entity
            return(model);
        }
        /// <summary>
        /// Gets the serialized data version of this <see cref="Buffer"/>.
        /// </summary>
        /// <param name="buffer">The buffer.</param>
        /// <returns></returns>
        public static BufferData GetSerializationData(this Buffer buffer)
        {
            var attachedReference = AttachedReferenceManager.GetAttachedReference(buffer);

            return(attachedReference != null ? (BufferData)attachedReference.Data : null);
        }
Beispiel #6
0
        /// <summary>
        /// Finds an asset from its attached reference.
        /// It will first try by id, then location.
        /// </summary>
        /// <param name="package">The package.</param>
        /// <param name="obj">The object containing the attached reference.</param>
        /// <returns>An <see cref="AssetItem" /> or <c>null</c> if not found.</returns>
        public static AssetItem FindAssetFromAttachedReference(this Package package, object obj)
        {
            var attachedReference = AttachedReferenceManager.GetAttachedReference(obj);

            return(attachedReference != null?package.FindAsset(attachedReference) : null);
        }
Beispiel #7
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,
                                                                             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.GetOrDefault <RenderingSettings>().DisplayOrientation);
                }

                var assetManager = new ContentManager(MicrothreadLocalDatabases.ProviderService);

                assetManager.Save(Url, result);

                return(Task.FromResult(ResultStatus.Successful));
            }
        /// <summary>
        /// Checks if a default scene exists for this game package.
        /// </summary>
        /// <param name="log">The log to output the result of the validation.</param>
        public override void Run(ILogger log)
        {
            if (log == null)
            {
                throw new ArgumentNullException(nameof(log));
            }

            foreach (var package in Session.Packages)
            {
                // Make sure package has its assets loaded
                if (package.State < PackageState.AssetsReady)
                {
                    continue;
                }

                var hasGameExecutable = package.Profiles.SelectMany(profile => profile.ProjectReferences).Any(projectRef => projectRef.Type == ProjectType.Executable);
                if (!hasGameExecutable)
                {
                    continue;
                }

                // Find game settings
                var       gameSettingsAssetItem = package.Assets.Find(GameSettingsAsset.GameSettingsLocation);
                AssetItem defaultScene          = null;

                // If game settings is found, try to find default scene inside
                var defaultSceneRuntime   = ((GameSettingsAsset)gameSettingsAssetItem?.Asset)?.DefaultScene;
                var defaultSceneReference = AttachedReferenceManager.GetAttachedReference(defaultSceneRuntime);
                if (defaultSceneReference != null)
                {
                    // Find it either by Url or Id
                    defaultScene = package.Assets.Find(defaultSceneReference.Id) ?? package.Assets.Find(defaultSceneReference.Url);

                    // Check it is actually a scene asset
                    if (defaultScene != null && !(defaultScene.Asset is SceneAsset))
                    {
                        defaultScene = null;
                    }
                }

                // Find or create default scene
                if (defaultScene == null)
                {
                    defaultScene = package.Assets.Find(GameSettingsAsset.DefaultSceneLocation);
                    if (defaultScene != null && !(defaultScene.Asset is SceneAsset))
                    {
                        defaultScene = null;
                    }
                }

                // Otherwise, try to find any scene
                if (defaultScene == null)
                {
                    defaultScene = package.Assets.FirstOrDefault(x => x.Asset is SceneAsset);
                }

                // Create game settings if not done yet
                if (gameSettingsAssetItem == null)
                {
                    log.Error(package, null, AssetMessageCode.AssetForPackageNotFound, GameSettingsAsset.GameSettingsLocation, package.FullPath.GetFileNameWithoutExtension());

                    var gameSettingsAsset = GameSettingsFactory.Create();

                    if (defaultScene != null)
                    {
                        gameSettingsAsset.DefaultScene = AttachedReferenceManager.CreateProxyObject <Scene>(defaultScene.Id, defaultScene.Location);
                    }

                    gameSettingsAssetItem = new AssetItem(GameSettingsAsset.GameSettingsLocation, gameSettingsAsset);
                    package.Assets.Add(gameSettingsAssetItem);

                    gameSettingsAssetItem.IsDirty = true;
                }
            }
        }
            public override void VisitDictionaryKeyValue(object dictionaryObj, DictionaryDescriptor descriptor, object key, ITypeDescriptor keyDescriptor, object value, ITypeDescriptor valueDescriptor)
            {
                base.VisitDictionaryKeyValue(dictionaryObj, descriptor, key, keyDescriptor, value, valueDescriptor);
                var assetReference    = value as AssetReference;
                var attachedReference = AttachedReferenceManager.GetAttachedReference(value);

                if (assetReference != null)
                {
                    AddLink(assetReference,
                            (guid, location) =>
                    {
                        var newValue = AssetReference.New(guid ?? assetReference.Id, location);
                        descriptor.SetValue(dictionaryObj, key, newValue);
                        return(newValue);
                    });
                }
                else if (attachedReference != null)
                {
                    AddLink(attachedReference,
                            (guid, location) =>
                    {
                        object newValue = guid.HasValue && guid.Value != AssetId.Empty ? AttachedReferenceManager.CreateProxyObject(descriptor.ValueType, guid.Value, location) : null;
                        descriptor.SetValue(dictionaryObj, key, newValue);
                        return(newValue);
                    });
                }
                else if (value is UFile)
                {
                    AddLink(value,
                            (guid, location) =>
                    {
                        var newValue = new UFile(location);
                        descriptor.SetValue(dictionaryObj, key, newValue);
                        return(newValue);
                    });
                }
                else if (value is UDirectory)
                {
                    AddLink(value,
                            (guid, location) =>
                    {
                        var newValue = new UDirectory(location);
                        descriptor.SetValue(dictionaryObj, key, newValue);
                        return(newValue);
                    });
                }
            }
Beispiel #10
0
            public override void VisitCollectionItem(IEnumerable collection, CollectionDescriptor descriptor, int index, object item, ITypeDescriptor itemDescriptor)
            {
                base.VisitCollectionItem(collection, descriptor, index, item, itemDescriptor);
                var assetReference    = item as AssetReference;
                var assetBase         = item as AssetBase;
                var attachedReference = AttachedReferenceManager.GetAttachedReference(item);

                // We cannot set links if we do not have indexer accessor
                if (!descriptor.HasIndexerAccessors)
                {
                    return;
                }

                if (assetReference != null)
                {
                    AddLink(assetReference, (guid, location) =>
                    {
                        var link = AssetReference.New(descriptor.ElementType, guid ?? assetReference.Id, location);
                        descriptor.SetValue(collection, index, link);
                        return(link);
                    });
                }
                else if (assetBase != null)
                {
                    AddLink(assetBase, (guid, location) =>
                    {
                        var link = new AssetBase(location, assetBase.Asset);
                        descriptor.SetValue(collection, index, link);
                        return(link);
                    });
                }
                else if (attachedReference != null)
                {
                    AddLink(attachedReference, (guid, location) =>
                    {
                        var link = guid.HasValue && guid.Value != Guid.Empty ? AttachedReferenceManager.CreateProxyObject(descriptor.ElementType, guid.Value, location) : null;
                        if (link != null)
                        {
                            IdentifiableHelper.SetId(link, IdentifiableHelper.GetId(item));
                        }
                        descriptor.SetValue(collection, index, link);
                        return(link);
                    });
                }
                else if (item is UFile)
                {
                    AddLink(item, (guid, location) =>
                    {
                        var link = new UFile(location);
                        descriptor.SetValue(collection, index, link);
                        return(link);
                    });
                }
                else if (item is UDirectory)
                {
                    AddLink(item, (guid, location) =>
                    {
                        var link = new UDirectory(location);
                        descriptor.SetValue(collection, index, link);
                        return(link);
                    });
                }
            }
            protected override Task <ResultStatus> DoCommandOverride(ICommandContext commandContext)
            {
                var assetManager = new ContentManager(MicrothreadLocalDatabases.ProviderService);

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

                var validShapes = 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 validShapes 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,
                        Decomposition = convexHullDesc.Decomposition,
                    };

                    // 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 (!string.IsNullOrEmpty(vertexBufferRef.Url))
                            {
                                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 (!string.IsNullOrEmpty(indexBufferRef.Url))
                            {
                                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.Decomposition.Depth,
                            PosSampling   = convexHullDesc.Decomposition.PosSampling,
                            PosRefine     = convexHullDesc.Decomposition.PosRefine,
                            AngleSampling = convexHullDesc.Decomposition.AngleSampling,
                            AngleRefine   = convexHullDesc.Decomposition.AngleRefine,
                            Alpha         = convexHullDesc.Decomposition.Alpha,
                            Threshold     = convexHullDesc.Decomposition.Threshold,
                            SimpleHull    = !convexHullDesc.Decomposition.Enabled,
                        };

                        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)
                            {
                                Core.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);

                assetManager.Save(Url, runtimeShape);

                return(Task.FromResult(ResultStatus.Successful));
            }
        protected override async Task <bool> PrepareAssetCreation(AssetTemplateGeneratorParameters parameters)
        {
            var result = await base.PrepareAssetCreation(parameters);

            if (!result)
            {
                return(false);
            }

            var files = parameters.Tags.Get(SourceFilesPathKey);

            if (files == null)
            {
                return(true);
            }

            var showDeduplicateMaterialsCheckBox = files.Any(x => ImportAssimpCommand.IsSupportingExtensions(x.GetFileExtension()));
            var showFbxDedupeNotSupportedWarning = showDeduplicateMaterialsCheckBox && files.Any(x => ImportFbxCommand.IsSupportingExtensions(x.GetFileExtension()));
            // Load settings from the last time this template was used for this project
            var profile = parameters.Package.UserSettings.Profile;
            var window  = new ModelAssetTemplateWindow
            {
                Parameters =
                {
                    ImportMaterials                  = ModelFromFileTemplateSettings.ImportMaterials.GetValue(profile,      true),
                    ShowDeduplicateMaterialsCheckBox = showDeduplicateMaterialsCheckBox,
                    ShowFbxDedupeNotSupportedWarning = showFbxDedupeNotSupportedWarning,
                    DeduplicateMaterials             = ModelFromFileTemplateSettings.DeduplicateMaterials.GetValue(profile, true),
                    ImportTextures = ModelFromFileTemplateSettings.ImportTextures.GetValue(profile,       true),
                    ImportSkeleton = ModelFromFileTemplateSettings.ImportSkeleton.GetValue(profile,       true)
                }
            };

            var skeletonId = ModelFromFileTemplateSettings.DefaultSkeleton.GetValue();
            var skeleton   = SessionViewModel.Instance?.GetAssetById(skeletonId);

            if (skeleton != null)
            {
                window.Parameters.ReuseSkeleton   = true;
                window.Parameters.SkeletonToReuse = ContentReferenceHelper.CreateReference <Skeleton>(skeleton);
            }

            await window.ShowModal();

            if (window.Result == DialogResult.Cancel)
            {
                return(false);
            }

            // Apply settings
            var skeletonToReuse = window.Parameters.ReuseSkeleton ? window.Parameters.SkeletonToReuse : null;

            parameters.Tags.Set(ImportMaterialsKey, window.Parameters.ImportMaterials);
            parameters.Tags.Set(DeduplicateMaterialsKey, window.Parameters.DeduplicateMaterials);
            parameters.Tags.Set(ImportTexturesKey, window.Parameters.ImportTextures);
            parameters.Tags.Set(ImportSkeletonKey, window.Parameters.ImportSkeleton);
            parameters.Tags.Set(SkeletonToUseKey, skeletonToReuse);

            // Save settings
            ModelFromFileTemplateSettings.ImportMaterials.SetValue(window.Parameters.ImportMaterials, profile);
            ModelFromFileTemplateSettings.DeduplicateMaterials.SetValue(window.Parameters.DeduplicateMaterials, profile);
            ModelFromFileTemplateSettings.ImportTextures.SetValue(window.Parameters.ImportTextures, profile);
            ModelFromFileTemplateSettings.ImportSkeleton.SetValue(window.Parameters.ImportSkeleton, profile);
            skeletonId = AttachedReferenceManager.GetAttachedReference(skeletonToReuse)?.Id ?? AssetId.Empty;
            ModelFromFileTemplateSettings.DefaultSkeleton.SetValue(skeletonId, profile);
            parameters.Package.UserSettings.Save();

            return(true);
        }
Beispiel #13
0
            private static void ProcessMaterial(ContentManager manager, ICollection <EntityChunk> chunks, MaterialInstance material, Rendering.Model prefabModel)
            {
                //we need to futher group by VertexDeclaration
                var meshes = new Dictionary <VertexDeclaration, MeshData>();

                //actually create the mesh
                foreach (var chunk in chunks)
                {
                    foreach (var modelMesh in chunk.Model.Meshes)
                    {
                        //process only right material
                        if (modelMesh.MaterialIndex == chunk.MaterialIndex)
                        {
                            MeshData mesh;
                            if (!meshes.TryGetValue(modelMesh.Draw.VertexBuffers[0].Declaration, out mesh))
                            {
                                mesh = new MeshData {
                                    VertexStride = modelMesh.Draw.VertexBuffers[0].Stride
                                };
                                meshes.Add(modelMesh.Draw.VertexBuffers[0].Declaration, mesh);
                            }

                            //vertexes
                            var    vertexBufferRef = AttachedReferenceManager.GetAttachedReference(modelMesh.Draw.VertexBuffers[0].Buffer);
                            byte[] vertexData;
                            if (vertexBufferRef.Data != null)
                            {
                                vertexData = ((BufferData)vertexBufferRef.Data).Content;
                            }
                            else if (!vertexBufferRef.Url.IsNullOrEmpty())
                            {
                                var dataAsset = manager.Load <Graphics.Buffer>(vertexBufferRef.Url);
                                vertexData = dataAsset.GetSerializationData().Content;
                            }
                            else
                            {
                                throw new Exception($"Failed to get Vertex BufferData for entity {chunk.Entity.Name}'s model.");
                            }

                            //transform the vertexes according to the entity
                            var vertexDataCopy = vertexData.ToArray();
                            chunk.Entity.Transform.UpdateWorldMatrix(); //make sure matrix is computed
                            modelMesh.Draw.VertexBuffers[0].TransformBuffer(vertexDataCopy, ref chunk.Entity.Transform.WorldMatrix);

                            //add to the big single array
                            var vertexes = vertexDataCopy
                                           .Skip(modelMesh.Draw.VertexBuffers[0].Offset)
                                           .Take(modelMesh.Draw.VertexBuffers[0].Count * modelMesh.Draw.VertexBuffers[0].Stride)
                                           .ToArray();

                            mesh.VertexData.AddRange(vertexes);

                            //indices
                            var    indexBufferRef = AttachedReferenceManager.GetAttachedReference(modelMesh.Draw.IndexBuffer.Buffer);
                            byte[] indexData;
                            if (indexBufferRef.Data != null)
                            {
                                indexData = ((BufferData)indexBufferRef.Data).Content;
                            }
                            else if (!indexBufferRef.Url.IsNullOrEmpty())
                            {
                                var dataAsset = manager.Load <Graphics.Buffer>(indexBufferRef.Url);
                                indexData = dataAsset.GetSerializationData().Content;
                            }
                            else
                            {
                                throw new Exception("Failed to get Indices BufferData for entity {chunk.Entity.Name}'s model.");
                            }

                            var indexSize = modelMesh.Draw.IndexBuffer.Is32Bit ? sizeof(uint) : sizeof(ushort);

                            var indices = indexData
                                          .Skip(modelMesh.Draw.IndexBuffer.Offset)
                                          .Take(modelMesh.Draw.IndexBuffer.Count * indexSize)
                                          .ToArray();

                            //todo this code is not optimal, use unsafe

                            //must convert to 32bits
                            if (indexSize == sizeof(ushort))
                            {
                                var uintIndex = new List <byte>();
                                for (var i = 0; i < indices.Length; i += sizeof(ushort))
                                {
                                    var index = BitConverter.ToUInt16(indices, i);
                                    var bi    = BitConverter.GetBytes((uint)index);
                                    uintIndex.Add(bi[0]);
                                    uintIndex.Add(bi[1]);
                                    uintIndex.Add(bi[2]);
                                    uintIndex.Add(bi[3]);
                                }
                                indices = uintIndex.ToArray();
                            }

                            //need to offset the indices
                            for (var i = 0; i < indices.Length; i += sizeof(uint))
                            {
                                var index = BitConverter.ToUInt32(indices, i) + mesh.IndexOffset;
                                var bi    = BitConverter.GetBytes(index);
                                indices[i + 0] = bi[0];
                                indices[i + 1] = bi[1];
                                indices[i + 2] = bi[2];
                                indices[i + 3] = bi[3];
                            }

                            mesh.IndexOffset += modelMesh.Draw.VertexBuffers[0].Count;

                            mesh.IndexData.AddRange(indices);
                        }
                    }
                }

                //Sort out material
                var matIndex = prefabModel.Materials.Count;

                prefabModel.Materials.Add(material);

                foreach (var meshData in meshes)
                {
                    //todo need to take care of short index
                    var vertexArray = meshData.Value.VertexData.ToArray();
                    var indexArray  = meshData.Value.IndexData.ToArray();

                    var vertexCount = vertexArray.Length / meshData.Value.VertexStride;
                    var indexCount  = indexArray.Length / 4;

                    var gpuMesh = new Mesh
                    {
                        Draw = new MeshDraw {
                            PrimitiveType = PrimitiveType.TriangleList, DrawCount = indexCount, StartLocation = 0
                        },
                        MaterialIndex = matIndex
                    };

                    var vertexBuffer = new BufferData(BufferFlags.VertexBuffer, new byte[vertexArray.Length]);
                    var indexBuffer  = new BufferData(BufferFlags.IndexBuffer, new byte[indexArray.Length]);

                    var vertexBufferSerializable = vertexBuffer.ToSerializableVersion();
                    var indexBufferSerializable  = indexBuffer.ToSerializableVersion();

                    Array.Copy(vertexArray, vertexBuffer.Content, vertexArray.Length);
                    Array.Copy(indexArray, indexBuffer.Content, indexArray.Length);

                    gpuMesh.Draw.VertexBuffers    = new VertexBufferBinding[1];
                    gpuMesh.Draw.VertexBuffers[0] = new VertexBufferBinding(vertexBufferSerializable, meshData.Key, vertexCount);
                    gpuMesh.Draw.IndexBuffer      = new IndexBufferBinding(indexBufferSerializable, true, indexCount);

                    prefabModel.Meshes.Add(gpuMesh);
                }
            }
Beispiel #14
0
        private ObjectId GetHashId()
        {
            // This methods use the stream that is already filled-up by the standard binary serialization of the object
            // Here we add ids and overrides metadata informations to the stream in order to calculate an accurate id
            var stream = streamOrValueType as MemoryStream;

            if (stream != null)
            {
                // ------------------------------------------------------
                // Un-comment the following code to debug the ObjectId of the serialized version without taking into account overrides
                // ------------------------------------------------------
                //var savedPosition = stream.Position;
                //stream.Position = 0;
                //var intermediateHashId = ObjectId.FromBytes(stream.ToArray());
                //stream.Position = savedPosition;

                var writer = new BinarySerializationWriter(stream);
                Dictionary <string, OverrideType> overrides = null;
                List <string> orderedNames = null;
                foreach (var objectRef in objectReferences)
                {
                    // If the object is actually a reference to another asset, we can skip it as their won't be any overrides
                    if (AttachedReferenceManager.GetAttachedReference(objectRef) != null)
                    {
                        continue;
                    }

                    // Else gets the id if there are any (including shadows that are not part of the standard serialization)
                    var shadowObject = ShadowObject.GetOrCreate(objectRef);
                    if (shadowObject.IsIdentifiable)
                    {
                        // Get the shadow id (may be a non-shadow, so we may duplicate it in the stream (e.g Entity)
                        // but it should not be a big deal
                        var id = shadowObject.GetId(objectRef);
                        writer.Write(id);
                    }

                    // Dump all members with overrides informations
                    foreach (var item in shadowObject)
                    {
                        if (item.Key.Item2 == Override.OverrideKey)
                        {
                            // Use the member name to ensure a stable id
                            var memberName = ((IMemberDescriptor)item.Key.Item1).Name;
                            // Only creates the overrides dictionary if needed
                            if (overrides == null)
                            {
                                overrides = new Dictionary <string, OverrideType>();
                            }
                            overrides.Add(memberName, (OverrideType)item.Value);
                        }
                    }

                    // Write any overrides information to the stream
                    if (overrides != null)
                    {
                        // Collect names and order them by alphabetical order in order to make sure that we will get a stable id
                        // (Dictionary doesn't ensure order)
                        if (orderedNames == null)
                        {
                            orderedNames = new List <string>();
                        }
                        orderedNames.Clear();
                        foreach (var entry in overrides)
                        {
                            orderedNames.Add(entry.Key);
                        }
                        orderedNames.Sort();

                        // Write all overrides for the current object reference
                        foreach (var name in orderedNames)
                        {
                            writer.Write(name);
                            // Write the override as an int
                            writer.Write((int)overrides[name]);
                        }

                        // Clear overrides for next entry
                        overrides.Clear();
                    }
                }

                writer.Flush();
                stream.Position = 0;

                return(ObjectId.FromBytes(stream.ToArray()));
            }

            return(ObjectId.Empty);
        }
        private void SerializeObject(Queue <SerializeOperation> serializeOperations, string url, object obj, bool publicReference)
        {
            // Don't create context in case we don't want to serialize referenced objects
            //if (!SerializeReferencedObjects && obj != RootObject)
            //    return null;

            // Already saved?
            // TODO: Ref counting? Should we change it on save? Probably depends if we cache or not.
            if (LoadedAssetReferences.ContainsKey(obj))
            {
                return;
            }

            var serializer = Serializer.GetSerializer(null, obj.GetType());

            if (serializer == null)
            {
                throw new InvalidOperationException(string.Format("Content serializer for {0} could not be found.", obj.GetType()));
            }

            var contentSerializerContext = new ContentSerializerContext(url, ArchiveMode.Serialize, this);

            using (var stream = FileProvider.OpenStream(url, VirtualFileMode.Create, VirtualFileAccess.Write))
            {
                var streamWriter = new BinarySerializationWriter(stream);
                PrepareSerializerContext(contentSerializerContext, streamWriter.Context);

                ChunkHeader header = null;

                // Allocate space in the stream, and also include header version in the hash computation, which is better
                // If serialization type is null, it means there should be no header.
                var serializationType = serializer.SerializationType;
                if (serializationType != null)
                {
                    header      = new ChunkHeader();
                    header.Type = serializer.SerializationType.AssemblyQualifiedName;
                    header.Write(streamWriter);
                    header.OffsetToObject = (int)streamWriter.NativeStream.Position;
                }

                contentSerializerContext.SerializeContent(streamWriter, serializer, obj);

                // Write references and updated header
                if (header != null)
                {
                    header.OffsetToReferences = (int)streamWriter.NativeStream.Position;
                    contentSerializerContext.SerializeReferences(streamWriter);

                    // Move back to the pre-allocated header position in the steam
                    stream.Seek(0, SeekOrigin.Begin);

                    // Write actual header.
                    header.Write(new BinarySerializationWriter(stream));
                }
            }

            var assetReference = new Reference(url, publicReference);

            SetAssetObject(assetReference, obj);

            // Process content references
            // TODO: Should we work at ChunkReference level?
            foreach (var contentReference in contentSerializerContext.ContentReferences)
            {
                if (contentReference.ObjectValue != null)
                {
                    var attachedReference = AttachedReferenceManager.GetAttachedReference(contentReference.ObjectValue);
                    if (attachedReference == null || attachedReference.IsProxy)
                    {
                        continue;
                    }

                    serializeOperations.Enqueue(new SerializeOperation(contentReference.Location, contentReference.ObjectValue, false));
                }
            }
        }
Beispiel #16
0
            public override void VisitObjectMember(object container, ObjectDescriptor containerDescriptor, IMemberDescriptor member, object value)
            {
                base.VisitObjectMember(container, containerDescriptor, member, value);
                var assetReference    = value as AssetReference;
                var attachedReference = AttachedReferenceManager.GetAttachedReference(value);

                if (assetReference != null)
                {
                    AddLink(assetReference,
                            (guid, location) =>
                    {
                        var newValue = AssetReference.New(guid ?? assetReference.Id, location);
                        member.Set(container, newValue);
                        return(newValue);
                    });
                }
                else if (attachedReference != null)
                {
                    AddLink(attachedReference,
                            (guid, location) =>
                    {
                        object newValue = guid.HasValue && guid.Value != AssetId.Empty ? AttachedReferenceManager.CreateProxyObject(member.Type, guid.Value, location) : null;
                        member.Set(container, newValue);
                        return(newValue);
                    });
                }
                else if (value is UFile)
                {
                    AddLink(value,
                            (guid, location) =>
                    {
                        var newValue = new UFile(location);
                        member.Set(container, newValue);
                        return(newValue);
                    });
                }
                else if (value is UDirectory)
                {
                    AddLink(value,
                            (guid, location) =>
                    {
                        var newValue = new UDirectory(location);
                        member.Set(container, newValue);
                        return(newValue);
                    });
                }
            }
Beispiel #17
0
        /// <summary>
        /// Checks if a default scene exists for this game package.
        /// </summary>
        /// <param name="log">The log to output the result of the validation.</param>
        public override void Run(ILogger log)
        {
            if (log == null)
            {
                throw new ArgumentNullException("log");
            }

            foreach (var package in Session.Packages)
            {
                // Make sure package has its assets loaded
                if (package.State < PackageState.AssetsReady)
                {
                    continue;
                }

                var hasGameExecutable = package.Profiles.SelectMany(profile => profile.ProjectReferences).Any(projectRef => projectRef.Type == ProjectType.Executable);
                if (!hasGameExecutable)
                {
                    continue;
                }

                // Find game settings
                var       gameSettingsAssetItem = package.Assets.Find(GameSettingsAsset.GameSettingsLocation);
                AssetItem defaultScene          = null;

                // If game settings is found, try to find default scene inside
                if (gameSettingsAssetItem != null)
                {
                    var defaultSceneRuntime = ((GameSettingsAsset)gameSettingsAssetItem.Asset).DefaultScene;
                    if (defaultSceneRuntime != null)
                    {
                        var defaultSceneReference = AttachedReferenceManager.GetAttachedReference(defaultSceneRuntime);
                        if (defaultSceneReference != null)
                        {
                            // Find it either by Url or Id
                            defaultScene = package.Assets.Find(defaultSceneReference.Id) ?? package.Assets.Find(defaultSceneReference.Url);

                            // Check it is actually a scene asset
                            if (defaultScene != null && !(defaultScene.Asset is SceneAsset))
                            {
                                defaultScene = null;
                            }
                        }
                    }
                }

                // Find or create default scene
                if (defaultScene == null)
                {
                    defaultScene = package.Assets.Find(GameSettingsAsset.DefaultSceneLocation);
                    if (defaultScene != null && !(defaultScene.Asset is SceneAsset))
                    {
                        defaultScene = null;
                    }
                }

                // Otherwise, try to find any scene
                if (defaultScene == null)
                {
                    defaultScene = package.Assets.FirstOrDefault(x => x.Asset is SceneAsset);
                }

                // Nothing found, let's create an empty one
                if (defaultScene == null)
                {
                    log.Error(package, null, AssetMessageCode.DefaultSceneNotFound, null);

                    var defaultSceneName  = NamingHelper.ComputeNewName(GameSettingsAsset.DefaultSceneLocation, package.Assets, a => a.Location);
                    var defaultSceneAsset = SceneAsset.Create();

                    defaultScene = new AssetItem(defaultSceneName, defaultSceneAsset);
                    package.Assets.Add(defaultScene);
                    defaultScene.IsDirty = true;
                }

                // Create game settings if not done yet
                if (gameSettingsAssetItem == null)
                {
                    log.Error(package, null, AssetMessageCode.AssetNotFound, GameSettingsAsset.GameSettingsLocation);

                    var gameSettingsAsset = new GameSettingsAsset();

                    gameSettingsAsset.DefaultScene = AttachedReferenceManager.CreateSerializableVersion <Scene>(defaultScene.Id, defaultScene.Location);

                    gameSettingsAssetItem = new AssetItem(GameSettingsAsset.GameSettingsLocation, gameSettingsAsset);
                    package.Assets.Add(gameSettingsAssetItem);

                    gameSettingsAssetItem.IsDirty = true;
                }
            }
        }
Beispiel #18
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 == 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.Any(x => x != null && 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));
            }
Beispiel #19
0
        public static SkyboxResult Compile(SkyboxAsset asset, SkyboxGeneratorContext context)
        {
            if (asset == null)
            {
                throw new ArgumentNullException("asset");
            }
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }
            var result = new SkyboxResult {
                Skybox = new Skybox()
            };

            var parameters = context.Parameters;
            var skybox     = result.Skybox;

            skybox.Parameters = parameters;

            if (asset.Model != null)
            {
                var cubemap = ((SkyboxCubeMapModel)asset.Model).CubeMap;
                if (cubemap == null)
                {
                    return(result);
                }

                // load the skybox texture from the asset.
                var reference     = AttachedReferenceManager.GetAttachedReference(cubemap);
                var skyboxTexture = context.Content.Load <Texture>(BuildTextureForSkyboxGenerationLocation(reference.Url));
                if (skyboxTexture.Dimension != TextureDimension.TextureCube)
                {
                    result.Error("SkyboxGenerator: The texture used as skybox should be a Cubemap.");
                    return(result);
                }

                var shaderSource = asset.Model.Generate(context);
                parameters.Set(SkyboxKeys.Shader, shaderSource);

                // If we are using the skybox asset for lighting, we can compute it
                // TODO: This following code should be pluggable (like asset.Model.Generate(context);) but it is currently not
                if (asset.Usage != SkyboxUsage.Background)
                {
                    // -------------------------------------------------------------------
                    // Calculate Diffuse prefiltering
                    // -------------------------------------------------------------------
                    var lamberFiltering = new LambertianPrefilteringSHNoCompute(context.RenderContext)
                    {
                        HarmonicOrder = (int)asset.DiffuseSHOrder,
                        RadianceMap   = skyboxTexture
                    };
                    lamberFiltering.Draw(context.RenderDrawContext);

                    var coefficients = lamberFiltering.PrefilteredLambertianSH.Coefficients;

                    // TODO: MOVE THE COEFFICIENTS TO THE SphericalHarmonics type in Core.Mathematics
                    var PI4     = 4 * Math.PI;
                    var PI16    = 16 * Math.PI;
                    var PI64    = 64 * Math.PI;
                    var SQRT_PI = 1.77245385090551602729;

                    var bases = new float[coefficients.Length];
                    bases[0] = (float)(1.0 / (2.0 * SQRT_PI));

                    bases[1] = (float)(-Math.Sqrt(3.0 / PI4));
                    bases[2] = (float)(Math.Sqrt(3.0 / PI4));
                    bases[3] = (float)(-Math.Sqrt(3.0 / PI4));

                    bases[4] = (float)(Math.Sqrt(15.0 / PI4));
                    bases[5] = (float)(-Math.Sqrt(15.0 / PI4));
                    bases[6] = (float)(Math.Sqrt(5.0 / PI16));
                    bases[7] = (float)(-Math.Sqrt(15.0 / PI4));
                    bases[8] = (float)(Math.Sqrt(15.0 / PI16));

                    if (asset.DiffuseSHOrder == SkyboxPreFilteringDiffuseOrder.Order5)
                    {
                        bases[9]  = -(float)Math.Sqrt(7 / PI64);
                        bases[10] = (float)Math.Sqrt(105 / PI4);
                        bases[11] = -(float)Math.Sqrt(21 / PI16);
                        bases[12] = (float)Math.Sqrt(7 / PI16);
                        bases[13] = -(float)Math.Sqrt(42 / PI64);
                        bases[14] = (float)Math.Sqrt(105 / PI16);
                        bases[15] = -(float)Math.Sqrt(70 / PI64);

                        bases[16] = 3 * (float)Math.Sqrt(35 / PI16);
                        bases[17] = -3 * (float)Math.Sqrt(70 / PI64);
                        bases[18] = 3 * (float)Math.Sqrt(5 / PI16);
                        bases[19] = -3 * (float)Math.Sqrt(10 / PI64);
                        bases[20] = (float)(1.0 / (16.0 * SQRT_PI));
                        bases[21] = -3 * (float)Math.Sqrt(10 / PI64);
                        bases[22] = 3 * (float)Math.Sqrt(5 / PI64);
                        bases[23] = -3 * (float)Math.Sqrt(70 / PI64);
                        bases[24] = 3 * (float)Math.Sqrt(35 / (4 * PI64));
                    }

                    for (int i = 0; i < coefficients.Length; i++)
                    {
                        coefficients[i] = coefficients[i] * bases[i];
                    }

                    skybox.DiffuseLightingParameters.Set(SkyboxKeys.Shader, new ShaderClassSource("SphericalHarmonicsEnvironmentColor", lamberFiltering.HarmonicOrder));
                    skybox.DiffuseLightingParameters.Set(SphericalHarmonicsEnvironmentColorKeys.SphericalColors, coefficients);

                    // -------------------------------------------------------------------
                    // Calculate Specular prefiltering
                    // -------------------------------------------------------------------
                    var specularRadiancePrefilterGGX = new RadiancePrefilteringGGXNoCompute(context.RenderContext);

                    var textureSize = asset.SpecularCubeMapSize <= 0 ? 64 : asset.SpecularCubeMapSize;
                    textureSize = (int)Math.Pow(2, Math.Round(Math.Log(textureSize, 2)));
                    if (textureSize < 64)
                    {
                        textureSize = 64;
                    }

                    // TODO: Add support for HDR 32bits
                    var filteringTextureFormat = skyboxTexture.Format.IsHDR() ? skyboxTexture.Format : PixelFormat.R8G8B8A8_UNorm;

                    //var outputTexture = Texture.New2D(graphicsDevice, 256, 256, skyboxTexture.Format, TextureFlags.ShaderResource | TextureFlags.UnorderedAccess, 6);
                    using (var outputTexture = Texture.New2D(context.GraphicsDevice, textureSize, textureSize, true, filteringTextureFormat, TextureFlags.ShaderResource | TextureFlags.RenderTarget, 6)
                           )
                    {
                        specularRadiancePrefilterGGX.RadianceMap         = skyboxTexture;
                        specularRadiancePrefilterGGX.PrefilteredRadiance = outputTexture;
                        specularRadiancePrefilterGGX.Draw(context.RenderDrawContext);

                        var cubeTexture = Texture.NewCube(context.GraphicsDevice, textureSize, true, skyboxTexture.Format);
                        context.RenderDrawContext.CommandList.Copy(outputTexture, cubeTexture);

                        cubeTexture.SetSerializationData(cubeTexture.GetDataAsImage(context.RenderDrawContext.CommandList));

                        skybox.SpecularLightingParameters.Set(SkyboxKeys.Shader, new ShaderClassSource("RoughnessCubeMapEnvironmentColor"));
                        skybox.SpecularLightingParameters.Set(SkyboxKeys.CubeMap, cubeTexture);
                    }
                }
                // TODO: cubeTexture is not deallocated
            }

            return(result);
        }
Beispiel #20
0
            private static unsafe void ProcessMaterial(ContentManager manager, ICollection <EntityChunk> chunks, MaterialInstance material, Model prefabModel)
            {
                //we need to futher group by VertexDeclaration
                var meshes = new Dictionary <VertexDeclaration, MeshData>();

                //actually create the mesh
                foreach (var chunk in chunks)
                {
                    foreach (var modelMesh in chunk.Model.Meshes)
                    {
                        //process only right material
                        if (modelMesh.MaterialIndex == chunk.MaterialIndex)
                        {
                            MeshData mesh;
                            if (!meshes.TryGetValue(modelMesh.Draw.VertexBuffers[0].Declaration, out mesh))
                            {
                                mesh = new MeshData {
                                    VertexStride = modelMesh.Draw.VertexBuffers[0].Stride
                                };
                                meshes.Add(modelMesh.Draw.VertexBuffers[0].Declaration, mesh);
                            }

                            //vertexes
                            var    vertexBufferRef = AttachedReferenceManager.GetAttachedReference(modelMesh.Draw.VertexBuffers[0].Buffer);
                            byte[] vertexData;
                            if (vertexBufferRef.Data != null)
                            {
                                vertexData = ((BufferData)vertexBufferRef.Data).Content;
                            }
                            else if (!vertexBufferRef.Url.IsNullOrEmpty())
                            {
                                var dataAsset = manager.Load <Graphics.Buffer>(vertexBufferRef.Url);
                                vertexData = dataAsset.GetSerializationData().Content;
                            }
                            else
                            {
                                throw new Exception($"Failed to get Vertex BufferData for entity {chunk.Entity.Name}'s model.");
                            }

                            //transform the vertexes according to the entity
                            var vertexDataCopy = vertexData.ToArray();
                            chunk.Entity.Transform.UpdateWorldMatrix(); //make sure matrix is computed
                            var  worldMatrix       = chunk.Entity.Transform.WorldMatrix;
                            var  up                = Vector3.Cross(worldMatrix.Right, worldMatrix.Forward);
                            bool isScalingNegative = Vector3.Dot(worldMatrix.Up, up) < 0.0f;

                            modelMesh.Draw.VertexBuffers[0].TransformBuffer(vertexDataCopy, ref worldMatrix);

                            //add to the big single array
                            var vertexes = vertexDataCopy
                                           .Skip(modelMesh.Draw.VertexBuffers[0].Offset)
                                           .Take(modelMesh.Draw.VertexBuffers[0].Count * modelMesh.Draw.VertexBuffers[0].Stride)
                                           .ToArray();

                            mesh.VertexData.AddRange(vertexes);

                            //indices
                            var    indexBufferRef = AttachedReferenceManager.GetAttachedReference(modelMesh.Draw.IndexBuffer.Buffer);
                            byte[] indexData;
                            if (indexBufferRef.Data != null)
                            {
                                indexData = ((BufferData)indexBufferRef.Data).Content;
                            }
                            else if (!indexBufferRef.Url.IsNullOrEmpty())
                            {
                                var dataAsset = manager.Load <Graphics.Buffer>(indexBufferRef.Url);
                                indexData = dataAsset.GetSerializationData().Content;
                            }
                            else
                            {
                                throw new Exception("Failed to get Indices BufferData for entity {chunk.Entity.Name}'s model.");
                            }

                            var indexSize = modelMesh.Draw.IndexBuffer.Is32Bit ? sizeof(uint) : sizeof(ushort);

                            byte[] indices;
                            if (isScalingNegative)
                            {
                                // Get reversed winding order
                                modelMesh.Draw.GetReversedWindingOrder(out indices);
                                indices = indices.Skip(modelMesh.Draw.IndexBuffer.Offset)
                                          .Take(modelMesh.Draw.IndexBuffer.Count * indexSize)
                                          .ToArray();
                            }
                            else
                            {
                                // Get indices normally
                                indices = indexData
                                          .Skip(modelMesh.Draw.IndexBuffer.Offset)
                                          .Take(modelMesh.Draw.IndexBuffer.Count * indexSize)
                                          .ToArray();
                            }

                            // Convert indices to 32 bits
                            if (indexSize == sizeof(ushort))
                            {
                                var uintIndices = new byte[indices.Length * 2];
                                fixed(byte *psrc = indices)
                                fixed(byte *pdst = uintIndices)
                                {
                                    var src = (ushort *)psrc;
                                    var dst = (uint *)pdst;

                                    int numIndices = indices.Length / sizeof(ushort);

                                    for (var i = 0; i < numIndices; i++)
                                    {
                                        dst[i] = src[i];
                                    }
                                }
                                indices = uintIndices;
                            }

                            // Offset indices by mesh.IndexOffset
                            fixed(byte *pdst = indices)
                            {
                                var dst = (uint *)pdst;

                                int numIndices = indices.Length / sizeof(uint);

                                for (var i = 0; i < numIndices; i++)
                                {
                                    // Offset indices
                                    dst[i] += (uint)mesh.IndexOffset;
                                }
                            }

                            mesh.IndexOffset += modelMesh.Draw.VertexBuffers[0].Count;

                            mesh.IndexData.AddRange(indices);
                        }
                    }
                }

                //Sort out material
                var matIndex = prefabModel.Materials.Count;

                prefabModel.Materials.Add(material);

                foreach (var meshData in meshes)
                {
                    //todo need to take care of short index
                    var vertexArray = meshData.Value.VertexData.ToArray();
                    var indexArray  = meshData.Value.IndexData.ToArray();

                    var vertexCount = vertexArray.Length / meshData.Value.VertexStride;
                    var indexCount  = indexArray.Length / 4;

                    var gpuMesh = new Mesh
                    {
                        Draw = new MeshDraw {
                            PrimitiveType = PrimitiveType.TriangleList, DrawCount = indexCount, StartLocation = 0
                        },
                        MaterialIndex = matIndex
                    };

                    var vertexBuffer = new BufferData(BufferFlags.VertexBuffer, new byte[vertexArray.Length]);
                    var indexBuffer  = new BufferData(BufferFlags.IndexBuffer, new byte[indexArray.Length]);

                    var vertexBufferSerializable = vertexBuffer.ToSerializableVersion();
                    var indexBufferSerializable  = indexBuffer.ToSerializableVersion();

                    Array.Copy(vertexArray, vertexBuffer.Content, vertexArray.Length);
                    Array.Copy(indexArray, indexBuffer.Content, indexArray.Length);

                    gpuMesh.Draw.VertexBuffers    = new VertexBufferBinding[1];
                    gpuMesh.Draw.VertexBuffers[0] = new VertexBufferBinding(vertexBufferSerializable, meshData.Key, vertexCount);
                    gpuMesh.Draw.IndexBuffer      = new IndexBufferBinding(indexBufferSerializable, true, indexCount);

                    prefabModel.Meshes.Add(gpuMesh);
                }
            }
Beispiel #21
0
        public void TestMaterial()
        {
            var compiler = new EffectCompiler {
                UseFileSystem = true
            };

            compiler.SourceDirectories.Add(@"..\..\sources\engine\SiliconStudio.Xenko.Graphics\Shaders");
            compiler.SourceDirectories.Add(@"..\..\sources\engine\SiliconStudio.Xenko.Engine\Shaders");
            compiler.SourceDirectories.Add(@"..\..\sources\shaders\Core");
            compiler.SourceDirectories.Add(@"..\..\sources\shaders\Lights");
            compiler.SourceDirectories.Add(@"..\..\sources\shaders\Materials");
            compiler.SourceDirectories.Add(@"..\..\sources\shaders\Shadows");
            compiler.SourceDirectories.Add(@"..\..\sources\shaders\ComputeColor");
            compiler.SourceDirectories.Add(@"..\..\sources\shaders\Skinning");
            compiler.SourceDirectories.Add(@"..\..\sources\shaders\Shading");
            compiler.SourceDirectories.Add(@"..\..\sources\shaders\Transformation");
            compiler.SourceDirectories.Add(@"..\..\sources\shaders\Utils");
            var compilerParameters = new CompilerParameters {
                Platform = GraphicsPlatform.Direct3D11
            };

            var layers = new MaterialBlendLayers();

            layers.Add(new MaterialBlendLayer
            {
                BlendMap = new ComputeFloat(0.5f),
                Material = AttachedReferenceManager.CreateSerializableVersion <Material>(Guid.Empty, "fake")
            });

            var materialAsset = new MaterialAsset
            {
                Attributes = new MaterialAttributes()
                {
                    Diffuse = new MaterialDiffuseMapFeature()
                    {
                        DiffuseMap = new ComputeColor(Color4.White)
                    },
                    DiffuseModel = new MaterialDiffuseLambertModelFeature()
                },
                Layers = layers
            };

            var fakeAsset = new MaterialAsset
            {
                Attributes = new MaterialAttributes()
                {
                    Diffuse = new MaterialDiffuseMapFeature()
                    {
                        DiffuseMap = new ComputeColor(Color.Blue)
                    },
                }
            };

            var context = new MaterialGeneratorContext {
                FindAsset = reference => fakeAsset
            };
            var result = MaterialGenerator.Generate(new MaterialDescriptor {
                Attributes = materialAsset.Attributes, Layers = materialAsset.Layers
            }, context, "TestMaterial");

            compilerParameters.Set(MaterialKeys.PixelStageSurfaceShaders, result.Material.Parameters.Get(MaterialKeys.PixelStageSurfaceShaders));
            var directionalLightGroup = new ShaderClassSource("LightDirectionalGroup", 1);

            compilerParameters.Set(LightingKeys.DirectLightGroups, new List <ShaderSource> {
                directionalLightGroup
            });
            //compilerParameters.Set(LightingKeys.CastShadows, false);
            //compilerParameters.Set(MaterialParameters.HasSkinningPosition, true);
            //compilerParameters.Set(MaterialParameters.HasSkinningNormal, true);
            compilerParameters.Set(MaterialKeys.HasNormalMap, true);

            var results = compiler.Compile(new ShaderMixinGeneratorSource("XenkoEffectBase"), compilerParameters);

            Assert.IsFalse(results.HasErrors);
        }
Beispiel #22
0
            protected override Task <ResultStatus> DoCommandOverride(ICommandContext commandContext)
            {
                var    nodes = new List <SpriteStudioNode>();
                string modelName;

                if (!SpriteStudioXmlImport.ParseModel(Parameters.Source, nodes, out modelName))
                {
                    return(null);
                }

                var cells    = new List <SpriteStudioCell>();
                var textures = new List <UFile>();

                if (!SpriteStudioXmlImport.ParseCellMaps(Parameters.Source, textures, cells))
                {
                    return(null);
                }

                var anims = new List <SpriteStudioAnim>();

                if (!SpriteStudioXmlImport.ParseAnimations(Parameters.Source, anims))
                {
                    return(null);
                }

                var assetManager = new ContentManager();

                var sheet = new SpriteSheet();

                foreach (var cell in cells)
                {
                    var sprite = new Sprite(cell.Name, AttachedReferenceManager.CreateProxyObject <Texture>(AssetId.Empty, Parameters.BuildTextures[cell.TextureIndex]))
                    {
                        Region        = cell.Rectangle,
                        Center        = cell.Pivot,
                        IsTransparent = true
                    };
                    sheet.Sprites.Add(sprite);
                }

                var nodeMapping = nodes.Select((x, i) => new { Name = x.Name, Index = i }).ToDictionary(x => x.Name, x => x.Index);

                //fill up some basic data for our model using the first animation in the array
                var anim = anims[0];

                foreach (var data in anim.NodesData)
                {
                    int nodeIndex;
                    if (!nodeMapping.TryGetValue(data.Key, out nodeIndex))
                    {
                        continue;
                    }

                    var node = nodes[nodeIndex];

                    foreach (var pair in data.Value.Data)
                    {
                        var tag = pair.Key;
                        if (pair.Value.All(x => x["time"] != "0"))
                        {
                            continue;
                        }
                        var value = pair.Value.First()["value"]; //do we always have a frame 0? should be the case actually
                        switch (tag)
                        {
                        case "POSX":
                            node.BaseState.Position.X = float.Parse(value, CultureInfo.InvariantCulture);
                            break;

                        case "POSY":
                            node.BaseState.Position.Y = float.Parse(value, CultureInfo.InvariantCulture);
                            break;

                        case "ROTZ":
                            node.BaseState.RotationZ = MathUtil.DegreesToRadians(float.Parse(value, CultureInfo.InvariantCulture));
                            break;

                        case "PRIO":
                            node.BaseState.Priority = int.Parse(value, CultureInfo.InvariantCulture);
                            break;

                        case "SCLX":
                            node.BaseState.Scale.X = float.Parse(value, CultureInfo.InvariantCulture);
                            break;

                        case "SCLY":
                            node.BaseState.Scale.Y = float.Parse(value, CultureInfo.InvariantCulture);
                            break;

                        case "ALPH":
                            node.BaseState.Transparency = float.Parse(value, CultureInfo.InvariantCulture);
                            break;

                        case "HIDE":
                            node.BaseState.Hide = int.Parse(value, CultureInfo.InvariantCulture);
                            break;

                        case "FLPH":
                            node.BaseState.HFlipped = int.Parse(value, CultureInfo.InvariantCulture);
                            break;

                        case "FLPV":
                            node.BaseState.VFlipped = int.Parse(value, CultureInfo.InvariantCulture);
                            break;

                        case "CELL":
                            node.BaseState.SpriteId = int.Parse(value, CultureInfo.InvariantCulture);
                            break;

                        case "COLV":
                            var color = new Color4(Color.FromBgra(int.Parse(value, CultureInfo.InvariantCulture)));
                            node.BaseState.BlendColor = colorSpace == ColorSpace.Linear ? color.ToLinear() : color;
                            break;

                        case "COLB":
                            node.BaseState.BlendType = (SpriteStudioBlending)int.Parse(value, CultureInfo.InvariantCulture);
                            break;

                        case "COLF":
                            node.BaseState.BlendFactor = float.Parse(value, CultureInfo.InvariantCulture);
                            break;
                        }
                    }
                }

                var spriteStudioSheet = new SpriteStudioSheet
                {
                    NodesInfo   = nodes,
                    SpriteSheet = sheet
                };

                assetManager.Save(Url, spriteStudioSheet);

                return(Task.FromResult(ResultStatus.Successful));
            }
Beispiel #23
0
        public void TestMaterial()
        {
            var compiler = new EffectCompiler(TestHelper.CreateDatabaseProvider().FileProvider)
            {
                UseFileSystem = true
            };
            var currentPath = Core.PlatformFolders.ApplicationBinaryDirectory;

            compiler.SourceDirectories.Add(Path.Combine(currentPath, @"..\..\sources\engine\Xenko.Graphics\Shaders"));
            compiler.SourceDirectories.Add(Path.Combine(currentPath, @"..\..\sources\engine\Xenko.Engine\Rendering\Shaders"));
            compiler.SourceDirectories.Add(Path.Combine(currentPath, @"..\..\sources\engine\Xenko.Engine\Rendering\Core"));
            compiler.SourceDirectories.Add(Path.Combine(currentPath, @"..\..\sources\engine\Xenko.Engine\Rendering\Lights"));
            compiler.SourceDirectories.Add(Path.Combine(currentPath, @"..\..\sources\engine\Xenko.Engine\Rendering\Shadows"));
            compiler.SourceDirectories.Add(Path.Combine(currentPath, @"..\..\sources\engine\Xenko.Engine\Rendering\Materials\Shaders"));
            compiler.SourceDirectories.Add(Path.Combine(currentPath, @"..\..\sources\engine\Xenko.Engine\Rendering\Materials\ComputeColors\Shaders"));
            compiler.SourceDirectories.Add(Path.Combine(currentPath, @"..\..\sources\engine\Xenko.Engine\Rendering\Skinning"));
            compiler.SourceDirectories.Add(Path.Combine(currentPath, @"..\..\sources\engine\Xenko.Engine\Rendering\Shading"));
            compiler.SourceDirectories.Add(Path.Combine(currentPath, @"..\..\sources\engine\Xenko.Engine\Rendering\Transformation"));
            compiler.SourceDirectories.Add(Path.Combine(currentPath, @"..\..\sources\engine\Xenko.Engine\Rendering\Utils"));
            var compilerParameters = new CompilerParameters {
                EffectParameters = { Platform = GraphicsPlatform.OpenGL }
            };

            var layers = new MaterialBlendLayers();

            layers.Add(new MaterialBlendLayer
            {
                BlendMap = new ComputeFloat(0.5f),
                Material = AttachedReferenceManager.CreateProxyObject <Material>(AssetId.Empty, "fake")
            });

            var materialAsset = new MaterialAsset
            {
                Attributes = new MaterialAttributes()
                {
                    Diffuse = new MaterialDiffuseMapFeature()
                    {
                        DiffuseMap = new ComputeColor(Color4.White)
                    },
                    DiffuseModel = new MaterialDiffuseLambertModelFeature()
                },
                Layers = layers
            };

            var fakeAsset = new MaterialAsset
            {
                Attributes = new MaterialAttributes()
                {
                    Diffuse = new MaterialDiffuseMapFeature()
                    {
                        DiffuseMap = new ComputeColor(Color.Blue)
                    },
                }
            };

            var context = new MaterialGeneratorContext {
                FindAsset = reference => fakeAsset
            };
            var result = MaterialGenerator.Generate(new MaterialDescriptor {
                Attributes = materialAsset.Attributes, Layers = materialAsset.Layers
            }, context, "TestMaterial");

            compilerParameters.Set(MaterialKeys.PixelStageSurfaceShaders, result.Material.Passes[0].Parameters.Get(MaterialKeys.PixelStageSurfaceShaders));
            var directionalLightGroup = new ShaderClassSource("LightDirectionalGroup", 1);

            compilerParameters.Set(LightingKeys.DirectLightGroups, new ShaderSourceCollection {
                directionalLightGroup
            });
            //compilerParameters.Set(LightingKeys.CastShadows, false);
            //compilerParameters.Set(MaterialParameters.HasSkinningPosition, true);
            //compilerParameters.Set(MaterialParameters.HasSkinningNormal, true);
            compilerParameters.Set(MaterialKeys.HasNormalMap, true);

            var results = compiler.Compile(new ShaderMixinGeneratorSource("XenkoEffectBase"), compilerParameters);

            Assert.False(results.HasErrors);
        }
Beispiel #24
0
        public void CompilerVisitRuntimeType()
        {
            PackageSessionPublicHelper.FindAndSetMSBuildVersion();

            var package = new Package();
            // ReSharper disable once UnusedVariable - we need a package session to compile
            var packageSession = new PackageSession(package);
            var otherAssets    = new List <AssetItem>
            {
                new AssetItem("contentRB", new MyAssetContentType(0), package),
                new AssetItem("contentRA", new MyAssetContentType(1), package),
                new AssetItem("content0B", new MyAssetContentType(2), package),
                new AssetItem("content0M", new MyAssetContentType(3), package),
                new AssetItem("content0A", new MyAssetContentType(4), package),
                new AssetItem("content1B", new MyAssetContentType(5), package),
                new AssetItem("content1M", new MyAssetContentType(6), package),
                new AssetItem("content1A", new MyAssetContentType(7), package),
                new AssetItem("content2B", new MyAssetContentType(8), package),
                new AssetItem("content2M", new MyAssetContentType(9), package),
                new AssetItem("content2A", new MyAssetContentType(10), package),
                new AssetItem("content3B", new MyAssetContentType(11), package),
                new AssetItem("content3M", new MyAssetContentType(12), package),
                new AssetItem("content3A", new MyAssetContentType(13), package),
                new AssetItem("content4B", new MyAssetContentType(14), package),
                new AssetItem("content4M", new MyAssetContentType(15), package),
                new AssetItem("content4A", new MyAssetContentType(16), package),
            };

            var assetToVisit = new MyAsset1();

            assetToVisit.Before = AttachedReferenceManager.CreateProxyObject <MyContentType>(otherAssets[0].Id, otherAssets[0].Location);
            assetToVisit.Zafter = AttachedReferenceManager.CreateProxyObject <MyContentType>(otherAssets[1].Id, otherAssets[1].Location);
            assetToVisit.RuntimeTypes.Add(CreateRuntimeType(otherAssets[2], otherAssets[3], otherAssets[4]));
            assetToVisit.RuntimeTypes.Add(CreateRuntimeType(otherAssets[5], otherAssets[6], otherAssets[7]));
            assetToVisit.RuntimeTypes.Add(CreateRuntimeType(otherAssets[8], otherAssets[9], otherAssets[10]));
            assetToVisit.RuntimeTypes.Add(CreateRuntimeType(otherAssets[11], otherAssets[12], otherAssets[13]));
            assetToVisit.RuntimeTypes.Add(CreateRuntimeType(otherAssets[14], otherAssets[15], otherAssets[16]));
            assetToVisit.RuntimeTypes[0].A = assetToVisit.RuntimeTypes[1];
            assetToVisit.RuntimeTypes[0].B = assetToVisit.RuntimeTypes[2];
            assetToVisit.RuntimeTypes[1].A = assetToVisit.RuntimeTypes[3];
            assetToVisit.RuntimeTypes[1].B = assetToVisit.RuntimeTypes[4];

            otherAssets.ForEach(x => package.Assets.Add(x));
            var assetItem = new AssetItem("asset", assetToVisit, package);

            package.Assets.Add(assetItem);
            package.RootAssets.Add(new AssetReference(assetItem.Id, assetItem.Location));

            // Create context
            var context = new AssetCompilerContext {
                CompilationContext = typeof(AssetCompilationContext)
            };

            // Builds the project
            var assetBuilder = new PackageCompiler(new RootPackageAssetEnumerator(package));

            context.Properties.Set(BuildAssetNode.VisitRuntimeTypes, true);
            var assetBuildResult = assetBuilder.Prepare(context);

            Assert.Equal(16, assetBuildResult.BuildSteps.Count);
        }
        /// <summary>
        /// Sets the serialized data version of this <see cref="Buffer" />.
        /// </summary>
        /// <param name="buffer">The buffer.</param>
        /// <param name="bufferData">The buffer data.</param>
        public static void SetSerializationData(this Buffer buffer, BufferData bufferData)
        {
            var attachedReference = AttachedReferenceManager.GetOrCreateAttachedReference(buffer);

            attachedReference.Data = bufferData;
        }
Beispiel #26
0
        public static SkyboxResult Compile(SkyboxAsset asset, SkyboxGeneratorContext context)
        {
            if (asset == null)
            {
                throw new ArgumentNullException("asset");
            }
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }
            var result = new SkyboxResult {
                Skybox = new Skybox()
            };

            var parameters = context.Parameters;
            var skybox     = result.Skybox;

            skybox.Parameters = parameters;

            var cubemap = asset.CubeMap;

            if (cubemap == null)
            {
                return(result);
            }

            // load the skybox texture from the asset.
            var reference     = AttachedReferenceManager.GetAttachedReference(cubemap);
            var skyboxTexture = context.Content.Load <Texture>(BuildTextureForSkyboxGenerationLocation(reference.Url), ContentManagerLoaderSettings.StreamingDisabled);

            if (skyboxTexture.ViewDimension == TextureDimension.Texture2D)
            {
                var cubemapSize = (int)Math.Pow(2, Math.Ceiling(Math.Log(skyboxTexture.Width / 4) / Math.Log(2))); // maximum resolution is around horizontal middle line which composes 4 images.
                skyboxTexture = CubemapFromTextureRenderer.GenerateCubemap(context.Services, context.RenderDrawContext, skyboxTexture, cubemapSize);
            }
            else if (skyboxTexture.ViewDimension != TextureDimension.TextureCube)
            {
                result.Error($"SkyboxGenerator: The texture type ({skyboxTexture.ViewDimension}) used as skybox is not supported. Should be a Cubemap or a 2D texture.");
                return(result);
            }

            // If we are using the skybox asset for lighting, we can compute it
            // Specular lighting only?
            if (!asset.IsSpecularOnly)
            {
                // -------------------------------------------------------------------
                // Calculate Diffuse prefiltering
                // -------------------------------------------------------------------
                var lamberFiltering = new LambertianPrefilteringSHNoCompute(context.RenderContext)
                {
                    HarmonicOrder = (int)asset.DiffuseSHOrder,
                    RadianceMap   = skyboxTexture
                };
                lamberFiltering.Draw(context.RenderDrawContext);

                var coefficients = lamberFiltering.PrefilteredLambertianSH.Coefficients;
                for (int i = 0; i < coefficients.Length; i++)
                {
                    coefficients[i] = coefficients[i] * SphericalHarmonics.BaseCoefficients[i];
                }

                skybox.DiffuseLightingParameters.Set(SkyboxKeys.Shader, new ShaderClassSource("SphericalHarmonicsEnvironmentColor", lamberFiltering.HarmonicOrder));
                skybox.DiffuseLightingParameters.Set(SphericalHarmonicsEnvironmentColorKeys.SphericalColors, coefficients);
            }

            // -------------------------------------------------------------------
            // Calculate Specular prefiltering
            // -------------------------------------------------------------------
            var specularRadiancePrefilterGGX = new RadiancePrefilteringGGXNoCompute(context.RenderContext);

            var textureSize = asset.SpecularCubeMapSize <= 0 ? 64 : asset.SpecularCubeMapSize;

            textureSize = (int)Math.Pow(2, Math.Round(Math.Log(textureSize, 2)));
            if (textureSize < 64)
            {
                textureSize = 64;
            }

            // TODO: Add support for HDR 32bits
            var filteringTextureFormat = skyboxTexture.Format.IsHDR() ? skyboxTexture.Format : PixelFormat.R8G8B8A8_UNorm;

            //var outputTexture = Texture.New2D(graphicsDevice, 256, 256, skyboxTexture.Format, TextureFlags.ShaderResource | TextureFlags.UnorderedAccess, 6);
            using (var outputTexture = Texture.New2D(context.GraphicsDevice, textureSize, textureSize, true, filteringTextureFormat, TextureFlags.ShaderResource | TextureFlags.RenderTarget, 6))
            {
                specularRadiancePrefilterGGX.RadianceMap         = skyboxTexture;
                specularRadiancePrefilterGGX.PrefilteredRadiance = outputTexture;
                specularRadiancePrefilterGGX.Draw(context.RenderDrawContext);

                var cubeTexture = Texture.NewCube(context.GraphicsDevice, textureSize, true, filteringTextureFormat);
                context.RenderDrawContext.CommandList.Copy(outputTexture, cubeTexture);

                cubeTexture.SetSerializationData(cubeTexture.GetDataAsImage(context.RenderDrawContext.CommandList));

                skybox.SpecularLightingParameters.Set(SkyboxKeys.Shader, new ShaderClassSource("RoughnessCubeMapEnvironmentColor"));
                skybox.SpecularLightingParameters.Set(SkyboxKeys.CubeMap, cubeTexture);
            }
            // TODO: cubeTexture is not deallocated

            return(result);
        }
        /// <summary>
        /// Sets the serialized data version of this <see cref="Texture" />.
        /// </summary>
        /// <param name="texture">The texture.</param>
        /// <param name="image">The image.</param>
        public static void SetSerializationData(this Texture texture, Image image)
        {
            var attachedReference = AttachedReferenceManager.GetOrCreateAttachedReference(texture);

            attachedReference.Data = image;
        }
Beispiel #28
0
            protected override Task <ResultStatus> DoCommandOverride(ICommandContext commandContext)
            {
                var assetManager = new ContentManager(MicrothreadLocalDatabases.ProviderService);

                assetManager.Serializer.RegisterSerializer(new ImageTextureSerializer());

                // Create atlas texture
                Dictionary <SpriteInfo, PackedSpriteInfo> spriteToPackedSprite = null;

                // Generate texture atlas
                var isPacking = Parameters.SheetAsset.Packing.Enabled;

                if (isPacking)
                {
                    var resultStatus = CreateAtlasTextures(commandContext, out spriteToPackedSprite);

                    if (resultStatus != ResultStatus.Successful)
                    {
                        return(Task.FromResult(resultStatus));
                    }
                }

                var imageGroupData = new SpriteSheet();

                // add the sprite data to the sprite list.
                foreach (var image in Parameters.SheetAsset.Sprites)
                {
                    string           textureUrl;
                    RectangleF       region;
                    ImageOrientation orientation;

                    var borders = image.Borders;
                    var center  = image.Center + (image.CenterFromMiddle ? new Vector2(image.TextureRegion.Width, image.TextureRegion.Height) / 2 : Vector2.Zero);

                    if (isPacking &&
                        spriteToPackedSprite.ContainsKey(image))    // ensure that unpackable elements (invalid because of null size/texture) are properly added in the sheet using the normal path
                    {
                        var packedSprite            = spriteToPackedSprite[image];
                        var isOriginalSpriteRotated = image.Orientation == ImageOrientation.Rotated90;

                        region      = packedSprite.Region;
                        orientation = (packedSprite.IsRotated ^ isOriginalSpriteRotated) ? ImageOrientation.Rotated90 : ImageOrientation.AsIs;
                        textureUrl  = SpriteSheetAsset.BuildTextureAtlasUrl(Url, spriteToPackedSprite[image].AtlasTextureIndex);

                        // update the center and border info, if the packer rotated the sprite
                        // note: X->Left, Y->Top, Z->Right, W->Bottom.
                        if (packedSprite.IsRotated)
                        {
                            // turned the sprite CCW
                            if (isOriginalSpriteRotated)
                            {
                                var oldCenterX = center.X;
                                center.X = center.Y;
                                center.Y = region.Height - oldCenterX;

                                var oldBorderW = borders.W;
                                borders.W = borders.X;
                                borders.X = borders.Y;
                                borders.Y = borders.Z;
                                borders.Z = oldBorderW;
                            }
                            else // turned the sprite CW
                            {
                                var oldCenterX = center.X;
                                center.X = region.Width - center.Y;
                                center.Y = oldCenterX;

                                var oldBorderW = borders.W;
                                borders.W = borders.Z;
                                borders.Z = borders.Y;
                                borders.Y = borders.X;
                                borders.X = oldBorderW;
                            }
                        }
                    }
                    else
                    {
                        region      = image.TextureRegion;
                        orientation = image.Orientation;
                        Parameters.ImageToTextureUrl.TryGetValue(image, out textureUrl);
                    }

                    // Affect the texture
                    Texture texture = null;
                    if (textureUrl != null)
                    {
                        texture = AttachedReferenceManager.CreateProxyObject <Texture>(AssetId.Empty, textureUrl);
                    }
                    else
                    {
                        commandContext.Logger.Warning($"Image '{image.Name}' has an invalid image source file '{image.Source}', resulting texture will be null.");
                    }

                    imageGroupData.Sprites.Add(new Graphics.Sprite
                    {
                        Name          = image.Name,
                        Region        = region,
                        Orientation   = orientation,
                        Center        = center,
                        Borders       = borders,
                        PixelsPerUnit = new Vector2(image.PixelsPerUnit),
                        Texture       = texture,
                        IsTransparent = false,
                    });
                }

                // set the transparency information to all the sprites
                if (Parameters.SheetAsset.Alpha != AlphaFormat.None) // Skip the calculation when format is forced without alpha.
                {
                    var urlToTexImage = new Dictionary <string, Tuple <TexImage, Image> >();
                    using (var texTool = new TextureTool())
                    {
                        foreach (var sprite in imageGroupData.Sprites)
                        {
                            if (sprite.Texture == null) // the sprite texture is invalid
                            {
                                continue;
                            }

                            var textureUrl = AttachedReferenceManager.GetOrCreateAttachedReference(sprite.Texture).Url;
                            if (!urlToTexImage.ContainsKey(textureUrl))
                            {
                                var image       = assetManager.Load <Image>(textureUrl);
                                var newTexImage = texTool.Load(image, false); // the sRGB mode does not impact on the alpha level
                                texTool.Decompress(newTexImage, false);       // the sRGB mode does not impact on the alpha level
                                urlToTexImage[textureUrl] = Tuple.Create(newTexImage, image);
                            }
                            var texImage = urlToTexImage[textureUrl].Item1;

                            var region = new Rectangle
                            {
                                X = (int)Math.Floor(sprite.Region.X),
                                Y = (int)Math.Floor(sprite.Region.Y)
                            };
                            region.Width  = (int)Math.Ceiling(sprite.Region.Right) - region.X;
                            region.Height = (int)Math.Ceiling(sprite.Region.Bottom) - region.Y;

                            var alphaLevel = texTool.GetAlphaLevels(texImage, region, null, commandContext.Logger); // ignore transparent color key here because the input image has already been processed
                            sprite.IsTransparent = alphaLevel != AlphaLevels.NoAlpha;
                        }

                        // free all the allocated images
                        foreach (var tuple in urlToTexImage.Values)
                        {
                            tuple.Item1.Dispose();
                            assetManager.Unload(tuple.Item2);
                        }
                    }
                }

                // save the imageData into the data base
                assetManager.Save(Url, imageGroupData);

                return(Task.FromResult(ResultStatus.Successful));
            }
Beispiel #29
0
            public override void VisitArrayItem(Array array, ArrayDescriptor descriptor, int index, object item, ITypeDescriptor itemDescriptor)
            {
                base.VisitArrayItem(array, descriptor, index, item, itemDescriptor);
                var assetReference    = item as AssetReference;
                var assetBase         = item as AssetBase;
                var attachedReference = AttachedReferenceManager.GetAttachedReference(item);

                if (assetReference != null)
                {
                    AddLink(item,
                            (guid, location) =>
                    {
                        var newValue = AssetReference.New(descriptor.ElementType, guid ?? assetReference.Id, location);
                        array.SetValue(newValue, index);
                        return(newValue);
                    });
                }
                else if (assetBase != null)
                {
                    AddLink(item,
                            (guid, location) =>
                    {
                        var newValue = new AssetBase(location, assetBase.Asset);
                        array.SetValue(newValue, index);
                        return(newValue);
                    });
                }
                else if (attachedReference != null)
                {
                    AddLink(attachedReference,
                            (guid, location) =>
                    {
                        object newValue = guid.HasValue && guid.Value != Guid.Empty ? AttachedReferenceManager.CreateSerializableVersion(descriptor.ElementType, guid.Value, location) : null;
                        if (newValue != null)
                        {
                            IdentifiableHelper.SetId(newValue, IdentifiableHelper.GetId(item));
                        }
                        array.SetValue(newValue, index);
                        return(newValue);
                    });
                }
                else if (item is UFile)
                {
                    AddLink(item,
                            (guid, location) =>
                    {
                        var newValue = new UFile(location);
                        array.SetValue(newValue, index);
                        return(newValue);
                    });
                }
                else if (item is UDirectory)
                {
                    AddLink(item,
                            (guid, location) =>
                    {
                        var newValue = new UFile(location);
                        array.SetValue(newValue, index);
                        return(newValue);
                    });
                }
            }
        /// <summary>
        /// Creates default scene, with a ground plane, sphere, directional light and camera.
        /// If graphicsProfile is 10+, add cubemap light, otherwise ambient light.
        /// Also properly setup graphics pipeline depending on if HDR is set or not
        /// </summary>
        /// <param name="parameters">The parameters.</param>
        /// <param name="package">The package in which to create these assets.</param>
        private void CreateAndSetNewScene(SessionTemplateGeneratorParameters parameters, Package package, string projectGameName)
        {
            var logger = parameters.Logger;

            var graphicsProfile = parameters.GetTag(GraphicsProfileKey);
            var isHDR           = parameters.GetTag(IsHDRKey);

            if (graphicsProfile < GraphicsProfile.Level_10_0)
            {
                isHDR = false;
            }

            // Create the material for the sphere
            var sphereMaterial = new MaterialAsset
            {
                Attributes =
                {
                    Diffuse      = new MaterialDiffuseMapFeature(new ComputeColor(Color.FromBgra(0xFF8C8C8C))),
                    DiffuseModel = new MaterialDiffuseLambertModelFeature(),
                }
            };

            if (isHDR)
            {
                // Create HDR part of material
                sphereMaterial.Attributes.Specular      = new MaterialMetalnessMapFeature(new ComputeFloat(1.0f));
                sphereMaterial.Attributes.SpecularModel = new MaterialSpecularMicrofacetModelFeature();
                sphereMaterial.Attributes.MicroSurface  = new MaterialGlossinessMapFeature(new ComputeFloat(0.65f));
            }

            var sphereMaterialAssetItem = new AssetItem("Sphere Material", sphereMaterial);

            package.Assets.Add(sphereMaterialAssetItem);
            sphereMaterialAssetItem.IsDirty = true;

            // Create the sphere model
            var sphereModel = new ProceduralModelAsset
            {
                Type = new SphereProceduralModel
                {
                    MaterialInstance = { Material = AttachedReferenceManager.CreateProxyObject <Material>(sphereMaterialAssetItem.Id, sphereMaterialAssetItem.Location) },
                    Tessellation     = 30,
                },
            };
            var sphereModelAssetItem = new AssetItem("Sphere", sphereModel);

            package.Assets.Add(sphereModelAssetItem);
            sphereModelAssetItem.IsDirty = true;

            // Create sphere entity
            var sphereEntity = new Entity("Sphere")
            {
                new ModelComponent(AttachedReferenceManager.CreateProxyObject <Model>(sphereModelAssetItem.Id, sphereModelAssetItem.Location))
            };

            sphereEntity.Transform.Position = new Vector3(0.0f, 0.5f, 0.0f);

            // Create the material for the ground
            var groundMaterial = new MaterialAsset
            {
                Attributes =
                {
                    Diffuse      = new MaterialDiffuseMapFeature(new ComputeColor(Color.FromBgra(0xFF242424))),
                    DiffuseModel = new MaterialDiffuseLambertModelFeature(),
                }
            };

            if (isHDR)
            {
                // Create HDR part of material
                groundMaterial.Attributes.Specular      = new MaterialMetalnessMapFeature(new ComputeFloat(0.0f));
                groundMaterial.Attributes.SpecularModel = new MaterialSpecularMicrofacetModelFeature();
                groundMaterial.Attributes.MicroSurface  = new MaterialGlossinessMapFeature(new ComputeFloat(0.1f));
            }

            var groundMaterialAssetItem = new AssetItem("Ground Material", groundMaterial);

            package.Assets.Add(groundMaterialAssetItem);
            groundMaterialAssetItem.IsDirty = true;

            // Create the ground model
            var groundModel = new ProceduralModelAsset
            {
                Type = new PlaneProceduralModel
                {
                    Size             = new Vector2(10.0f, 10.0f),
                    MaterialInstance = { Material = AttachedReferenceManager.CreateProxyObject <Material>(groundMaterialAssetItem.Id, groundMaterialAssetItem.Location) },
                },
            };
            var groundModelAssetItem = new AssetItem("Ground", groundModel);

            package.Assets.Add(groundModelAssetItem);
            groundModelAssetItem.IsDirty = true;

            // Create the ground entity
            var groundEntity = new Entity("Ground")
            {
                new ModelComponent(AttachedReferenceManager.CreateProxyObject <Model>(groundModelAssetItem.Id, groundModelAssetItem.Location))
            };

            // Copy file in Resources
            var skyboxFilename = (UFile)(isHDR ? "skybox_texture_hdr.dds" : "skybox_texture_ldr.dds");

            try
            {
                var resources = UPath.Combine(package.RootDirectory, (UDirectory)"Resources");
                Directory.CreateDirectory(resources.ToWindowsPath());

                // TODO: Hardcoded due to the fact that part of the template is in another folder in dev build
                // We might want to extend TemplateFolder to support those cases
                var dataDirectory  = ProjectTemplateGeneratorHelper.GetTemplateDataDirectory(parameters.Description);
                var skyboxFullPath = UPath.Combine(dataDirectory, skyboxFilename).ToWindowsPath();
                File.Copy(skyboxFullPath, UPath.Combine(resources, skyboxFilename).ToWindowsPath(), true);
            }
            catch (Exception ex)
            {
                logger.Error("Unexpected exception while copying cubemap", ex);
            }

            // Create the texture asset
            var skyboxTextureAsset = new TextureAsset {
                Source = Path.Combine(@"../Resources", skyboxFilename), IsCompressed = isHDR, Type = new ColorTextureType {
                    UseSRgbSampling = false
                }
            };
            var skyboxTextureAssetItem = new AssetItem("Skybox texture", skyboxTextureAsset);

            package.Assets.Add(skyboxTextureAssetItem);
            skyboxTextureAssetItem.IsDirty = true;

            // Create the skybox asset
            var skyboxAsset = new SkyboxAsset
            {
                CubeMap = AttachedReferenceManager.CreateProxyObject <Texture>(skyboxTextureAssetItem.Id, skyboxTextureAssetItem.Location)
            };
            var skyboxAssetItem = new AssetItem("Skybox", skyboxAsset);

            package.Assets.Add(skyboxAssetItem);
            skyboxAssetItem.IsDirty = true;

            // Create the scene
            var defaultSceneAsset = isHDR ? SceneHDRFactory.Create() : SceneLDRFactory.Create();

            defaultSceneAsset.Hierarchy.Parts.Add(new EntityDesign(groundEntity));
            defaultSceneAsset.Hierarchy.RootParts.Add(groundEntity);

            defaultSceneAsset.Hierarchy.Parts.Add(new EntityDesign(sphereEntity));
            defaultSceneAsset.Hierarchy.RootParts.Add(sphereEntity);

            var sceneAssetItem = new AssetItem(GameSettingsAsset.DefaultSceneLocation, defaultSceneAsset);

            package.Assets.Add(sceneAssetItem);
            sceneAssetItem.IsDirty = true;

            // Sets the scene created as default in the shared profile
            var gameSettingsAsset = package.Assets.Find(GameSettingsAsset.GameSettingsLocation);

            if (gameSettingsAsset != null)
            {
                ((GameSettingsAsset)gameSettingsAsset.Asset).DefaultScene = AttachedReferenceManager.CreateProxyObject <Scene>(sceneAssetItem.Id, sceneAssetItem.Location);
                gameSettingsAsset.IsDirty = true;
            }

            var skyboxEntity = defaultSceneAsset.Hierarchy.Parts.Select(x => x.Value.Entity).Single(x => x.Name == SceneBaseFactory.SkyboxEntityName);

            skyboxEntity.Get <BackgroundComponent>().Texture = skyboxAsset.CubeMap;
            if (isHDR)
            {
                skyboxEntity.Get <LightComponent>().Type = new LightSkybox
                {
                    Skybox = AttachedReferenceManager.CreateProxyObject <Skybox>(skyboxAssetItem.Id, skyboxAssetItem.Location)
                };
            }

            var cameraEntity       = defaultSceneAsset.Hierarchy.Parts.Select(x => x.Value.Entity).Single(x => x.Name == SceneBaseFactory.CameraEntityName);
            var graphicsCompositor = package.Assets.Select(x => x.Asset).OfType <GraphicsCompositorAsset>().Single();

            cameraEntity.Components.Get <CameraComponent>().Slot = graphicsCompositor.Cameras.Single().ToSlotId();

            // Let's add camera script
            CreateCameraScript(parameters, package, projectGameName, cameraEntity, sceneAssetItem);
        }