Never Sleeper's picture

How to create a sphere?

Hello Everyone,

my last experience with OpenGL is a few years ago and I was more used to it in Java. Now I need a working environment in C# so thats the reason why I'm trying to use OpenTK.

I just need a simple example how to draw a sphere in OpenTK. I've found the IsoSphere in the examples and I can draw kind of some circles but there not building a full coloured sphere.

Here is the important code and I'm attaching the result as a picture:

 
        IsoSphere iso = new IsoSphere(30, 30, 30, 30, 30);
 
        GL.Translate(50, 50, -5); 
 
        GL.Color3(Color.Red);
        GL.PolygonMode(MaterialFace.Front, PolygonMode.Fill);
 
        GL.Begin(BeginMode.TriangleFan);
 
        for (int i = 0; i < iso.Vertices.Length; i++) {
 
            GL.Vertex3(iso.Vertices[i]);
        }
        GL.End();

I really appreciate every help! = (

Inline Images

Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
NightmareX2000's picture

If it makes sense, here is what I found and put together to make things simpler...
Important Note: Not sure that Pixel struct behaves correct, may need formating for RGBA~order.

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Runtime.InteropServices;
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;
 
public struct Vertex
{
    public Vector2 TexCoord;
    public Vector3 Normal;
    public Vector3 Position;
    public Pixel Pixel;
 
    public Vertex(Vector2 texCoord, Vector3 normal, Vector3 position) : this()
    {
        TexCoord = texCoord;
        Normal = normal;
        Position = position;
        Pixel.uintColor = uint.MaxValue;
    }
 
    public Vertex(Vector2 texCoord, Vector3 normal, Vector3 position, Pixel pixel) : this()
    {
        TexCoord = texCoord;
        Normal = normal;
        Position = position;
        Pixel = pixel;
    }
}
 
[StructLayout(LayoutKind.Explicit)]
public struct Pixel
{
    [FieldOffset(0)]
    public byte B;
    [FieldOffset(1)]
    public byte G;
    [FieldOffset(2)]
    public byte R;
    [FieldOffset(3)]
    public byte A;
    [FieldOffset(0)]
    public uint uintColor;
    [FieldOffset(0)]
    public int intColor;
 
    public static Pixel White { get { return new Pixel(uint.MaxValue); } }
 
    public Pixel(Color color) : this()
    {
        B = color.B;
        G = color.G;
        R = color.R;
        A = color.A;
    }
 
    public Pixel(Color4 color) : this()
    {
        fB = color.B;
        fG = color.G;
        fR = color.R;
        fA = color.A;
    }
 
    public Pixel(int color) : this()
    {
         intColor = color;
    }
 
    public Pixel(uint color) : this()
    {
         uintColor = color;
    }
 
    public float fA
    {
        get { return A / 255f; }
        set { A = (byte)(value * 255); }
    }
    public float fR
    {
        get { return R / 255f; }
        set { R = (byte)(value * 255); }
    }
    public float fG
    {
        get { return G / 255f; }
        set { G = (byte)(value * 255); }
    }
    public float fB
    {
        get { return B / 255f; }
        set { B = (byte)(value * 255); }
    }
 
    public byte GrayScale
    {
        get { return (byte)((R + G + B) / 3); }
        set { R = G = B = value; }
    }
    public float fGrayScale
    {
        get { return (fR + fG + fB) / 3f; }
        set { fR = fG = fB = value; }
    }
}
 
public static class GluEx
{
    public static ushort[] CalculateElements(byte segments, byte rings)
    {
        ushort[] data = new ushort[segments * rings * 6];
 
        ushort i = 0;
 
        for (byte y = 0; y < rings - 1; y++)
        {
            for (byte x = 0; x < segments - 1; x++)
            {
                data[i++] = (ushort)((y + 0) * segments + x);
                data[i++] = (ushort)((y + 1) * segments + x);
                data[i++] = (ushort)((y + 1) * segments + x + 1);
 
                data[i++] = (ushort)((y + 1) * segments + x + 1);
                data[i++] = (ushort)((y + 0) * segments + x + 1);
                data[i++] = (ushort)((y + 0) * segments + x);
            }
        }
 
        // Verify that we don't access any vertices out of bounds:
        foreach (int index in data)
            if (index >= segments * rings)
                throw new IndexOutOfRangeException();
 
        return data;
    }
 
    public static class SphereShape
    {
        public static Vertex[] CalculateVertices(double radius, double height, byte segments, byte rings)
        {
            Vertex[] data = new Vertex[segments * rings];
 
            int i = 0;
 
            for (double y = 0; y < rings; y++)
            {
                double phi = (y / (rings - 1)) * Math.PI;
                for (double x = 0; x < segments; x++)  
                {
                    double theta = (x / (segments - 1)) * 2 * Math.PI;
 
                    Vector3 v = new Vector3()
                    {
                        X = (float)(radius * Math.Sin(phi) * Math.Cos(theta)),
                        Y = (float)(height * Math.Cos(phi)),
                        Z = (float)(radius * Math.Sin(phi) * Math.Sin(theta))
                    };
                    Vector3 n = Vector3.Normalize(v);
                    Vector2 uv = new Vector2()
                    {
                        X = (float)(x / (segments - 1)),
                        Y = (float)(y / (rings - 1))
                    };
                    data[i] = new Vertex(uv, n, v);
                    i++;
                }
            }
 
            return data;
        }
    }
 
    public static void Draw(BeginMode beginMode, Vertex[] vertices, IEnumerable<ushort> elements)
    {
        GL.Begin(beginMode);
 
        foreach (ushort element in elements)
        {
            Vertex vertex = vertices[element];
            GL.TexCoord2(vertex.TexCoord);
            GL.Normal3(vertex.Normal);
            GL.Color4(vertex.Pixel.R, vertex.Pixel.G, vertex.Pixel.B, vertex.Pixel.A);
            GL.Vertex3(vertex.Position);
        }
        GL.End();
    }
}
Never Sleeper's picture

Thank you for your response. I've implemented your code samples and it works the same like the example of IsoSphere.

The problem is just that I want to see a full colored circle at the moment. There just connected vertices by lines. If I try to use "Polygon"-Mode to draw, its getting more worse.

I know this such a noobish questions. =(

the Fiddler's picture

You should use BeginMode.Triangles, not Polygons.

Never Sleeper's picture

I've tried that too but the result gets worse. I've got only dots in space and not even more some kind of connection. =/