Basic OpenGL Model loading

Started by
4 comments, last by Irlan Robson 9 years, 3 months ago

Hello i am a real beginner so please dont blame me for my question probably it sounds very stupid.

Basically i am traing do display Unreal Engine Model.

The structure of the Model is with several surfices.Each surfice have own Vertex normals indexes and UVs.

And here is the code itself



        private void openGLControl1_OpenGLInitialized(object sender, EventArgs e)
        {
          SharpGL.OpenGL gl = this.openGLControl1.OpenGL;
            gl.Enable(OpenGL.GL_DEPTH_TEST);
            gl.ShadeModel(OpenGL.GL_SMOOTH);
            gl.Hint(OpenGL.GL_PERSPECTIVE_CORRECTION_HINT, OpenGL.GL_NICEST);
          
          
        }
 private void DrawMesh2()
        {
            SharpGL.OpenGL gl = this.openGLControl1.OpenGL;
            gl.Clear(OpenGL.GL_COLOR_BUFFER_BIT | OpenGL.GL_DEPTH_BUFFER_BIT);
            gl.Color(1.0f, 1.0f, 1.0f);
            gl.LoadIdentity();
            gl.LookAt(50, 50, 50, 0, 0.5f, 0, 0, 1, 0);
            gl.Rotate(0, rotation++, rotation / 2);


            for (int i = 0; i < m_Model.Surfices.Count; i++)
            {
                int k = 0;
                gl.BindTexture(OpenGL.GL_TEXTURE_2D, textures[i]);
                gl.Enable(OpenGL.GL_TEXTURE_2D);
                gl.Begin(OpenGL.GL_TRIANGLES);
                for (int j = 0; j < m_Model.Surfices[i].triangle_count; j++) {
                    gl.Normal(m_Model.Surfices[i].Verteces[k].Normal.ToArray());
                    gl.TexCoord(m_Model.Surfices[i].TextureCords[k].UV.ToArray()); 
                    gl.Vertex(m_Model.Surfices[i].Verteces[k].Location.ToArray());

                    gl.Normal(m_Model.Surfices[i].Verteces[k+1].Normal.ToArray());
                    gl.TexCoord(m_Model.Surfices[i].TextureCords[k+1].UV.ToArray()); 
                    gl.Vertex(m_Model.Surfices[i].Verteces[k+1].Location.ToArray());

                    gl.Normal(m_Model.Surfices[i].Verteces[k+2].Normal.ToArray());
                    gl.TexCoord(m_Model.Surfices[i].TextureCords[k+2].UV.ToArray()); 
                    gl.Vertex(m_Model.Surfices[i].Verteces[k+2].Location.ToArray());
                    k += 3;
                }
                gl.End();
                gl.BindTexture(OpenGL.GL_TEXTURE_2D, 0);
                gl.Disable(OpenGL.GL_TEXTURE_2D);
                
            }
            gl.End();
            gl.Flush();
        }

The result looks like this:

4n6Dfr.png

But should look like

rQLUjZ.png

So my guess is that the texture of the first or last Surfice is used

I will strongly appreciate any help or directions what may be wrong

Advertisement

The problem is or with the UV coordinates or the texture that you've loaded. All vertex positions looks correcty.

Are you sure that all the UV coordinates were loaded correctly?

A Unreal Engine Model uses LHS or RHS coordinate system?

Since you're starter I'd say that you may look at the OpenGL Shader Language.

Hey thanks for the replay.

UV coordinates are just fine Somthing is wrong with texture binding

What i done was something actually stupid (right now i even dont know how i come to that idea.. )

moved Texture bind outside the for look so the drowing code looks like this


private void DrawMeshBasic()
        {
            SharpGL.OpenGL gl = this.openGLControl1.OpenGL;
            gl.Clear(OpenGL.GL_COLOR_BUFFER_BIT | OpenGL.GL_DEPTH_BUFFER_BIT);
            gl.Color(1.0f, 1.0f, 1.0f);
            gl.LoadIdentity();
            gl.LookAt(50, 50, 50, 0, 0.5f, 0, 0, 1, 0);
            gl.Rotate(0, rotation++, rotation / 2);

            for(int i=0;i<textures.Length;i++){
                gl.BindTexture(OpenGL.GL_TEXTURE_2D, textures[i]);
            }
            gl.Enable(OpenGL.GL_TEXTURE_2D);
            for (int i = 0; i < m_Model.Surfices.Count; i++)
            {
                int k = 0;
                gl.Begin(OpenGL.GL_TRIANGLES);
                for (int j = 0; j < m_Model.Surfices[i].triangle_count; j++) {
                    gl.Normal(m_Model.Surfices[i].Verteces[k].Normal.ToArray());
                    gl.TexCoord(m_Model.Surfices[i].TextureCords[k].UV.ToArray()); 
                    gl.Vertex(m_Model.Surfices[i].Verteces[k].Location.ToArray());

                    gl.Normal(m_Model.Surfices[i].Verteces[k+1].Normal.ToArray());
                    gl.TexCoord(m_Model.Surfices[i].TextureCords[k+1].UV.ToArray()); 
                    gl.Vertex(m_Model.Surfices[i].Verteces[k+1].Location.ToArray());

                    gl.Normal(m_Model.Surfices[i].Verteces[k+2].Normal.ToArray());
                    gl.TexCoord(m_Model.Surfices[i].TextureCords[k+2].UV.ToArray()); 
                    gl.Vertex(m_Model.Surfices[i].Verteces[k+2].Location.ToArray());
                    k += 3;
                }
                gl.End();
                
            }
            gl.Flush();
        }

The result from that is

7xafFk.png

From that i know that in previous case only the last texture was used.

After that i ty to load each texture manually to see is there is a problem with UV

ll9FwV.png

So the UV are fine

seams I bind the textures incorrectly in that piece of code


 private void InitTextures() {
            SharpGL.OpenGL gl = this.openGLControl1.OpenGL;
            gl_Textures = new Texture2D[m_Model.Surfices.Count];
            textures = new uint[m_Model.Surfices.Count];
            List<Material> materials = m_Model.GetMaterials();
            gl.GenTextures(3, textures);
            for (int i = 0; i < m_Model.Surfices.Count; i++)
            {
                UTexture obj = (UTexture)pm.FindObject(materials[i].Texture);
                obj.Decompile();
                Bitmap image = LibSquish.GetImage((UTexture)obj);
                gl.GenTextures(3, textures);	
                BitmapData bitmapData = image.LockBits(new Rectangle(0, 0, image.Width, image.Height),
               ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);

                gl.BindTexture(OpenGL.GL_TEXTURE_2D, textures[i]);
                //  Set the image data.
                gl.TexImage2D(OpenGL.GL_TEXTURE_2D, 0, (int)OpenGL.GL_RGBA,
                    (int)image.Width, image.Height, 0, OpenGL.GL_BGRA, OpenGL.GL_UNSIGNED_BYTE,
                    bitmapData.Scan0);
                gl.TexParameter(OpenGL.GL_TEXTURE_2D, OpenGL.GL_TEXTURE_MIN_FILTER, OpenGL.GL_LINEAR);
                gl.TexParameter(OpenGL.GL_TEXTURE_2D, OpenGL.GL_TEXTURE_MAG_FILTER, OpenGL.GL_LINEAR);
                //  Unlock the image.
                image.UnlockBits(bitmapData);
            }
        }

You're welcome.

OpenGL is a state machine. You're binding only the last texture in the texture array in the first example. In your case you're forcing that each surface has a texture.

Try this way:

For each drawable part of the mesh...

Set one texture;

Draw the vertex data in that part;

Repeat process for the mesh;

Looks like you're in trouble with the model format. Try to get the separation between mesh, drawable mesh part, and model to see if you can get more concise results.


gl.GenTextures(3, textures);

Are you forcing that you will only have 3 textures. If each surface has a texture, call gl.GenTextures(m_Model.Surfices.Count, textures) (but you're creating textures more than once).

Each surface has a texture in your case?

Yes sry in that case are 3 surfaces each have 1 texture


gl.GenTextures(3, textures);
for (int i = 0; i < m_Model.Surfices.Count; i++)
{
UTexture obj = (UTexture)pm.FindObject(materials.Texture);
obj.Decompile();
Bitmap image = LibSquish.GetImage((UTexture)obj);
gl.GenTextures(3, textures);

You're generating 3 textures more than once assigning it to the same texture array pointer.

This is the life cycle of an texture:

Generate once;

Enable texture the type;

Bind/Unbind;

Destroy it;

If each surface has 3 textures, you should assign 3 textures to each surface. But doing in this way, shared textures will be loaded multiple times, which is horrible for the graphics card video memory.

Try change to that:


//Initialization:

private void InitTextures() {
            SharpGL.OpenGL gl = this.openGLControl1.OpenGL;
            gl_Textures = new Texture2D[m_Model.Surfices.Count]; //Don't know what is this.
            textures = new uint[m_Model.Surfices.Count];
            gl.GenTextures(m_Model.Surfices.Count, textures); //Here.
            List<Material> materials = m_Model.GetMaterials();
            for (int i = 0; i < m_Model.Surfices.Count; i++)
            {
                BitmapData bitmapData = image.LockBits(new Rectangle(0, 0, image.Width, image.Height),
               ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);

                gl.BindTexture(OpenGL.GL_TEXTURE_2D, textures[i]);
                //  Set the image data.
                gl.TexImage2D(OpenGL.GL_TEXTURE_2D, 0, (int)OpenGL.GL_RGBA,
                    (int)image.Width, image.Height, 0, OpenGL.GL_BGRA, OpenGL.GL_UNSIGNED_BYTE,
                    bitmapData.Scan0);
                gl.TexParameter(OpenGL.GL_TEXTURE_2D, OpenGL.GL_TEXTURE_MIN_FILTER, OpenGL.GL_LINEAR);
                gl.TexParameter(OpenGL.GL_TEXTURE_2D, OpenGL.GL_TEXTURE_MAG_FILTER, OpenGL.GL_LINEAR);
                //  Unlock the image.
                image.UnlockBits(bitmapData);
                
                gl.BindTexture(OpenGL.GL_TEXTURE_2D, 0); //Just to make sure.
            }
        }

//Drawing code:

private void DrawMeshBasic()
        {
            SharpGL.OpenGL gl = this.openGLControl1.OpenGL;
            gl.Clear(OpenGL.GL_COLOR_BUFFER_BIT | OpenGL.GL_DEPTH_BUFFER_BIT);
            gl.LoadIdentity();
            gl.LookAt(50.0f, 50.0f, 50.0f, 0.0f, 0.5f, 0, 0, 1, 0);
            gl.Rotate(0, rotation++, rotation / 2);

            for (int i = 0; i < m_Model.Surfices.Count; i++)
            {
                int k = 0;
                
                gl.Enable(OpenGL.GL_TEXTURE_2D);
                gl.BindTexture(OpenGL.GL_TEXTURE_2D, textures[i]);

                gl.Begin(OpenGL.GL_TRIANGLES);

                for (int j = 0; j < m_Model.Surfices[i].triangle_count; j++) {
                    gl.Normal(m_Model.Surfices[i].Verteces[k].Normal.ToArray());
                    gl.TexCoord(m_Model.Surfices[i].TextureCords[k].UV.ToArray()); 
                    gl.Vertex(m_Model.Surfices[i].Verteces[k].Location.ToArray());

                    gl.Normal(m_Model.Surfices[i].Verteces[k+1].Normal.ToArray());
                    gl.TexCoord(m_Model.Surfices[i].TextureCords[k+1].UV.ToArray()); 
                    gl.Vertex(m_Model.Surfices[i].Verteces[k+1].Location.ToArray());

                    gl.Normal(m_Model.Surfices[i].Verteces[k+2].Normal.ToArray());
                    gl.TexCoord(m_Model.Surfices[i].TextureCords[k+2].UV.ToArray()); 
                    gl.Vertex(m_Model.Surfices[i].Verteces[k+2].Location.ToArray());
                    
                    k += 3;
                }

                gl.End();

                gl.BindTexture(OpenGL.GL_TEXTURE_2D, 0); //Just to make sure.
                gl.Disable(OpenGL.GL_TEXTURE_2D); //Just to make sure.
                
            }
            gl.Flush();
        }

This topic is closed to new replies.

Advertisement