سؤال

So in my program there is a function for drawing a cube. I am using c# with monodevelop on linux. Here is the function:

private int DrawCube(float x, float y, float z, float ori, int SideTexture, int TopTexture, int BottomTexture)
{
    GL.PushMatrix();

    GL.Translate(x, y, z);
    GL.Rotate(ori, 0, 1, 0);

    GL.BindTexture(TextureTarget.Texture2D, SideTexture);

    GL.Begin(BeginMode.Quads);

    GL.Color3(Color.White);
    GL.TexCoord2(0.0f, 1.0f - 0.0f); GL.Vertex3(0, 0, 0);
    GL.TexCoord2(1.0f, 1.0f - 0.0f); GL.Vertex3(20, 0, 0);
    GL.TexCoord2(1.0f, 1.0f - 1.0f); GL.Vertex3(20, 20, 0);
    GL.TexCoord2(0.0f, 1.0f - 1.0f); GL.Vertex3(0, 20, 0);
    //Top
    //GL.ActiveTexture(TextureUnit.Texture0);
    GL.BindTexture(TextureTarget.Texture2D, TopTexture);
    GL.TexCoord2(0.0f, 1.0f - 0.0f); GL.Vertex3(20, 0, 0);
    GL.TexCoord2(1.0f, 1.0f - 0.0f); GL.Vertex3(20, 0, -20);
    GL.TexCoord2(1.0f, 1.0f - 1.0f); GL.Vertex3(20, 20, -20);
    GL.TexCoord2(0.0f, 1.0f - 1.0f); GL.Vertex3(20, 20, 0);
    //Bottom
    GL.BindTexture(TextureTarget.Texture2D, BottomTexture);
    GL.TexCoord2(0.0f, 1.0f - 0.0f); GL.Vertex3(0, 0, 0);
    GL.TexCoord2(1.0f, 1.0f - 0.0f); GL.Vertex3(0, 0, -20);
    GL.TexCoord2(1.0f, 1.0f - 1.0f); GL.Vertex3(20, 0, -20);
    GL.TexCoord2(0.0f, 1.0f - 1.0f); GL.Vertex3(20, 0, 0);
    GL.BindTexture(TextureTarget.Texture2D, SideTexture);
    GL.TexCoord2(0.0f, 1.0f - 0.0f); GL.Vertex3(0, 0, -20);
    GL.TexCoord2(1.0f, 1.0f - 0.0f); GL.Vertex3(0, 0, 0);
    GL.TexCoord2(1.0f, 1.0f - 1.0f); GL.Vertex3(0, 20, 0);
    GL.TexCoord2(0.0f, 1.0f - 1.0f); GL.Vertex3(0, 20, -20);

    GL.TexCoord2(0.0f, 1.0f - 0.0f); GL.Vertex3(0, 20, 0);
    GL.TexCoord2(1.0f, 1.0f - 0.0f); GL.Vertex3(20, 20, 0);
    GL.TexCoord2(1.0f, 1.0f - 1.0f); GL.Vertex3(20, 20, -20);
    GL.TexCoord2(0.0f, 1.0f - 1.0f); GL.Vertex3(0, 20, -20);

    GL.TexCoord2(0.0f, 1.0f - 0.0f); GL.Vertex3(20, 0, -20);
    GL.TexCoord2(1.0f, 1.0f - 0.0f); GL.Vertex3(0, 0, -20);
    GL.TexCoord2(1.0f, 1.0f - 1.0f); GL.Vertex3(0, 20, -20);
    GL.TexCoord2(0.0f, 1.0f - 1.0f); GL.Vertex3(20, 20, -20);

    GL.End();
    GL.PopMatrix();

return 6;   // Return number of faces drawn
}

As you may have guessed this function draws a cube with position x, y, z. Direction ori and SideTexture on the sides as well as TopTexture and BottomTexture on the top and bottom. Now the problem is that it draws the cube with only one texture! the side texture. I don't know what is the problem. Do I have to unbind the textures? everything else in the code works fine just as I said already there is this nuisance with the textures. Any help is appreciated.

هل كانت مفيدة؟

المحلول

You cannot call GL.BindTexture() within a begin-end region. From the documentation:

Only a subset of GL commands can be used between glBegin and glEnd. The commands are glVertex, glColor, glSecondaryColor, glIndex, glNormal, glFogCoord, glTexCoord, glMultiTexCoord, glVertexAttrib, glEvalCoord, glEvalPoint, glArrayElement, glMaterial, and glEdgeFlag. Also, it is acceptable to use glCallList or glCallLists to execute display lists that include only the preceding commands. If any other GL command is executed between glBegin and glEnd, the error flag is set and the command is ignored.

If you check GL.GetError() you will see that you are getting an InvalidOperation error. In fact GL.GetError() should be your first reaction when something does not render as expected in OpenGL.

The solution:

private int DrawCube(float x, float y, float z, float ori, int SideTexture, int TopTexture, int BottomTexture)
{
    GL.PushMatrix();

    GL.Translate(x, y, z);
    GL.Rotate(ori, 0, 1, 0);

    GL.BindTexture(TextureTarget.Texture2D, SideTexture);
    GL.Begin(BeginMode.Quads);
    GL.Color3(Color.White);
    GL.TexCoord2(0.0f, 1.0f - 0.0f); GL.Vertex3(0, 0, 0);
    GL.TexCoord2(1.0f, 1.0f - 0.0f); GL.Vertex3(20, 0, 0);
    GL.TexCoord2(1.0f, 1.0f - 1.0f); GL.Vertex3(20, 20, 0);
    GL.TexCoord2(0.0f, 1.0f - 1.0f); GL.Vertex3(0, 20, 0);
    GL.End();

    //Top
    GL.BindTexture(TextureTarget.Texture2D, TopTexture);
    GL.Begin(BeginMode.Quads);
    GL.TexCoord2(0.0f, 1.0f - 0.0f); GL.Vertex3(20, 0, 0);
    GL.TexCoord2(1.0f, 1.0f - 0.0f); GL.Vertex3(20, 0, -20);
    GL.TexCoord2(1.0f, 1.0f - 1.0f); GL.Vertex3(20, 20, -20);
    GL.TexCoord2(0.0f, 1.0f - 1.0f); GL.Vertex3(20, 20, 0);
    GL.End();

    //Bottom
    GL.BindTexture(TextureTarget.Texture2D, BottomTexture);
    GL.Begin(BeginMode.Quads);
    GL.TexCoord2(0.0f, 1.0f - 0.0f); GL.Vertex3(0, 0, 0);
    GL.TexCoord2(1.0f, 1.0f - 0.0f); GL.Vertex3(0, 0, -20);
    GL.TexCoord2(1.0f, 1.0f - 1.0f); GL.Vertex3(20, 0, -20);
    GL.TexCoord2(0.0f, 1.0f - 1.0f); GL.Vertex3(20, 0, 0);
    GL.End();

    GL.BindTexture(TextureTarget.Texture2D, SideTexture);
    GL.Begin(BeginMode.Quads);
    GL.TexCoord2(0.0f, 1.0f - 0.0f); GL.Vertex3(0, 0, -20);
    GL.TexCoord2(1.0f, 1.0f - 0.0f); GL.Vertex3(0, 0, 0);
    GL.TexCoord2(1.0f, 1.0f - 1.0f); GL.Vertex3(0, 20, 0);
    GL.TexCoord2(0.0f, 1.0f - 1.0f); GL.Vertex3(0, 20, -20);

    GL.TexCoord2(0.0f, 1.0f - 0.0f); GL.Vertex3(0, 20, 0);
    GL.TexCoord2(1.0f, 1.0f - 0.0f); GL.Vertex3(20, 20, 0);
    GL.TexCoord2(1.0f, 1.0f - 1.0f); GL.Vertex3(20, 20, -20);
    GL.TexCoord2(0.0f, 1.0f - 1.0f); GL.Vertex3(0, 20, -20);

    GL.TexCoord2(0.0f, 1.0f - 0.0f); GL.Vertex3(20, 0, -20);
    GL.TexCoord2(1.0f, 1.0f - 0.0f); GL.Vertex3(0, 0, -20);
    GL.TexCoord2(1.0f, 1.0f - 1.0f); GL.Vertex3(0, 20, -20);
    GL.TexCoord2(0.0f, 1.0f - 1.0f); GL.Vertex3(20, 20, -20);
    GL.End();

    GL.PopMatrix();

    return 6;   // Return number of faces drawn
}

نصائح أخرى

Oh yes an for those for who this might be helpful I actually used the wrong sides with the textures. The topTexture was really attached to the bottom, e.t.c. Here is the working code. The code to upload a texture from a path:

static public int UploadTexture(string pathname)
{
    // Create a new OpenGL texture object
    int id = GL.GenTexture();

    // Select the new texture
    GL.BindTexture(TextureTarget.Texture2D, id);

    // Load the image
    Bitmap bmp = new Bitmap(pathname);

    // Lock image data to allow direct access
    BitmapData bmp_data = bmp.LockBits(
            new Rectangle(0, 0, bmp.Width, bmp.Height),
            System.Drawing.Imaging.ImageLockMode.ReadOnly,
            System.Drawing.Imaging.PixelFormat.Format32bppArgb);

    // Import the image data into the OpenGL texture
    GL.TexImage2D(TextureTarget.Texture2D,
                  0,
                  PixelInternalFormat.Rgba,
                  bmp_data.Width,
                  bmp_data.Height,
                  0,
                  OpenTK.Graphics.OpenGL.PixelFormat.Bgra,
                  OpenTK.Graphics.OpenGL.PixelType.UnsignedByte,
                  bmp_data.Scan0);

    // Unlock the image data
    bmp.UnlockBits(bmp_data);

    // Configure minification and magnification filters
    GL.TexParameter(TextureTarget.Texture2D,
            TextureParameterName.TextureMinFilter,
            (int)TextureMinFilter.Linear);
    GL.TexParameter(TextureTarget.Texture2D,
            TextureParameterName.TextureMagFilter,
            (int)TextureMagFilter.Linear);

    // Return the OpenGL object ID for use
    return id;
}

and the code to draw the cube with the textures

private int DrawCube(float x, float y, float z, float ori, int TopTexture, int BottomTexture, params int[] SideTextures)
        {
            GL.PushMatrix();

            GL.Translate(x, y, z);
            GL.Rotate(ori, 0, 1, 0);

            GL.BindTexture(TextureTarget.Texture2D, SideTextures[0]);
            GL.Begin(BeginMode.Quads);
            GL.Color3(Color.White);
            GL.TexCoord2(0.0f, 1.0f - 0.0f); GL.Vertex3(0, 0, 0);
            GL.TexCoord2(1.0f, 1.0f - 0.0f); GL.Vertex3(20, 0, 0);
            GL.TexCoord2(1.0f, 1.0f - 1.0f); GL.Vertex3(20, 20, 0);
            GL.TexCoord2(0.0f, 1.0f - 1.0f); GL.Vertex3(0, 20, 0);
            GL.End();

            //Top
            GL.BindTexture(TextureTarget.Texture2D, SideTextures[1]);
            GL.Begin(BeginMode.Quads);
            GL.TexCoord2(0.0f, 1.0f - 0.0f); GL.Vertex3(20, 0, 0);
            GL.TexCoord2(1.0f, 1.0f - 0.0f); GL.Vertex3(20, 0, -20);
            GL.TexCoord2(1.0f, 1.0f - 1.0f); GL.Vertex3(20, 20, -20);
            GL.TexCoord2(0.0f, 1.0f - 1.0f); GL.Vertex3(20, 20, 0);
            GL.End();

            //Bottom
            GL.BindTexture(TextureTarget.Texture2D, BottomTexture);
            GL.Begin(BeginMode.Quads);
            GL.TexCoord2(0.0f, 1.0f - 0.0f); GL.Vertex3(0, 0, 0);
            GL.TexCoord2(1.0f, 1.0f - 0.0f); GL.Vertex3(0, 0, -20);
            GL.TexCoord2(1.0f, 1.0f - 1.0f); GL.Vertex3(20, 0, -20);
            GL.TexCoord2(0.0f, 1.0f - 1.0f); GL.Vertex3(20, 0, 0);
            GL.End();

            GL.BindTexture(TextureTarget.Texture2D, SideTextures[2]);
            GL.Begin(BeginMode.Quads);
            GL.TexCoord2(0.0f, 1.0f - 0.0f); GL.Vertex3(0, 0, -20);
            GL.TexCoord2(1.0f, 1.0f - 0.0f); GL.Vertex3(0, 0, 0);
            GL.TexCoord2(1.0f, 1.0f - 1.0f); GL.Vertex3(0, 20, 0);
            GL.TexCoord2(0.0f, 1.0f - 1.0f); GL.Vertex3(0, 20, -20);
            GL.End();
            GL.BindTexture(TextureTarget.Texture2D, TopTexture);
            GL.Begin(BeginMode.Quads);
            GL.TexCoord2(0.0f, 1.0f - 0.0f); GL.Vertex3(0, 20, 0);
            GL.TexCoord2(1.0f, 1.0f - 0.0f); GL.Vertex3(20, 20, 0);
            GL.TexCoord2(1.0f, 1.0f - 1.0f); GL.Vertex3(20, 20, -20);
            GL.TexCoord2(0.0f, 1.0f - 1.0f); GL.Vertex3(0, 20, -20);
            GL.End();
            GL.BindTexture(TextureTarget.Texture2D, SideTextures[3]);
            GL.Begin(BeginMode.Quads);
            GL.TexCoord2(0.0f, 1.0f - 0.0f); GL.Vertex3(20, 0, -20);
            GL.TexCoord2(1.0f, 1.0f - 0.0f); GL.Vertex3(0, 0, -20);
            GL.TexCoord2(1.0f, 1.0f - 1.0f); GL.Vertex3(0, 20, -20);
            GL.TexCoord2(0.0f, 1.0f - 1.0f); GL.Vertex3(20, 20, -20);
            GL.End();

            GL.PopMatrix();

            return 6;   // Return number of faces drawn
        }
        protected override void OnResize(EventArgs e)
        {
            int w = Width;
            int h = Height;
            float aspect = 1;

            // Calculate aspect ratio, checking for divide by zero
            if (h > 0)
            {
                aspect = (float)w / (float)h;
            }

            // Initialise the projection view matrix
            GL.MatrixMode(MatrixMode.Projection);
            GL.LoadIdentity();

            // Setup a perspective view
            float FOVradians = MathHelper.DegreesToRadians(45);
            Matrix4 perspective = Matrix4.CreatePerspectiveFieldOfView(FOVradians, aspect, 1, 4000);
            GL.MultMatrix(ref perspective);

            // Set the viewport to the whole window
            GL.Viewport(0, 0, w, h);
        }

and the refrences you will have to use:

using System;
using System.Drawing;
using System.Windows.Forms;
using OpenTK;
using OpenTK.Graphics.OpenGL;

EDIT: In the newer version of OpenTK I believe you will have to use PrimitiveType.Quad instead of BeginMode.Quad

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top