Example #1
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <param name="dx"></param>
        /// <param name="dy"></param>
        /// <returns></returns>
        public static VertexArrayObject CreatePlane(float x, float y, float z, uint dx, uint dy)
        {
            VertexArrayObject vertexArray = new VertexArrayObject();

            // Vertex generation
            Vertex3f[] position = new Vertex3f[(dx + 1) * (dy + 1)];
            float      x2 = x / 2.0f, y2 = y / 2.0f;
            float      vdx = x / dx, vdy = y / dy;
            int        vidx = 0;

            for (float vy = -y2; vy <= y2; vy += vdy)
            {
                for (float vx = -x2; vx <= x2; vx += vdx)
                {
                    Debug.Assert(vidx < position.Length);
                    position[vidx++] = new Vertex3f(vx, vy, z);
                }
            }

            // Elements generation
            List <uint> indices = new List <uint>();
            uint        vstride = dx + 1;

            for (uint i = 0; i < dy; i++)
            {
                uint yoffset = i * vstride;

                // Triangle strip start
                indices.Add(yoffset + vstride);

                for (uint ix = 0; ix < dx; ix++)
                {
                    uint xoffset = yoffset + ix;

                    indices.Add(xoffset);
                    indices.Add(xoffset + vstride + 1);
                }

                indices.Add(yoffset + vstride - 1);

                if (Gl.CurrentExtensions.PrimitiveRestart == false)
                {
                    throw new NotImplementedException();
                }
                else
                {
                    indices.Add(uint.MaxValue);
                }
            }

            // Buffer definition
            ArrayBufferObject <Vertex3f> positionBuffer = new ArrayBufferObject <Vertex3f>(BufferObjectHint.StaticCpuDraw);

            positionBuffer.Create(position);
            vertexArray.SetArray(positionBuffer, VertexArraySemantic.Position);

            ElementBufferObject <uint> elementBuffer = new ElementBufferObject <uint>(BufferObjectHint.StaticCpuDraw);

            elementBuffer.Create(indices.ToArray());
            elementBuffer.RestartIndexEnabled = Gl.CurrentExtensions.PrimitiveRestart;
            vertexArray.SetElementArray(PrimitiveType.TriangleStrip, elementBuffer);

            return(vertexArray);
        }
Example #2
0
        /// <summary>
        /// Create a <see cref="VertexArrayObject"/> for rendering glyphs.
        /// </summary>
        /// <param name="fontFamily"></param>
        /// <param name="emSize"></param>
        /// <param name="glyphs"></param>
        /// <returns></returns>
        private static VertexArrayObject CreateVertexArray(GraphicsContext ctx, FontFamily fontFamily, uint emSize, FontStyle fontStyle, out Dictionary <char, Glyph> glyphs)
        {
            CheckCurrentContext(ctx);

            string resourceBaseId = String.Format("OpenGL.Objects.FontPatch.{0}-{1}-{2}", fontFamily, emSize, fontStyle);
            string vertexArrayId  = resourceBaseId + ".VertexArray";
            string glyphDbId      = resourceBaseId + ".GlyphDb";

            VertexArrayObject        vertexArrays = (VertexArrayObject)ctx.GetSharedResource(vertexArrayId);
            Dictionary <char, Glyph> glyphsDb     = (Dictionary <char, Glyph>)ctx.GetSharedResource(glyphDbId);

            if (vertexArrays != null && glyphsDb != null)
            {
                glyphs = glyphsDb;
                return(vertexArrays);
            }

            vertexArrays = new VertexArrayObject();
            glyphsDb     = new Dictionary <char, Glyph>();

            List <GlyphPolygons> glyphPolygons  = GenerateGlyphs(fontFamily, emSize, fontStyle);
            List <Vertex2f>      glyphsVertices = new List <Vertex2f>();
            GlyphPolygons        gGlyph         = null;
            uint gVertexIndex = 0;

            glyphs = new Dictionary <char, Glyph>();

            using (Tessellator tessellator = new Tessellator()) {
                tessellator.Begin += delegate(object sender, TessellatorBeginEventArgs e) {
                    gVertexIndex = (uint)glyphsVertices.Count;
                };
                tessellator.End += delegate(object sender, EventArgs e) {
                    // Create element (range)
                    int glyphIndex = vertexArrays.SetElementArray(PrimitiveType.Triangles, gVertexIndex, (uint)glyphsVertices.Count - gVertexIndex);

                    glyphsDb.Add(gGlyph.GlyphChar, new Glyph(gGlyph.GlyphChar, gGlyph.GlyphSize, glyphIndex));
                };
                tessellator.Vertex += delegate(object sender, TessellatorVertexEventArgs e) {
                    glyphsVertices.Add((Vertex2f)e.Vertex);
                };

                // Tessellate all glyphs
                foreach (GlyphPolygons glyph in glyphPolygons)
                {
                    gGlyph = glyph;

                    if (glyph.Contours.Count == 0)
                    {
                        glyphsDb.Add(gGlyph.GlyphChar, new Glyph(gGlyph.GlyphChar, gGlyph.GlyphSize, -1));
                        continue;
                    }

                    tessellator.BeginPolygon();
                    foreach (List <Vertex2f> countour in glyph.Contours)
                    {
                        tessellator.AddContour(countour.ToArray(), Vertex3f.UnitZ);
                    }
                    tessellator.EndPolygon();
                }
            }

            // Element vertices
            ArrayBufferObject <Vertex2f> gVertexPosition = new ArrayBufferObject <Vertex2f>(BufferObjectHint.StaticCpuDraw);

            gVertexPosition.Create(glyphsVertices.ToArray());
            vertexArrays.SetArray(gVertexPosition, VertexArraySemantic.Position);

            // Returns glyphs database
            glyphs = glyphsDb;

            // Share resources
            ctx.SetSharedResource(vertexArrayId, vertexArrays);
            ctx.SetSharedResource(glyphDbId, glyphsDb);

            return(vertexArrays);
        }
            /// <summary>
            /// Generate tangents for this Element.
            /// </summary>
            /// <param name="vertexArray">
            /// The <see cref="VertexArrayObject"/>
            /// </param>
            public override void GenerateTangents(VertexArrayObject vertexArray)
            {
                IVertexArray positionArray = vertexArray.GetVertexArray(VertexArraySemantic.Position);

                if (positionArray == null)
                {
                    throw new InvalidOperationException("position semantic not set");
                }
                IVertexArray texArray = vertexArray.GetVertexArray(VertexArraySemantic.TexCoord);

                if (texArray == null)
                {
                    throw new InvalidOperationException("texture semantic not set");
                }

                IVertexArray normalArray = vertexArray.GetVertexArray(VertexArraySemantic.Normal);

                if (normalArray == null)
                {
                    throw new InvalidOperationException("normal semantic not set");
                }
                if (normalArray.Array == null)
                {
                    throw new InvalidOperationException("normal array not set");
                }

                IVertexArray tanArray = vertexArray.GetVertexArray(VertexArraySemantic.Tangent);

                if (tanArray == null)
                {
                    throw new InvalidOperationException("tangent semantic not set");
                }
                if (tanArray.Array == null)
                {
                    throw new InvalidOperationException("tangent array not set");
                }

                IVertexArray bitanArray = vertexArray.GetVertexArray(VertexArraySemantic.Bitangent);

                if (bitanArray == null)
                {
                    throw new InvalidOperationException("bitangent semantic not set");
                }
                if (bitanArray.Array == null)
                {
                    throw new InvalidOperationException("bitangent array not set");
                }

                if (positionArray.Array != null)
                {
                    positionArray.Array.Map();
                }
                if (texArray.Array != null)
                {
                    texArray.Array.Map();
                }
                normalArray.Array.Map();
                tanArray.Array.Map();
                bitanArray.Array.Map();
                ArrayIndices.Map();

                try {
                    switch (ElementsMode)
                    {
                    case PrimitiveType.TriangleStrip:
                        switch (positionArray.ArraySection.ItemType)
                        {
                        case ArrayBufferItemType.Float3:
                            GenerateTangentsTriangleStrip3f(positionArray, normalArray, texArray, tanArray, bitanArray);
                            break;

                        default:
                            throw new NotSupportedException("normals generation not supported for elements of type " + positionArray.ArraySection.ItemType);
                        }
                        break;

                    default:
                        throw new NotSupportedException("normals generation not supported for primitive " + ElementsMode);
                    }
                } finally {
                    if (positionArray.Array != null)
                    {
                        positionArray.Array.Unmap();
                    }
                    if (texArray.Array != null)
                    {
                        texArray.Array.Unmap();
                    }
                    normalArray.Array.Unmap();
                    tanArray.Array.Unmap();
                    bitanArray.Array.Unmap();
                    ArrayIndices.Unmap();
                }
            }
Example #4
0
        /// <summary>
        /// Create a <see cref="VertexArrayObject"/> for rendering glyphs.
        /// </summary>
        /// <param name="fontFamily"></param>
        /// <param name="emSize"></param>
        /// <param name="glyphs"></param>
        /// <returns></returns>
        private void LinkSharedResources(GraphicsContext ctx)
        {
            CheckCurrentContext(ctx);

            // Font-wide resources
            string resourceClassId = "OpenGL.Objects.FontTextureArray2d";

            string instanceArrayId = resourceClassId + ".InstanceArray";
            string vertexArrayId   = resourceClassId + ".VertexArray";

            _GlyphInstances = (ArrayBufferObjectInterleaved <GlyphInstance>)ctx.GetSharedResource(instanceArrayId);
            _VertexArrays   = (VertexArrayObject)ctx.GetSharedResource(vertexArrayId);

            if (_GlyphInstances == null)
            {
                _GlyphInstances = new ArrayBufferObjectInterleaved <GlyphInstance>(BufferObjectHint.DynamicCpuDraw);
                _GlyphInstances.Create(256);
                // Share
                ctx.SetSharedResource(instanceArrayId, _GlyphInstances);
            }
            LinkResource(_GlyphInstances);

            if (_VertexArrays == null)
            {
                _VertexArrays = new VertexArrayObject();

                ArrayBufferObject <Vertex2f> arrayPosition = new ArrayBufferObject <Vertex2f>(BufferObjectHint.StaticCpuDraw);
                arrayPosition.Create(new Vertex2f[] {
                    new Vertex2f(0.0f, 1.0f),
                    new Vertex2f(0.0f, 0.0f),
                    new Vertex2f(1.0f, 1.0f),
                    new Vertex2f(1.0f, 0.0f),
                });
                _VertexArrays.SetArray(arrayPosition, VertexArraySemantic.Position);
                _VertexArrays.SetInstancedArray(_GlyphInstances, 0, 1, "glo_GlyphModelViewProjection");
                _VertexArrays.SetInstancedArray(_GlyphInstances, 1, 1, "glo_GlyphVertexParams");
                _VertexArrays.SetInstancedArray(_GlyphInstances, 2, 1, "glo_GlyphTexParams");
                _VertexArrays.SetElementArray(PrimitiveType.TriangleStrip);
                // Share
                ctx.SetSharedResource(vertexArrayId, _VertexArrays);
            }
            LinkResource(_VertexArrays);

            // Font resources
            string resourceBaseId = String.Format("{0}.{1}-{2}-{3}", resourceClassId, Family, Size, Style);

            string glyphDbId = resourceBaseId + ".GlyphDb";
            string textureId = resourceBaseId + ".Texture";

            _GlyphDb     = (Dictionary <char, Glyph>)ctx.GetSharedResource(glyphDbId);
            _FontTexture = (TextureArray2d)ctx.GetSharedResource(textureId);

            StringFormat stringFormat = StringFormat.GenericTypographic;

            if (_GlyphDb == null)
            {
                _GlyphDb = new Dictionary <char, Glyph>();

                char[] fontChars = GetFontCharacters().ToCharArray();
                uint   layer     = 0;

                using (Bitmap bitmap = new Bitmap(1, 1))
                    using (Graphics g = Graphics.FromImage(bitmap))
                        using (System.Drawing.Font font = new System.Drawing.Font(Family, Size, Style))
                        {
                            // Avoid grid fitting
                            g.TextRenderingHint = TextRenderingHint.AntiAlias;

                            float glyphHeight = font.GetHeight();

                            foreach (char c in fontChars)
                            {
                                SizeF glyphSize;

                                switch (c)
                                {
                                case ' ':
                                    glyphSize = g.MeasureString(c.ToString(), font, 0, StringFormat.GenericDefault);
                                    break;

                                default:
                                    glyphSize = g.MeasureString(c.ToString(), font, 0, stringFormat);
                                    break;
                                }

                                Glyph glyph = new Glyph(c, glyphSize, layer++, new SizeF(1.0f, 1.0f));

                                _GlyphDb.Add(c, glyph);
                            }
                        }

                // Share
                ctx.SetSharedResource(glyphDbId, _GlyphDb);
            }

            if (_FontTexture == null)
            {
                // Get the size required for all glyphs
                float w = 0.0f, h = 0.0f;
                uint  z = 0;

                foreach (Glyph glyph in _GlyphDb.Values)
                {
                    w = Math.Max(w, glyph.GlyphSize.Width);
                    h = Math.Max(h, glyph.GlyphSize.Height);
                    z = Math.Max(z, glyph.Layer);
                }

                // Create texture
                _FontTexture = new TextureArray2d((uint)Math.Ceiling(w), (uint)Math.Ceiling(h), z + 1, PixelLayout.R8);
                _FontTexture.Create(ctx);

                using (System.Drawing.Font font = new System.Drawing.Font(Family, Size, Style))
                    using (Brush brush = new SolidBrush(Color.White))
                    {
                        foreach (Glyph glyph in _GlyphDb.Values)
                        {
                            using (Bitmap bitmap = new Bitmap((int)_FontTexture.Width, (int)_FontTexture.Height, System.Drawing.Imaging.PixelFormat.Format24bppRgb))
                                using (Graphics g = Graphics.FromImage(bitmap)) {
                                    // Recompute texture scaling
                                    glyph.TexScale = new SizeF(
                                        glyph.GlyphSize.Width / bitmap.Width,
                                        glyph.GlyphSize.Height / bitmap.Height
                                        );

                                    // Avoid grid fitting
                                    g.TextRenderingHint = TextRenderingHint.AntiAlias;
                                    g.Clear(Color.Black);
                                    g.DrawString(glyph.GlyphChar.ToString(), font, brush, 0.0f, 0.0f, stringFormat);

                                    _FontTexture.Create(ctx, PixelLayout.R8, bitmap, glyph.Layer);
                                }
                        }
                    }

                // Share
                ctx.SetSharedResource(textureId, _FontTexture);
            }
            LinkResource(_FontTexture);
        }
 /// <summary>
 /// Specify which elements shall be drawn by indexing them, specifying an offset and the number of element indices.
 /// </summary>
 /// <param name="mode">
 /// A <see cref="PrimitiveType"/> that indicates how array elements are interpreted.
 /// </param>
 /// <param name="indices">
 /// A <see cref="ElementBufferObject"/> containing the indices of the drawn vertices.
 /// </param>
 /// <exception cref="ArgumentNullException">
 /// Exception thrown if <paramref name="indices"/> is null.
 /// </exception>
 /// <remarks>
 /// The element indices count is implictly defined by <paramref name="indices"/> at <see cref="Draw(GraphicsContext)"/>
 /// execution time.
 /// </remarks>
 public IndexedElement(VertexArrayObject vao, PrimitiveType mode, ElementBufferObject indices) :
     this(vao, mode, indices, 0, 0)
 {
 }
 /// <summary>
 /// Specify which elements shall be drawn.
 /// </summary>
 /// <param name="mode">
 /// A <see cref="PrimitiveType"/> that indicates how array elements are interpreted.
 /// </param>
 /// <remarks>
 /// The array elements count is implictly defined as the vertex array length at <see cref="Draw(GraphicsContext)"/>
 /// execution time.
 /// </remarks>
 public ArrayElement(VertexArrayObject vao, PrimitiveType mode) :
     this(vao, mode, 0, 0)
 {
 }
 /// <summary>
 /// Specify which elements shall be drawn, specifying an offset and the number of elements.
 /// </summary>
 /// <param name="vao">
 /// The <see cref="VertexArrayObject"/> to which this element belongs to.
 /// </param>
 /// <param name="mode">
 /// A <see cref="PrimitiveType"/> that indicates how array elements are interpreted.
 /// </param>
 /// <param name="offset">
 /// A <see cref="UInt32"/> that specify the offset applied to the drawn array elements.
 /// </param>
 /// <param name="count">
 /// A <see cref="UInt32"/> that specify the number of array elements drawn.
 /// </param>
 public ArrayElement(VertexArrayObject vao, PrimitiveType mode, uint offset, uint count) :
     base(vao, mode)
 {
     ElementOffset = offset;
     ElementCount  = count;
 }
 /// <summary>
 /// Generate bitangents for this Element.
 /// </summary>
 /// <param name="vertexArray">
 /// The <see cref="VertexArrayObject"/>
 /// </param>
 public virtual void GenerateBitangents(VertexArrayObject vertexArray)
 {
     throw new NotImplementedException();
 }
 /// <summary>
 /// Generate texture coordinates for this Element.
 /// </summary>
 /// <param name="vertexArray">
 /// The <see cref="VertexArrayObject"/>
 /// </param>
 public virtual void GenerateTexCoord(VertexArrayObject vertexArray, VertexArrayTexGenDelegate genTexCoordCallback)
 {
     throw new NotImplementedException();
 }