/// <summary> /// Create a sphere. /// </summary> /// <param name="radius"> /// A <see cref="Single"/> that specifies the radius of the sphere. /// </param> /// <param name="slices"> /// A <see cref="Int32"/> that specifies the number of horizontal subdivisions of the sphere. /// </param> /// <param name="stacks"> /// A <see cref="Int32"/> that specifies the number of vertical subdivisions of the sphere. /// </param> /// <returns> /// It returns a <see cref="Objects.VertexArrays"/> defining the following semantics: /// - Positions /// - Normals /// </returns> public static VertexArrays CreateSphere(float radius, int slices, int stacks) { VertexArrays vertexArray = new VertexArrays(); // Vertex generation Vertex3f[] position, normal; ushort[] indices; int vertexCount; GenerateSphere(radius, slices, stacks, out position, out normal, out indices, out vertexCount); // Buffer definition ArrayBuffer <Vertex3f> positionBuffer = new ArrayBuffer <Vertex3f>(); positionBuffer.Create(position); vertexArray.SetArray(positionBuffer, VertexArraySemantic.Position); ArrayBuffer <Vertex3f> normalBuffer = new ArrayBuffer <Vertex3f>(); normalBuffer.Create(normal); vertexArray.SetArray(normalBuffer, VertexArraySemantic.Normal); ElementBuffer <ushort> elementBuffer = new ElementBuffer <ushort>(); elementBuffer.Create(indices); vertexArray.SetElementArray(PrimitiveType.TriangleStrip, elementBuffer); return(vertexArray); }
public static VertexArrays CreateCone(float radius, float height, uint dr) { VertexArrays vertexArray = new VertexArrays(); // Vertex generation Vertex3f[] position = new Vertex3f[dr + 2]; int positionIndex = 0; position[positionIndex++] = new Vertex3f(0.0f, 0.0f, -height); double angleStep = Math.PI * 2.0 / dr; for (double angle = 0.0f; angle <= Math.PI * 2.0; angle += angleStep) { float x = radius * (float)Math.Cos(angle); float y = radius * (float)Math.Sin(angle); Debug.Assert(positionIndex < position.Length); position[positionIndex++] = new Vertex3f(x, y, 0.0f); } position[positionIndex++] = position[1]; // Buffer definition ArrayBuffer <Vertex3f> positionBuffer = new ArrayBuffer <Vertex3f>(); positionBuffer.Create(position); vertexArray.SetArray(positionBuffer, VertexArraySemantic.Position); vertexArray.SetElementArray(PrimitiveType.TriangleFan); return(vertexArray); }
/// <summary> /// /// </summary> /// <param name="x"></param> /// <param name="y"></param> /// <param name="dx"></param> /// <param name="dy"></param> /// <returns></returns> public static VertexArrays CreatePlane(float x, float y, float z, uint dx, uint dy) { VertexArrays vertexArray = new VertexArrays(); // 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 restartIndex = ElementBuffer <uint> .DefaultRestartIndex; 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); indices.Add(restartIndex); } // Buffer definition ArrayBuffer <Vertex3f> positionBuffer = new ArrayBuffer <Vertex3f>(); positionBuffer.Create(position); vertexArray.SetArray(positionBuffer, VertexArraySemantic.Position); ElementBuffer <uint> elementBuffer = new ElementBuffer <uint>(); elementBuffer.Create(indices.ToArray()); elementBuffer.RestartIndexEnabled = true; vertexArray.SetElementArray(PrimitiveType.TriangleStrip, elementBuffer); return(vertexArray); }
/// <summary> /// Create a <see cref="VertexArrays"/> for rendering glyphs. /// </summary> private void LinkSharedResources(GraphicsContext ctx) { CheckCurrentContext(ctx); string resourceClassId = "OpenGL.Objects.FontPatch"; string resourceBaseId = String.Format("{0}.{1}-{2}-{3}", resourceClassId, Family, Size, Style); string vertexArrayId = resourceBaseId + ".VertexArray"; string glyphDbId = resourceBaseId + ".GlyphDb"; #region Vertex Arrays _VertexArrays = (VertexArrays)ctx.GetSharedResource(vertexArrayId); Dictionary <char, Glyph> glyphsDb = null; if (_VertexArrays == null) { _VertexArrays = new VertexArrays(); List <GlyphPolygons> glyphPolygons = GenerateGlyphs(Family, Size, Style); List <Vertex2f> glyphsVertices = new List <Vertex2f>(); GlyphPolygons gGlyph = null; uint gVertexIndex = 0; glyphsDb = 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 ArrayBuffer <Vertex2f> gVertexPosition = new ArrayBuffer <Vertex2f>(); gVertexPosition.Create(glyphsVertices.ToArray()); _VertexArrays.SetArray(gVertexPosition, VertexArraySemantic.Position); // Share ctx.SetSharedResource(vertexArrayId, _VertexArrays); } LinkResource(_VertexArrays); #endregion #region Glyph Metadata _Glyphs = (Dictionary <char, Glyph>)ctx.GetSharedResource(glyphDbId); if (glyphsDb != null) { _Glyphs = glyphsDb; } if (_Glyphs == null) { throw new InvalidProgramException("no glyph metadata"); } // Share ctx.SetSharedResource(glyphDbId, _Glyphs); #endregion }
/// <summary> /// Create resources for rendering glyphs. /// </summary> /// <param name="ctx"></param> private void LinkSharedResources(GraphicsContext ctx) { CheckCurrentContext(ctx); StringFormat stringFormat = StringFormat.GenericTypographic; // Font-wide resources string resourceClassId = "OpenGL.Objects.FontTextureArray2d"; string resourceBaseId = String.Format("{0}.{1}-{2}-{3}", resourceClassId, Family, Size, Style); #region Instanced Arrays if (ctx.Extensions.InstancedArrays) { string instanceArrayId = resourceClassId + ".InstanceArray"; _GlyphInstances = (ArrayBufferObjectInterleaved <GlyphInstance>)ctx.GetSharedResource(instanceArrayId); if (_GlyphInstances == null) { _GlyphInstances = new ArrayBufferObjectInterleaved <GlyphInstance>(MapBufferUsageMask.MapWriteBit); _GlyphInstances.Create(256); // Share ctx.SetSharedResource(instanceArrayId, _GlyphInstances); } LinkResource(_GlyphInstances); } else { _GlyphInstances = null; } #endregion #region Vertex Array string vertexArrayId = resourceClassId + ".VertexArray"; _VertexArrays = (VertexArrays)ctx.GetSharedResource(vertexArrayId); if (_VertexArrays == null) { _VertexArrays = new VertexArrays(); ArrayBuffer <Vertex2f> arrayPosition = new ArrayBuffer <Vertex2f>(); 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); if (ctx.Extensions.InstancedArrays) { _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); #endregion #region Glyphs Metadata string glyphDbId = resourceBaseId + ".GlyphDb"; _GlyphMetadata = (Dictionary <char, Glyph>)ctx.GetSharedResource(glyphDbId); if (_GlyphMetadata == null) { _GlyphMetadata = 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)); _GlyphMetadata.Add(c, glyph); } } // Share ctx.SetSharedResource(glyphDbId, _GlyphMetadata); } #endregion #region Glyph Sampler string samplerId = resourceBaseId + ".Sampler"; Sampler sampler = (Sampler)ctx.GetSharedResource(samplerId); if (sampler == null) { sampler = new Sampler(); sampler.Parameters.MinFilter = TextureMinFilter.Linear; } #endregion #region Glyph Texture string textureId = resourceBaseId + ".Texture"; _FontTexture = (TextureArray2d)ctx.GetSharedResource(textureId); if (_FontTexture == null) { // Get the size required for all glyphs float w = 0.0f, h = 0.0f; uint z = 0; foreach (Glyph glyph in _GlyphMetadata.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(); _FontTexture.Sampler = sampler; _FontTexture.Create(ctx, (uint)Math.Ceiling(w), (uint)Math.Ceiling(h), z + 1, PixelLayout.R8, 1); using (System.Drawing.Font font = new System.Drawing.Font(Family, Size, Style)) using (Brush brush = new SolidBrush(Color.White)) { foreach (Glyph glyph in _GlyphMetadata.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); #endregion }
/// <summary> /// Initialize the IVertexArrayTexGen instance. /// </summary> public virtual void Initialize(VertexArrays vertexArray) { }
/// <summary> /// Initialize the IVertexArrayTexGen instance. /// </summary> public override void Initialize(VertexArrays vertexArray) { }