public GroupLocation(BufferBuilder builder, int index, BufferGroup group)
 {
     Builder = builder;
     Index   = index;
     Group   = group;
 }
示例#2
0
        internal static async Task ConvertFaces(BufferBuilder builder, MapDocument document, IMapObject obj, List <Face> faces, ResourceCollector resourceCollector)
        {
            faces = faces.Where(x => x.Vertices.Count > 2).ToList();

            var displayFlags = document.Map.Data.GetOne <DisplayFlags>();
            var hideNull     = displayFlags?.HideNullTextures == true;

            // Pack the vertices like this [ f1v1 ... f1vn ] ... [ fnv1 ... fnvn ]
            var numVertices = (uint)faces.Sum(x => x.Vertices.Count);

            // Pack the indices like this [ solid1 ... solidn ] [ wireframe1 ... wireframe n ]
            var numSolidIndices     = (uint)faces.Sum(x => (x.Vertices.Count - 2) * 3);
            var numWireframeIndices = numVertices * 2;

            var points  = new VertexStandard[numVertices];
            var indices = new uint[numSolidIndices + numWireframeIndices];

            var colour = (obj.IsSelected ? Color.Red : obj.Data.GetOne <ObjectColor>()?.Color ?? Color.White).ToVector4();

            //var c = obj.IsSelected ? Color.FromArgb(255, 128, 128) : Color.White;
            //var tint = new Vector4(c.R, c.G, c.B, c.A) / 255f;
            var tint = Vector4.One;

            var tc = await document.Environment.GetTextureCollection();

            var pipeline = PipelineType.TexturedOpaque;
            var entityHasTransparency = false;
            var flags = obj.IsSelected ? VertexFlags.SelectiveTransformed : VertexFlags.None;

            // try and find the parent entity for render flags
            // TODO: this code is extremely specific to Goldsource and should be abstracted away
            var parentEntity = obj.FindClosestParent(x => x is Entity) as Entity;

            if (parentEntity?.EntityData != null)
            {
                const int renderModeColor    = 1;
                const int renderModeTexture  = 2;
                const int renderModeGlow     = 3; // same as texture for brushes
                const int renderModeSolid    = 4;
                const int renderModeAdditive = 5;

                var rendermode = parentEntity.EntityData.Get("rendermode", 0);
                var renderamt  = parentEntity.EntityData.Get("renderamt", 255f) / 255;
                entityHasTransparency = renderamt < 0.99;

                switch (rendermode)
                {
                case renderModeColor:
                    // Flat colour, use render colour and force it to run through the alpha tested pipeline
                    var rendercolor = parentEntity.EntityData.GetVector3("rendercolor") / 255f ?? Vector3.One;
                    tint     = new Vector4(rendercolor, renderamt);
                    flags   |= VertexFlags.FlatColour | VertexFlags.AlphaTested;
                    pipeline = PipelineType.TexturedAlpha;
                    entityHasTransparency = true;
                    break;

                case renderModeTexture:
                case renderModeGlow:
                    // Texture is alpha tested and can be transparent
                    tint   = new Vector4(1, 1, 1, renderamt);
                    flags |= VertexFlags.AlphaTested;
                    if (entityHasTransparency)
                    {
                        pipeline = PipelineType.TexturedAlpha;
                    }
                    break;

                case renderModeSolid:
                    // Texture is alpha tested only
                    flags |= VertexFlags.AlphaTested;
                    entityHasTransparency = false;
                    break;

                case renderModeAdditive:
                    // Texture is alpha tested and transparent, force through the additive pipeline
                    tint     = new Vector4(renderamt, renderamt, renderamt, 1);
                    pipeline = PipelineType.TexturedAdditive;
                    entityHasTransparency = true;
                    break;

                default:
                    entityHasTransparency = false;
                    break;
                }
            }

            if (obj.IsSelected)
            {
                tint *= new Vector4(1, 0.5f, 0.5f, 1);
            }

            var vi = 0u;
            var si = 0u;
            var wi = numSolidIndices;

            foreach (var face in faces)
            {
                var opacity = tc.GetOpacity(face.Texture.Name);
                var t       = await tc.GetTextureItem(face.Texture.Name);

                var w = t?.Width ?? 0;
                var h = t?.Height ?? 0;

                var tintModifier = new Vector4(1, 1, 1, opacity);
                var extraFlags   = t == null ? VertexFlags.FlatColour : VertexFlags.None;

                var offs         = vi;
                var numFaceVerts = (uint)face.Vertices.Count;

                var textureCoords = face.GetTextureCoordinates(w, h).ToList();

                var normal = face.Plane.Normal;
                for (var i = 0; i < face.Vertices.Count; i++)
                {
                    var v = face.Vertices[i];
                    points[vi++] = new VertexStandard
                    {
                        Position = v,
                        Colour   = colour,
                        Normal   = normal,
                        Texture  = new Vector2(textureCoords[i].Item2, textureCoords[i].Item3),
                        Tint     = tint * tintModifier,
                        Flags    = flags | extraFlags
                    };
                }

                // Triangles - [0 1 2]  ... [0 n-1 n]
                for (uint i = 2; i < numFaceVerts; i++)
                {
                    indices[si++] = offs;
                    indices[si++] = offs + i - 1;
                    indices[si++] = offs + i;
                }

                // Lines - [0 1] ... [n-1 n] [n 0]
                for (uint i = 0; i < numFaceVerts; i++)
                {
                    indices[wi++] = offs + i;
                    indices[wi++] = offs + (i == numFaceVerts - 1 ? 0 : i + 1);
                }
            }

            var groups = new List <BufferGroup>();

            uint texOffset = 0;

            foreach (var f in faces)
            {
                var texInd = (uint)(f.Vertices.Count - 2) * 3;

                if (hideNull && tc.IsNullTexture(f.Texture.Name))
                {
                    texOffset += texInd;
                    continue;
                }

                var opacity = tc.GetOpacity(f.Texture.Name);
                var t       = await tc.GetTextureItem(f.Texture.Name);

                var transparent = entityHasTransparency || opacity < 0.95f || t?.Flags.HasFlag(TextureFlags.Transparent) == true;

                var texture = t == null ? string.Empty : $"{document.Environment.ID}::{f.Texture.Name}";

                var group = new BufferGroup(
                    pipeline == PipelineType.TexturedOpaque && transparent ? PipelineType.TexturedAlpha : pipeline,
                    CameraType.Perspective, transparent, f.Origin, texture, texOffset, texInd
                    );
                groups.Add(group);

                texOffset += texInd;

                if (t != null)
                {
                    resourceCollector.RequireTexture(t.Name);
                }
            }

            groups.Add(new BufferGroup(PipelineType.Wireframe, obj.IsSelected ? CameraType.Both : CameraType.Orthographic, numSolidIndices, numWireframeIndices));

            builder.Append(points, indices, groups);

            // Also push the untransformed wireframe when selected
            if (obj.IsSelected)
            {
                for (var i = 0; i < points.Length; i++)
                {
                    points[i].Flags = VertexFlags.None;
                }
                var untransformedIndices = indices.Skip((int)numSolidIndices);
                builder.Append(points, untransformedIndices, new[]
                {
                    new BufferGroup(PipelineType.Wireframe, CameraType.Both, 0, numWireframeIndices)
                });
            }
        }
 public GroupLocation(int index, BufferGroup group)
 {
     Index = index;
     Group = group;
 }