示例#1
0
        public ModelBoneHierarchy Load(string name, AssetLoadContext context)
        {
            // Find it in the file system.
            FileSystemEntry entry = null;

            foreach (var path in _pathResolver.GetPaths(name, context.Language))
            {
                entry = context.FileSystem.GetFile(path);
                if (entry != null)
                {
                    break;
                }
            }

            // Load hierarchy.
            W3dFile hierarchyFile;

            using (var entryStream = entry.Open())
            {
                hierarchyFile = W3dFile.FromStream(entryStream, entry.FilePath);
            }
            var w3dHierarchy = hierarchyFile.GetHierarchy();

            return(w3dHierarchy != null
                ? new ModelBoneHierarchy(w3dHierarchy)
                : ModelBoneHierarchy.CreateDefault());
        }
示例#2
0
        internal static W3DAnimation FromW3dFile(W3dFile w3dFile)
        {
            var w3dAnimations           = w3dFile.GetAnimations();
            var w3dCompressedAnimations = w3dFile.GetCompressedAnimations();

            var animations = new W3DAnimation[w3dAnimations.Count + w3dCompressedAnimations.Count];

            if (animations.Length == 0)
            {
                // sometimes w3d files are referenced inside animation states that do not contain any animation chunks
                return(null);
            }

            if (animations.Length != 1)
            {
                throw new NotSupportedException();
            }

            for (var i = 0; i < w3dAnimations.Count; i++)
            {
                animations[i] = new W3DAnimation(w3dAnimations[i]);
            }
            for (var i = 0; i < w3dCompressedAnimations.Count; i++)
            {
                animations[w3dAnimations.Count + i] = new W3DAnimation(w3dCompressedAnimations[i]);
            }

            return(animations[0]);
        }
示例#3
0
        protected override Model LoadEntry(FileSystemEntry entry, ContentManager contentManager, Game game, LoadOptions loadOptions)
        {
            W3dFile w3dFile;

            using (var entryStream = entry.Open())
            {
                w3dFile = W3dFile.FromStream(entryStream, entry.FilePath);
            }

            var w3dHLod      = w3dFile.GetHLod();
            var w3dHierarchy = w3dFile.GetHierarchy();

            if (w3dHLod != null && w3dHierarchy == null)
            {
                // Load referenced hierarchy.
                var     hierarchyFileName  = w3dHLod.Header.HierarchyName + ".W3D";
                var     hierarchyFilePath  = Path.Combine(Path.GetDirectoryName(w3dFile.FilePath), hierarchyFileName);
                var     hierarchyFileEntry = contentManager.FileSystem.GetFile(hierarchyFilePath);
                W3dFile hierarchyFile;
                using (var entryStream = hierarchyFileEntry.Open())
                {
                    hierarchyFile = W3dFile.FromStream(entryStream, hierarchyFileEntry.FilePath);
                }
                w3dHierarchy = hierarchyFile.GetHierarchy();
            }

            return(CreateModel(
                       contentManager,
                       w3dFile,
                       w3dHierarchy));
        }
示例#4
0
        public void LoadW3dFromBigFile()
        {
            var bigFilePath = Path.Combine(InstalledFilesTestData.GetInstallationDirectory(SageGame.CncGeneralsZeroHour), "W3DZH.big");

            using (var bigArchive = new BigArchive(bigFilePath))
            {
                var entry = bigArchive.GetEntry(@"Art\W3D\ABBarracks_AC.W3D");

                var w3dFile = W3dFile.FromFileSystemEntry(new FileSystemEntry(null, entry.FullName, entry.Length, entry.Open));
                Assert.Equal(3, w3dFile.Meshes.Count);
            }
        }
示例#5
0
        public void LoadW3dFromBigFile()
        {
            const string bigFilePath = @"C:\Program Files (x86)\Origin Games\Command and Conquer Generals Zero Hour\Command and Conquer Generals Zero Hour\W3DZH.big";

            using (var bigStream = File.OpenRead(bigFilePath))
                using (var bigArchive = new BigArchive(bigStream))
                {
                    var entry = bigArchive.GetEntry(@"Art\W3D\ABBarracks_AC.W3D");

                    var w3dFile = W3dFile.FromFileSystemEntry(new FileSystemEntry(null, entry.FullName, entry.Length, entry.Open));
                    Assert.Equal(3, w3dFile.Meshes.Count);
                }
        }
示例#6
0
        public Model Load(string name, AssetLoadContext context)
        {
            // Find it in the file system.
            FileSystemEntry entry = null;

            foreach (var path in _pathResolver.GetPaths(name, context.Language))
            {
                entry = context.FileSystem.GetFile(path);
                if (entry != null)
                {
                    break;
                }
            }

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

            // Load model.
            W3dFile w3dFile;

            using (var entryStream = entry.Open())
            {
                w3dFile = W3dFile.FromStream(entryStream, entry.FilePath);
            }

            var w3dHLod      = w3dFile.HLod;
            var w3dHierarchy = w3dFile.Hierarchy;
            ModelBoneHierarchy boneHierarchy;

            if (w3dHierarchy != null)
            {
                boneHierarchy = new ModelBoneHierarchy(w3dHierarchy);
            }
            else if (w3dHLod != null && w3dHierarchy == null)
            {
                // Load referenced hierarchy.
                boneHierarchy = context.AssetStore.ModelBoneHierarchies.GetByName(w3dHLod.Header.HierarchyName);
            }
            else
            {
                boneHierarchy = ModelBoneHierarchy.CreateDefault();
            }

            return(CreateModel(
                       context,
                       w3dFile,
                       boneHierarchy));
        }
示例#7
0
        public W3DAnimation Load(string key, AssetLoadContext context)
        {
            var splitName = key.Split('.');

            if (splitName.Length <= 1)
            {
                return(null);
            }

            // Find it in the file system.
            FileSystemEntry entry = null;

            foreach (var path in _pathResolver.GetPaths(splitName[1], context.Language))
            {
                entry = context.FileSystem.GetFile(path);
                if (entry != null)
                {
                    break;
                }
            }

            if (entry == null)
            {
                logger.Warn("Failed to load animation: " + key);
                return(null);
            }

            // Load animation.
            W3dFile w3dFile;

            using (var entryStream = entry.Open())
            {
                w3dFile = W3dFile.FromStream(entryStream, entry.FilePath);
            }
            var animation = W3DAnimation.FromW3dFile(w3dFile);

            if (animation == null)
            {
                logger.Warn("Failed to load animation (was null): " + key);
                return(null);
            }

            if (!string.Equals(animation.Name, key, StringComparison.OrdinalIgnoreCase))
            {
                logger.Warn("animation name '" + animation.Name + "' does not match '" + key + "'");
            }

            return(animation);
        }
示例#8
0
        public void LoadW3dFromBigFile()
        {
            var bigFilePath = Path.Combine(InstalledFilesTestData.GetInstallationDirectory(SageGame.CncGeneralsZeroHour), "W3DZH.big");

            using (var bigArchive = new BigArchive(bigFilePath))
            {
                var entry = bigArchive.GetEntry(@"Art\W3D\ABBarracks_AC.W3D");

                W3dFile w3dFile;
                using (var entryStream = entry.Open())
                {
                    w3dFile = W3dFile.FromStream(entryStream, entry.FullName);
                }

                Assert.Equal(3, w3dFile.GetMeshes().Count);
            }
        }
示例#9
0
        protected override Model LoadEntry(FileSystemEntry entry, ContentManager contentManager, Game game, LoadOptions loadOptions)
        {
            var w3dFile = W3dFile.FromFileSystemEntry(entry);

            var w3dHierarchy = w3dFile.Hierarchy;

            if (w3dFile.HLod != null && w3dHierarchy == null)
            {
                // Load referenced hierarchy.
                var hierarchyFileName  = w3dFile.HLod.Header.HierarchyName + ".W3D";
                var hierarchyFilePath  = Path.Combine(Path.GetDirectoryName(w3dFile.FilePath), hierarchyFileName);
                var hierarchyFileEntry = contentManager.FileSystem.GetFile(hierarchyFilePath);
                var hierarchyFile      = W3dFile.FromFileSystemEntry(hierarchyFileEntry);
                w3dHierarchy = hierarchyFile.Hierarchy;
            }

            return(CreateModel(
                       contentManager,
                       w3dFile,
                       w3dHierarchy));
        }
示例#10
0
        public static Animation[] LoadAnimations(W3dFile w3dFile, ContentManager contentManager)
        {
            var w3dAnimations           = w3dFile.GetAnimations();
            var w3dCompressedAnimations = w3dFile.GetCompressedAnimations();

            var animations = new Animation[w3dAnimations.Count + w3dCompressedAnimations.Count];

            for (var i = 0; i < w3dAnimations.Count; i++)
            {
                animations[i] = CreateAnimation(w3dAnimations[i]);
            }
            for (var i = 0; i < w3dCompressedAnimations.Count; i++)
            {
                animations[w3dAnimations.Count + i] = CreateAnimation(w3dCompressedAnimations[i]);
            }

            foreach (var animation in animations)
            {
                contentManager.DataContext.Animations.Add(animation.Name, animation);
            }

            return(animations);
        }
示例#11
0
        internal static W3DAnimation FromW3dFile(W3dFile w3dFile)
        {
            var w3dAnimations           = w3dFile.GetAnimations();
            var w3dCompressedAnimations = w3dFile.GetCompressedAnimations();

            var animations = new W3DAnimation[w3dAnimations.Count + w3dCompressedAnimations.Count];

            if (animations.Length != 1)
            {
                throw new NotSupportedException();
            }

            for (var i = 0; i < w3dAnimations.Count; i++)
            {
                animations[i] = new W3DAnimation(w3dAnimations[i]);
            }
            for (var i = 0; i < w3dCompressedAnimations.Count; i++)
            {
                animations[w3dAnimations.Count + i] = new W3DAnimation(w3dCompressedAnimations[i]);
            }

            return(animations[0]);
        }
示例#12
0
        public W3dView(AssetViewContext context)
            : base(context)
        {
            var game = context.Game;

            var modelInstance = game.ContentManager
                                .Load <Model>(context.Entry.FilePath)
                                .CreateInstance(game.GraphicsDevice);

            void onUpdating(object sender, GameUpdatingEventArgs e) => modelInstance.Update(e.GameTime);

            game.Updating += onUpdating;
            AddDisposeAction(() => game.Updating -= onUpdating);

            void onBuildingRenderList(object sender, BuildingRenderListEventArgs e)
            {
                modelInstance.SetWorldMatrix(Matrix4x4.Identity);
                modelInstance.BuildRenderList(e.RenderList, e.Camera);
            }

            game.BuildingRenderList += onBuildingRenderList;
            AddDisposeAction(() => game.BuildingRenderList -= onBuildingRenderList);

            var enclosingBoundingBox = GetEnclosingBoundingBox(modelInstance);

            var cameraController = new ArcballCameraController(
                enclosingBoundingBox.GetCenter(),
                Vector3.Distance(enclosingBoundingBox.Min, enclosingBoundingBox.Max));

            game.Scene3D = new Scene3D(
                game,
                cameraController,
                null,
                null,
                Array.Empty <Terrain.Road>(),
                null,
                new GameObjectCollection(game.ContentManager),
                new WaypointCollection(),
                new WaypointPathCollection(),
                WorldLighting.CreateDefault(),
                Array.Empty <Player>(),
                Array.Empty <Team>());

            var animations = new List <AnimationInstance>(modelInstance.AnimationInstances);

            var w3dFile = W3dFile.FromFileSystemEntry(context.Entry);

            // If this is a skin file, load "external" animations.
            var externalAnimations = new List <AnimationInstance>();

            if (w3dFile.HLod != null && w3dFile.HLod.Header.Name.EndsWith("_SKN", StringComparison.OrdinalIgnoreCase))
            {
                var namePrefix   = w3dFile.HLod.Header.Name.Substring(0, w3dFile.HLod.Header.Name.LastIndexOf('_') + 1);
                var parentFolder = Path.GetDirectoryName(w3dFile.FilePath);
                var pathPrefix   = Path.Combine(parentFolder, namePrefix);
                foreach (var animationFileEntry in context.Entry.FileSystem.GetFiles(parentFolder))
                {
                    if (!animationFileEntry.FilePath.StartsWith(pathPrefix, StringComparison.OrdinalIgnoreCase))
                    {
                        continue;
                    }

                    var animationModel = game.ContentManager.Load <Model>(animationFileEntry.FilePath);
                    foreach (var animation in animationModel.Animations)
                    {
                        var externalAnimationInstance = new AnimationInstance(modelInstance, animation);
                        modelInstance.AnimationInstances.Add(externalAnimationInstance);
                        externalAnimations.Add(externalAnimationInstance);
                    }
                }
            }

            _subObjects = new List <W3dItem>();

            _subObjects.Add(new W3dModelItem());

            foreach (var animation in animations)
            {
                _subObjects.Add(new W3dAnimationItem(animation, "Animation"));
            }

            foreach (var animation in externalAnimations)
            {
                _subObjects.Add(new W3dAnimationItem(animation, "External Animation"));
            }

            ActivateItem(_subObjects[0]);
        }
示例#13
0
        private static Model CreateModel(
            AssetLoadContext context,
            W3dFile w3dFile,
            ModelBoneHierarchy boneHierarchy)
        {
            //BoundingSphere boundingSphere = default(BoundingSphere);

            var w3dHLod = w3dFile.HLod;

            var subObjects = new List <ModelSubObject>();

            if (w3dHLod != null)
            {
                foreach (var w3dSubObject in w3dHLod.Lods[0].SubObjects)
                {
                    if (!w3dFile.RenderableObjectsByName.TryGetValue(w3dSubObject.Name, out var w3dRenderableObject))
                    {
                        continue;
                    }

                    var bone = boneHierarchy.Bones[(int)w3dSubObject.BoneIndex];

                    //var meshBoundingSphere = mesh.BoundingSphere.Transform(bone.Transform);

                    //boundingSphere = (i == 0)
                    //    ? meshBoundingSphere
                    //    : BoundingSphere.CreateMerged(boundingSphere, meshBoundingSphere);

                    subObjects.Add(
                        CreateSubObject(
                            w3dSubObject.Name,
                            w3dRenderableObject,
                            bone,
                            context));
                }
            }
            else if (w3dFile.RenderableObjects.Count > 0)
            {
                // Simple models can have only one mesh with no HLod chunk.
                if (w3dFile.RenderableObjects.Count != 1)
                {
                    throw new InvalidOperationException();
                }

                var w3dRenderableObjectPair = w3dFile.RenderableObjectsByName.First();

                subObjects.Add(
                    CreateSubObject(
                        w3dRenderableObjectPair.Key,
                        w3dRenderableObjectPair.Value,
                        boneHierarchy.Bones[0],
                        context));
            }
            else
            {
            }

            return(new Model(
                       Path.GetFileNameWithoutExtension(w3dFile.FilePath),
                       boneHierarchy,
                       subObjects.ToArray()));
        }
示例#14
0
 public W3dFileContentViewModel(FileSystemEntry file)
     : base(file)
 {
     _w3dFile = W3dFile.FromFileSystemEntry(file);
 }
示例#15
0
        private static Model CreateModel(
            AssetLoadContext context,
            W3dFile w3dFile,
            ModelBoneHierarchy boneHierarchy)
        {
            //BoundingSphere boundingSphere = default(BoundingSphere);

            var w3dMeshes = w3dFile.GetMeshes();
            var w3dHLod   = w3dFile.GetHLod();

            var subObjects = new List <ModelSubObject>();

            if (w3dHLod != null)
            {
                foreach (var w3dSubObject in w3dHLod.Lods[0].SubObjects)
                {
                    // TODO: Collision boxes
                    var w3dMesh = w3dMeshes.FirstOrDefault(x => x.Header.ContainerName + "." + x.Header.MeshName == w3dSubObject.Name);
                    if (w3dMesh == null)
                    {
                        continue;
                    }

                    var bone = boneHierarchy.Bones[(int)w3dSubObject.BoneIndex];

                    var mesh = new ModelMesh(w3dMesh, context);

                    //var meshBoundingSphere = mesh.BoundingSphere.Transform(bone.Transform);

                    //boundingSphere = (i == 0)
                    //    ? meshBoundingSphere
                    //    : BoundingSphere.CreateMerged(boundingSphere, meshBoundingSphere);

                    subObjects.Add(new ModelSubObject(w3dSubObject.Name, bone, mesh));
                }
            }
            else if (w3dMeshes.Count > 0)
            {
                // Simple models can have only one mesh with no HLod chunk.
                if (w3dMeshes.Count != 1)
                {
                    throw new InvalidOperationException();
                }

                var w3dMesh = w3dMeshes[0];

                var mesh = new ModelMesh(w3dMesh, context);

                subObjects.Add(new ModelSubObject(
                                   w3dMesh.Header.MeshName,
                                   boneHierarchy.Bones[0],
                                   mesh));
            }
            else
            {
                // TODO: Some .w3d files contain a single W3D_BOX.
            }

            return(new Model(
                       Path.GetFileNameWithoutExtension(w3dFile.FilePath),
                       boneHierarchy,
                       subObjects.ToArray()));
        }
示例#16
0
        public void CanRoundtripW3dFiles()
        {
            InstalledFilesTestData.ReadFiles(".w3d", _output, entry =>
            {
                switch (Path.GetFileName(entry.FilePath).ToLower())
                {
                case "uisabotr_idel.w3d":
                case "uisabotr_jump.w3d":
                case "uisabotr_left.w3d":
                case "uisabotr_right.w3d":
                case "uisabotr_up.w3d":
                case "cusheep_grza.w3d":
                case "gbmtwalld.w3d":
                case "gbmtwalldramp.w3d":
                case "gbmtwalle.w3d":
                case "bbbags.w3d":
                case "cuwyrm_cld_skl.w3d":
                case "cuwyrm_cld_skn.w3d":
                case "gugandalfcrstl.w3d":
                case "guhbtshfb_cinb.w3d":
                case "guhbtshfb_cinc.w3d":
                case "kbpostgaten_al.w3d":
                case "kbpostgaten_am.w3d":
                case "lwbanhfllbst.w3d":
                case "lwbanhnazgul.w3d":
                case "lwbanhwtchkng.w3d":
                case "psupplies04.w3d":
                case "readonly-0-rev-2-lwbanhwitchk.w3d":
                case "wbcave_d2a.w3d":
                case "wbcave_d2c.w3d":
                case "npc14b.w3d":
                case "npc15b.w3d":
                    return;     // Corrupt, or unreferenced and contain chunks that don't exist elsewhere.
                }

                var w3dFile = TestUtility.DoRoundtripTest(
                    () => entry.Open(),
                    stream => W3dFile.FromStream(stream, entry.FilePath),
                    (w3d, stream) => w3d.WriteTo(stream),
                    true);

                foreach (var mesh in w3dFile.GetMeshes())
                {
                    Assert.Equal((int)mesh.Header.NumVertices, mesh.Vertices.Items.Length);

                    Assert.Equal((int)mesh.Header.NumTris, mesh.Triangles.Items.Length);

                    if (mesh.Influences != null)
                    {
                        Assert.Equal(mesh.Vertices.Items.Length, mesh.Influences.Items.Length);
                    }

                    Assert.Equal((int)mesh.MaterialInfo.PassCount, mesh.MaterialPasses.Count);

                    Assert.Equal((int)mesh.MaterialInfo.ShaderCount, mesh.Shaders?.Items.Count ?? 0);

                    Assert.Equal(mesh.Vertices.Items.Length, mesh.ShadeIndices.Items.Length);

                    if (mesh.VertexMaterials != null)
                    {
                        Assert.True(mesh.VertexMaterials.Items.Count <= 16);

                        foreach (var material in mesh.VertexMaterials.Items)
                        {
                            Assert.Equal(W3dVertexMaterialFlags.None, material.Info.Attributes);

                            Assert.Equal(0, material.Info.Translucency);
                        }
                    }

                    Assert.True(mesh.MaterialPasses.Count <= 3);

                    Assert.True(mesh.ShaderMaterials == null || mesh.ShaderMaterials.Items.Count == 1);

                    if (mesh.ShaderMaterials != null)
                    {
                        Assert.Null(mesh.VertexMaterials);
                        Assert.Single(mesh.MaterialPasses);
                    }

                    foreach (var materialPass in mesh.MaterialPasses)
                    {
                        Assert.True(materialPass.Dcg == null || materialPass.Dcg.Items.Length == mesh.Vertices.Items.Length);
                        Assert.Null(materialPass.Dig);
                        Assert.Null(materialPass.Scg);

                        Assert.True(materialPass.TextureStages.Count <= 2);

                        foreach (var textureStage in materialPass.TextureStages)
                        {
                            Assert.True(textureStage.TexCoords == null || textureStage.TexCoords.Items.Length == mesh.Header.NumVertices);

                            Assert.Null(textureStage.PerFaceTexCoordIds);

                            var numTextureIds = textureStage.TextureIds.Items.Count;
                            Assert.True(numTextureIds == 1 || numTextureIds == mesh.Header.NumTris);
                        }

                        Assert.True((materialPass.ShaderIds != null && materialPass.VertexMaterialIds != null && materialPass.TexCoords == null) || materialPass.ShaderMaterialIds != null);

                        if (materialPass.ShaderIds != null)
                        {
                            var numShaderIds = materialPass.ShaderIds.Items.Length;
                            Assert.True(numShaderIds == 1 || numShaderIds == mesh.Header.NumTris);
                        }

                        if (materialPass.VertexMaterialIds != null)
                        {
                            var numVertexMaterialIds = materialPass.VertexMaterialIds.Items.Length;
                            Assert.True(numVertexMaterialIds == 1 || numVertexMaterialIds == mesh.Header.NumVertices);
                        }

                        Assert.True(materialPass.ShaderMaterialIds == null || materialPass.ShaderMaterialIds.Items[0] == 0);
                    }

                    if (mesh.Textures != null)
                    {
                        Assert.True(mesh.Textures.Items.Count <= 29);
                    }
                }

                foreach (var animation in w3dFile.GetCompressedAnimations())
                {
                    foreach (var channel in animation.TimeCodedChannels)
                    {
                        switch (channel.ChannelType)
                        {
                        case W3dAnimationChannelType.UnknownBfme:
                            Assert.Equal(1, channel.VectorLength);
                            break;
                        }
                    }
                }
            });
        }
示例#17
0
        public W3dView(FileSystemEntry entry, Func <IntPtr, Game> createGame)
        {
            _listBox = new ListBox
            {
                Width           = 250,
                ItemTextBinding = Binding.Property((W3dItem v) => v.Name)
            };
            _listBox.SelectedValueChanged += OnSelectedValueChanged;
            Panel1 = _listBox;

            _listBox.SelectedIndex = 0;

            Panel2 = new GameControl
            {
                CreateGame = h =>
                {
                    var game = createGame(h);

                    var modelInstance = game.ContentManager
                                        .Load <Model>(entry.FilePath)
                                        .CreateInstance(game.GraphicsDevice);

                    game.Updating += (sender, e) =>
                    {
                        modelInstance.Update(e.GameTime);
                    };

                    game.BuildingRenderList += (sender, e) =>
                    {
                        modelInstance.SetWorldMatrix(Matrix4x4.Identity);
                        modelInstance.BuildRenderList(e.RenderList, e.Camera);
                    };

                    var enclosingBoundingBox = GetEnclosingBoundingBox(modelInstance);

                    var cameraController = new ArcballCameraController(
                        enclosingBoundingBox.GetCenter(),
                        Vector3.Distance(enclosingBoundingBox.Min, enclosingBoundingBox.Max));

                    game.Scene3D = new Scene3D(
                        game,
                        cameraController,
                        null,
                        null,
                        null,
                        new GameObjectCollection(game.ContentManager),
                        new WaypointCollection(),
                        new WaypointPathCollection(),
                        WorldLighting.CreateDefault());

                    var animations = new List <AnimationInstance>(modelInstance.AnimationInstances);

                    var w3dFile = W3dFile.FromFileSystemEntry(entry);

                    // If this is a skin file, load "external" animations.
                    var externalAnimations = new List <AnimationInstance>();
                    if (w3dFile.HLod != null && w3dFile.HLod.Header.Name.EndsWith("_SKN", StringComparison.OrdinalIgnoreCase))
                    {
                        var namePrefix   = w3dFile.HLod.Header.Name.Substring(0, w3dFile.HLod.Header.Name.LastIndexOf('_') + 1);
                        var parentFolder = Path.GetDirectoryName(w3dFile.FilePath);
                        var pathPrefix   = Path.Combine(parentFolder, namePrefix);
                        foreach (var animationFileEntry in entry.FileSystem.GetFiles(parentFolder))
                        {
                            if (!animationFileEntry.FilePath.StartsWith(pathPrefix, StringComparison.OrdinalIgnoreCase))
                            {
                                continue;
                            }

                            var animationModel = game.ContentManager.Load <Model>(animationFileEntry.FilePath);
                            foreach (var animation in animationModel.Animations)
                            {
                                var externalAnimationInstance = new AnimationInstance(modelInstance, animation);
                                modelInstance.AnimationInstances.Add(externalAnimationInstance);
                                externalAnimations.Add(externalAnimationInstance);
                            }
                        }
                    }

                    var subObjects = new List <W3dItem>();

                    subObjects.Add(new W3dModelItem());

                    foreach (var animation in animations)
                    {
                        subObjects.Add(new W3dAnimationItem(animation, "Animation"));
                    }

                    foreach (var animation in externalAnimations)
                    {
                        subObjects.Add(new W3dAnimationItem(animation, "External Animation"));
                    }

                    _listBox.DataStore = subObjects;

                    return(game);
                }
            };
        }
示例#18
0
        public void CanReadW3dFiles()
        {
            InstalledFilesTestData.ReadFiles(".w3d", _output, entry =>
            {
                switch (Path.GetFileName(entry.FilePath))
                {
                case "UISabotr_idel.w3d":
                case "UISabotr_Jump.w3d":
                case "UISabotr_Left.w3d":
                case "UISabotr_Right.w3d":
                case "UISabotr_Up.w3d":
                case "cusheep_grza.w3d":
                case "gbmtwalld.w3d":
                case "gbmtwalldramp.w3d":
                case "gbmtwalle.w3d":
                case "bbbags.w3d":
                case "cuwyrm_cld_skl.w3d":
                case "cuwyrm_cld_skn.w3d":
                case "gugandalfcrstl.w3d":
                case "guhbtshfb_cinb.w3d":
                case "guhbtshfb_cinc.w3d":
                case "lwbanhfllbst.w3d":
                case "lwbanhnazgul.w3d":
                case "lwbanhwtchkng.w3d":
                case "psupplies04.w3d":
                case "wbcave_d2a.w3d":
                case "wbcave_d2c.w3d":
                    return;     // Corrupt, or unreferenced and contain chunks that don't exist elsewhere.
                }

                var w3dFile = W3dFile.FromFileSystemEntry(entry);

                foreach (var mesh in w3dFile.Meshes)
                {
                    Assert.Equal((int)mesh.Header.NumVertices, mesh.Vertices.Length);

                    Assert.Equal((int)mesh.Header.NumTris, mesh.Triangles.Length);

                    Assert.Equal(mesh.Vertices.Length, mesh.Influences.Length);

                    Assert.Equal((int)mesh.MaterialInfo.PassCount, mesh.MaterialPasses.Length);

                    Assert.Equal((int)mesh.MaterialInfo.ShaderCount, mesh.Shaders.Length);

                    Assert.Equal(mesh.Vertices.Length, mesh.ShadeIndices.Length);

                    Assert.True(mesh.Materials.Length <= 16);

                    foreach (var material in mesh.Materials)
                    {
                        Assert.Equal(W3dVertexMaterialFlags.None, material.VertexMaterialInfo.Attributes);

                        Assert.Equal(0, material.VertexMaterialInfo.Translucency);
                    }

                    Assert.True(mesh.MaterialPasses.Length <= 3);

                    Assert.True(mesh.ShaderMaterials == null || mesh.ShaderMaterials.Materials.Count == 1);

                    if (mesh.ShaderMaterials != null)
                    {
                        Assert.Empty(mesh.Materials);
                        Assert.Single(mesh.MaterialPasses);
                    }

                    foreach (var materialPass in mesh.MaterialPasses)
                    {
                        Assert.True(materialPass.Dcg == null || materialPass.Dcg.Length == mesh.Vertices.Length);
                        Assert.Null(materialPass.Dig);
                        Assert.Null(materialPass.Scg);

                        Assert.True(materialPass.TextureStages.Count <= 2);

                        foreach (var textureStage in materialPass.TextureStages)
                        {
                            Assert.True(textureStage.TexCoords == null || textureStage.TexCoords.Length == mesh.Header.NumVertices);

                            Assert.Null(textureStage.PerFaceTexCoordIds);

                            var numTextureIds = textureStage.TextureIds.Length;
                            Assert.True(numTextureIds == 1 || numTextureIds == mesh.Header.NumTris);
                        }

                        Assert.True((materialPass.ShaderIds != null && materialPass.VertexMaterialIds != null && materialPass.TexCoords == null) || materialPass.ShaderMaterialId != null);

                        if (materialPass.ShaderIds != null)
                        {
                            var numShaderIds = materialPass.ShaderIds.Length;
                            Assert.True(numShaderIds == 1 || numShaderIds == mesh.Header.NumTris);
                        }

                        if (materialPass.VertexMaterialIds != null)
                        {
                            var numVertexMaterialIds = materialPass.VertexMaterialIds.Length;
                            Assert.True(numVertexMaterialIds == 1 || numVertexMaterialIds == mesh.Header.NumVertices);
                        }

                        Assert.True(materialPass.ShaderMaterialId == null || materialPass.ShaderMaterialId == 0);
                    }

                    Assert.True(mesh.Textures.Count <= 29);
                }

                foreach (var animation in w3dFile.CompressedAnimations)
                {
                    foreach (var channel in animation.TimeCodedChannels)
                    {
                        switch (channel.ChannelType)
                        {
                        case W3dAnimationChannelType.UnknownBfme:
                            Assert.Equal(1, channel.VectorLength);
                            break;
                        }
                    }
                }
            });
        }
示例#19
0
        private Model CreateModel(
            ContentManager contentManager,
            W3dFile w3dFile,
            W3dHierarchyDef w3dHierarchy)
        {
            ModelBone[] bones;
            if (w3dHierarchy != null)
            {
                bones = new ModelBone[w3dHierarchy.Pivots.Items.Count];

                for (var i = 0; i < w3dHierarchy.Pivots.Items.Count; i++)
                {
                    var pivot = w3dHierarchy.Pivots.Items[i];

                    var parent = pivot.ParentIdx == -1
                        ? null
                        : bones[pivot.ParentIdx];

                    bones[i] = new ModelBone(
                        i,
                        pivot.Name,
                        parent,
                        pivot.Translation,
                        pivot.Rotation);
                }
            }
            else
            {
                bones    = new ModelBone[1];
                bones[0] = new ModelBone(0, null, null, Vector3.Zero, Quaternion.Identity);
            }

            //BoundingSphere boundingSphere = default(BoundingSphere);

            var w3dMeshes = w3dFile.GetMeshes();
            var w3dHLod   = w3dFile.GetHLod();

            var subObjects = new List <ModelSubObject>();

            if (w3dHLod != null)
            {
                foreach (var w3dSubObject in w3dHLod.Lods[0].SubObjects)
                {
                    // TODO: Collision boxes
                    var w3dMesh = w3dMeshes.FirstOrDefault(x => x.Header.ContainerName + "." + x.Header.MeshName == w3dSubObject.Name);
                    if (w3dMesh == null)
                    {
                        continue;
                    }

                    var bone = bones[(int)w3dSubObject.BoneIndex];

                    var mesh = CreateModelMesh(
                        contentManager,
                        w3dMesh);

                    //var meshBoundingSphere = mesh.BoundingSphere.Transform(bone.Transform);

                    //boundingSphere = (i == 0)
                    //    ? meshBoundingSphere
                    //    : BoundingSphere.CreateMerged(boundingSphere, meshBoundingSphere);

                    subObjects.Add(new ModelSubObject(w3dSubObject.Name, bone, mesh));
                }
            }
            else
            {
                // Simple models can have only one mesh with no HLod chunk.
                if (w3dMeshes.Count != 1)
                {
                    throw new InvalidOperationException();
                }

                var w3dMesh = w3dMeshes[0];

                var mesh = CreateModelMesh(
                    contentManager,
                    w3dMesh);

                subObjects.Add(new ModelSubObject(
                                   w3dMesh.Header.MeshName,
                                   bones[0],
                                   mesh));
            }

            LoadAnimations(w3dFile, contentManager);

            return(new Model(
                       new ModelBoneHierarchy(bones),
                       subObjects.ToArray()));
        }
示例#20
0
        private Model CreateModel(
            ContentManager contentManager,
            W3dFile w3dFile,
            W3dHierarchyDef w3dHierarchy)
        {
            ModelBone[] bones;
            if (w3dHierarchy != null)
            {
                if (w3dHierarchy.Pivots.Length > ModelMesh.MaxBones)
                {
                    throw new NotSupportedException();
                }

                bones = new ModelBone[w3dHierarchy.Pivots.Length];

                for (var i = 0; i < w3dHierarchy.Pivots.Length; i++)
                {
                    var pivot = w3dHierarchy.Pivots[i];

                    var parent = pivot.ParentIdx == -1
                        ? null
                        : bones[pivot.ParentIdx];

                    bones[i] = new ModelBone(
                        i,
                        pivot.Name,
                        parent,
                        pivot.Translation,
                        pivot.Rotation);
                }
            }
            else
            {
                bones    = new ModelBone[1];
                bones[0] = new ModelBone(0, null, null, Vector3.Zero, Quaternion.Identity);
            }

            //BoundingSphere boundingSphere = default(BoundingSphere);

            var meshes = new ModelMesh[w3dFile.Meshes.Count];

            for (var i = 0; i < w3dFile.Meshes.Count; i++)
            {
                var w3dMesh = w3dFile.Meshes[i];

                ModelBone bone;
                if (w3dFile.HLod != null)
                {
                    var hlodSubObject = w3dFile.HLod.Lods[0].SubObjects.Single(x => x.Name == w3dMesh.Header.ContainerName + "." + w3dMesh.Header.MeshName);
                    bone = bones[(int)hlodSubObject.BoneIndex];
                }
                else
                {
                    bone = bones[0];
                }

                meshes[i] = CreateModelMesh(
                    contentManager,
                    w3dMesh,
                    bone,
                    bones.Length);

                //var meshBoundingSphere = mesh.BoundingSphere.Transform(bone.Transform);

                //boundingSphere = (i == 0)
                //    ? meshBoundingSphere
                //    : BoundingSphere.CreateMerged(boundingSphere, meshBoundingSphere);
            }

            var animations = new Animation[w3dFile.Animations.Count + w3dFile.CompressedAnimations.Count];

            for (var i = 0; i < w3dFile.Animations.Count; i++)
            {
                animations[i] = CreateAnimation(w3dFile.Animations[i]);
            }
            for (var i = 0; i < w3dFile.CompressedAnimations.Count; i++)
            {
                animations[w3dFile.Animations.Count + i] = CreateAnimation(w3dFile.CompressedAnimations[i]);
            }

            return(new Model(
                       bones,
                       meshes,
                       animations));
        }
示例#21
0
        private W3dModelDrawConditionState CreateModelDrawConditionStateInstance(ModelConditionState conditionState)
        {
            ModelInstance modelInstance = null;

            if (!string.Equals(conditionState.Model, "NONE", StringComparison.OrdinalIgnoreCase))
            {
                var w3dFilePath = Path.Combine("Art", "W3D", conditionState.Model + ".W3D");
                var model       = _contentManager.Load <Model>(w3dFilePath);
                if (model != null)
                {
                    modelInstance = model.CreateInstance(_contentManager.GraphicsDevice);
                }
            }

            if (modelInstance != null)
            {
                // TODO: Multiple animations. Shouldn't play all of them. I think
                // we should randomly choose one of them?
                // And there is also IdleAnimation.
                var firstAnimation = conditionState.ConditionAnimations
                                     .Concat(conditionState.IdleAnimations)
                                     .LastOrDefault();
                if (firstAnimation != null)
                {
                    if (!_contentManager.DataContext.Animations.TryGetValue(firstAnimation.Animation, out var animation))
                    {
                        var splitName = firstAnimation.Animation.Split('.');

                        var w3dFilePath = Path.Combine("Art", "W3D", splitName[1] + ".W3D");
                        var w3dEntry    = _contentManager.FileSystem.GetFile(w3dFilePath);
                        var w3dFile     = W3dFile.FromFileSystemEntry(w3dEntry);

                        var animations = ModelLoader.LoadAnimations(w3dFile, _contentManager);
                        if (animations.Length != 1 || !string.Equals(animations[0].Name, firstAnimation.Animation, StringComparison.OrdinalIgnoreCase))
                        {
                            throw new NotSupportedException();
                        }

                        animation = animations[0];
                    }

                    var animationInstance = new AnimationInstance(modelInstance, animation);
                    modelInstance.AnimationInstances.Add(animationInstance);
                    animationInstance.Play();
                }
            }

            var particleSystems = new List <ParticleSystem>();

            if (modelInstance != null)
            {
                foreach (var particleSysBone in conditionState.ParticleSysBones)
                {
                    var particleSystemDefinition = _contentManager.IniDataContext.ParticleSystems.First(x => x.Name == particleSysBone.ParticleSystem);
                    var bone = modelInstance.Model.BoneHierarchy.Bones.FirstOrDefault(x => string.Equals(x.Name, particleSysBone.BoneName, StringComparison.OrdinalIgnoreCase));
                    if (bone == null)
                    {
                        // TODO: Should this ever happen?
                        continue;
                    }

                    particleSystems.Add(new ParticleSystem(
                                            _contentManager,
                                            particleSystemDefinition,
                                            () => ref modelInstance.AbsoluteBoneTransforms[bone.Index]));
                }
            }

            return(modelInstance != null
               ? new W3dModelDrawConditionState(modelInstance, particleSystems)
               : null);
        }