Ejemplo n.º 1
0
        // This method is optional. By sorting the wad textures it may result ahead of time
        // we may have better texture space efficency.
        public void PreloadReplaceWad(IEnumerable <WadMoveable> newMoveables, IEnumerable <WadStatic> newStatics)
        {
            Dispose();
            try
            {
                PreloadReplaceTextures(newMoveables, newStatics);
            }
            catch (TextureAtlasFullException)
            {
                logger.Error("Unable to preload wad because the texture atlas became too full!");
                return;
            }

            // Create moveable models
            Parallel.ForEach(newMoveables, moveable =>
            {
                var model = AnimatedModel.FromWadMoveable(GraphicsDevice, moveable, AllocateTexture);
                lock (Moveables)
                    Moveables.Add(moveable, model);
            });

            // Create static meshes
            Parallel.ForEach(newStatics, @static =>
            {
                var model = new StaticModel(GraphicsDevice);
                model.Meshes.Add(ObjectMesh.FromWad2(GraphicsDevice, @static.Mesh, AllocateTexture));
                model.UpdateBuffers();
                lock (Statics)
                    Statics.Add(@static, model);
            });
        }
Ejemplo n.º 2
0
        protected static void PutObjectVertexAndIndex(Vector3 v, ObjectMesh mesh, Submesh submesh, Vector2 uv, int submeshIndex,
                                                      short color, Vector2 positionInAtlas)
        {
            var newVertex = new ObjectVertex();

            newVertex.Position = new Vector3(v.X, v.Y, v.Z);
            newVertex.UV       = new Vector2((positionInAtlas.X + uv.X) / WadRenderer.TextureAtlasSize,
                                             (positionInAtlas.Y + uv.Y) / WadRenderer.TextureAtlasSize);

            var shade = 1.0f - color / 8191.0f;

            newVertex.Shade = new Vector2(shade, 0.0f);

            mesh.Vertices.Add(newVertex);
            submesh.Indices.Add((ushort)(mesh.Vertices.Count - 1));
        }
Ejemplo n.º 3
0
        public StaticModel GetStatic(WadStatic @static, bool maybeRebuildAll = true)
        {
            // Check if the data is already loaded
            // If yes attempt to use that one
            StaticModel model;

            if (Statics.TryGetValue(@static, out model))
            {
                if (model.Version >= @static.Version)
                {
                    return(model);
                }
                ReclaimTextureSpace(model);
                model.Dispose();
                Statics.Remove(@static);
            }

            // The data is either new or has changed, unfortunately we need to reload it
            try
            {
                model = new StaticModel(GraphicsDevice);
                model.Meshes.Add(ObjectMesh.FromWad2(GraphicsDevice, @static.Mesh, AllocateTexture));
                model.UpdateBuffers();
            }
            catch (TextureAtlasFullException exc)
            {
                logger.Info(exc.Message);

                if (maybeRebuildAll)
                {
                    logger.Info("Starting to rebuild the entire atlas.");
                    Dispose();
                    return(GetStatic(@static, false));
                }
            }

            Statics.Add(@static, model);
            return(model);
        }
Ejemplo n.º 4
0
        public static ObjectMesh FromWad2(GraphicsDevice device, WadMesh msh, Func <WadTexture, VectorInt2> allocateTexture)
        {
            Console.WriteLine(msh.Name);
            // Initialize the mesh
            var mesh = new ObjectMesh(device, msh.Name);

            // Prepare materials
            var materialOpaque                      = new Material(Material.Material_Opaque + "_0_0_0_0", null, false, false, 0);
            var materialOpaqueDoubleSided           = new Material(Material.Material_OpaqueDoubleSided + "_0_0_1_0", null, false, true, 0);
            var materialAdditiveBlending            = new Material(Material.Material_AdditiveBlending + "_0_1_0_0", null, true, false, 0);
            var materialAdditiveBlendingDoubleSided = new Material(Material.Material_AdditiveBlendingDoubleSided + "_0_1_1_0", null, true, true, 0);

            mesh.Materials = new List <Material>();
            mesh.Materials.Add(materialOpaque);
            mesh.Materials.Add(materialOpaqueDoubleSided);
            mesh.Materials.Add(materialAdditiveBlending);
            mesh.Materials.Add(materialAdditiveBlendingDoubleSided);

            mesh.Submeshes.Add(materialOpaque, new Submesh(materialOpaque));
            mesh.Submeshes.Add(materialOpaqueDoubleSided, new Submesh(materialOpaqueDoubleSided));
            mesh.Submeshes.Add(materialAdditiveBlending, new Submesh(materialAdditiveBlending));
            mesh.Submeshes.Add(materialAdditiveBlendingDoubleSided, new Submesh(materialAdditiveBlendingDoubleSided));

            mesh.BoundingBox    = msh.BoundingBox;
            mesh.BoundingSphere = msh.BoundingSphere;

            // For some reason, wad meshes sometimes may have position count desynced from color count, so we check that too.
            var hasShades = msh.VerticesShades.Count != 0 && msh.VerticesPositions.Count == msh.VerticesShades.Count;

            for (int j = 0; j < msh.Polys.Count; j++)
            {
                WadPolygon poly = msh.Polys[j];
                Vector2    positionInPackedTexture = allocateTexture((WadTexture)poly.Texture.Texture);

                // Get the right submesh
                var submesh = mesh.Submeshes[materialOpaque];
                if (poly.Texture.BlendMode == BlendMode.Additive)
                {
                    if (poly.Texture.DoubleSided)
                    {
                        submesh = mesh.Submeshes[materialAdditiveBlendingDoubleSided];
                    }
                    else
                    {
                        submesh = mesh.Submeshes[materialAdditiveBlending];
                    }
                }
                else
                {
                    if (poly.Texture.DoubleSided)
                    {
                        submesh = mesh.Submeshes[materialOpaqueDoubleSided];
                    }
                }

                // Do half-pixel correction on texture to prevent bleeding
                var coords = poly.Texture.TexCoords;
                var shape  = (int)TextureExtensions.GetTextureShapeType(poly.Texture.TexCoords, poly.Shape == WadPolygonShape.Triangle);

                for (int i = 0; i < (poly.Shape == WadPolygonShape.Triangle /*poly.Texture.TextureIsTriangle*/ ? 3 : 4); i++)
                {
                    if (poly.Shape == WadPolygonShape.Triangle /*poly.Texture.TextureIsTriangle*/)
                    {
                        coords[i] += TextureExtensions.CompensationTris[shape, i];
                    }
                    else
                    {
                        coords[i] += TextureExtensions.CompensationQuads[shape, i];
                    }
                }

                if (poly.Shape == WadPolygonShape.Triangle)
                {
                    int v1 = poly.Index0;
                    int v2 = poly.Index1;
                    int v3 = poly.Index2;

                    PutObjectVertexAndIndex(msh.VerticesPositions[v1], msh.VerticesNormals[v1], mesh, submesh,
                                            coords[0], 0, (short)(hasShades ? msh.VerticesShades[v1] : 0),
                                            positionInPackedTexture);
                    PutObjectVertexAndIndex(msh.VerticesPositions[v2], msh.VerticesNormals[v2], mesh, submesh,
                                            coords[1], 0, (short)(hasShades ? msh.VerticesShades[v2] : 0),
                                            positionInPackedTexture);
                    PutObjectVertexAndIndex(msh.VerticesPositions[v3], msh.VerticesNormals[v3], mesh, submesh,
                                            coords[2], 0, (short)(hasShades ? msh.VerticesShades[v3] : 0),
                                            positionInPackedTexture);
                }
                else
                {
                    int v1 = poly.Index0;
                    int v2 = poly.Index1;
                    int v3 = poly.Index2;
                    int v4 = poly.Index3;

                    PutObjectVertexAndIndex(msh.VerticesPositions[v1], msh.VerticesNormals[v1], mesh, submesh,
                                            coords[0], 0, (short)(hasShades ? msh.VerticesShades[v1] : 0),
                                            positionInPackedTexture);
                    PutObjectVertexAndIndex(msh.VerticesPositions[v2], msh.VerticesNormals[v2], mesh, submesh,
                                            coords[1], 0, (short)(hasShades ? msh.VerticesShades[v2] : 0),
                                            positionInPackedTexture);
                    PutObjectVertexAndIndex(msh.VerticesPositions[v4], msh.VerticesNormals[v4], mesh, submesh,
                                            coords[3], 0, (short)(hasShades ? msh.VerticesShades[v4] : 0),
                                            positionInPackedTexture);

                    PutObjectVertexAndIndex(msh.VerticesPositions[v4], msh.VerticesNormals[v4], mesh, submesh,
                                            coords[3], 0, (short)(hasShades ? msh.VerticesShades[v4] : 0),
                                            positionInPackedTexture);
                    PutObjectVertexAndIndex(msh.VerticesPositions[v2], msh.VerticesNormals[v2], mesh, submesh,
                                            coords[1], 0, (short)(hasShades ? msh.VerticesShades[v2] : 0),
                                            positionInPackedTexture);
                    PutObjectVertexAndIndex(msh.VerticesPositions[v3], msh.VerticesNormals[v3], mesh, submesh,
                                            coords[2], 0, (short)(hasShades ? msh.VerticesShades[v3] : 0),
                                            positionInPackedTexture);
                }
            }

            mesh.UpdateBuffers();

            return(mesh);
        }