Jump to content
  • Advertisement
Sign in to follow this  
devINVISIBLE

OpenGL Every other triangle is backwards

This topic is 4345 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I am switching over from a c++/opengl background to C#/DirectX. I've been transfering some old logic over -- namely an .obj loader. I realize that DX uses a left hand coordinate system as opposed to opengl's right hand coordinate system, however I am getting a weird outcome. For similar code (albeit much cleaner in C#) it seems that every other triangle for my model (a chest) is rendering backwards. I've wrote a small little demo so I could fool around and try and analyze what my problem is. I've made a screencast where I slowly rotate the chest around, play with the culling settings, and even step through the object being rendered triangle by triangle. It's less than a minute long but I believe it gets the point across. http://junk.invisiware.com/ModelLoadingBug.rar (of a 1 minute .mov) I won't go into details about the .obj being actually loaded, however I do have my classes setup fairly abstracted. I have three arrays for the vertices, normals, and texCoords. Then I have an array of faces (each face is has an index into a vertex, normal, and texCoord for each point). I also handle groups of faces. Here is snippit of my render loop. (bare in mind this is just to test my bug)
public void Render( Device device, int frameCount )
    {
      for ( int i = 0; i < _groups.Count; i++ )
      {
        _groups[ i ].material.Bind();
        if ( _groups[ i ].active == true )
        {
          CustomVertex.PositionNormalTextured[ ] vertices = new CustomVertex.PositionNormalTextured[ _groups[ i ].faces.Count * 3 ];
          for ( int j = 0; j < _groups[ i ].faces.Count && j < frameCount; j++ )
          {
            // TODO: Move the - 1 subtraction to the _load function, so it's only done once
            vertices[ ( j * 3 ) + 0 ].Position = _vertices[ _groups[ i ].faces[ j ].vIndex[ 0 ] - 1 ];
            vertices[ ( j * 3 ) + 1 ].Position = _vertices[ _groups[ i ].faces[ j ].vIndex[ 1 ] - 1 ];
            vertices[ ( j * 3 ) + 2 ].Position = _vertices[ _groups[ i ].faces[ j ].vIndex[ 2 ] - 1 ];
            
            if ( _hasNormals )
            {
              vertices[ ( j * 3 ) + 0 ].Normal = _normals[ _groups[ i ].faces[ j ].vnIndex[ 0 ] - 1 ];
              vertices[ ( j * 3 ) + 1 ].Normal = _normals[ _groups[ i ].faces[ j ].vnIndex[ 1 ] - 1 ];
              vertices[ ( j * 3 ) + 2 ].Normal = _normals[ _groups[ i ].faces[ j ].vnIndex[ 2 ] - 1 ];
            }

            if ( _hasTexCoords )
            {
              vertices[ ( j * 3 ) + 0 ].Tu = _texCoords[ _groups[ i ].faces[ j ].vtIndex[ 0 ] - 1 ].X;
              vertices[ ( j * 3 ) + 0 ].Tv = _texCoords[ _groups[ i ].faces[ j ].vtIndex[ 0 ] - 1 ].Y;
              vertices[ ( j * 3 ) + 1 ].Tu = _texCoords[ _groups[ i ].faces[ j ].vtIndex[ 1 ] - 1 ].X;
              vertices[ ( j * 3 ) + 1 ].Tv = _texCoords[ _groups[ i ].faces[ j ].vtIndex[ 1 ] - 1 ].Y;
              vertices[ ( j * 3 ) + 2 ].Tu = _texCoords[ _groups[ i ].faces[ j ].vtIndex[ 2 ] - 1 ].X;
              vertices[ ( j * 3 ) + 2 ].Tv = _texCoords[ _groups[ i ].faces[ j ].vtIndex[ 2 ] - 1 ].Y;
            }
          }
          device.VertexFormat = CustomVertex.PositionNormalTextured.Format;
          device.DrawUserPrimitives(PrimitiveType.TriangleList, _groups[ i ].faces.Count, vertices);
        }
      }
    }

Any help would be greatful, as I've been playing with it for few days now and not having any luck. [Edited by - devINVISIBLE on September 21, 2006 7:17:50 AM]

Share this post


Link to post
Share on other sites
Advertisement
Guest Anonymous Poster
directx has a order ther defines the surface of a triangle so if u have triangle ABC
a
*
**
***
****
*****B
C

if u define the triangle in ABC order it will be rendered corect but if the order is ACB the triangle will be opaside and form thei point of view it will not apper on the screen

you should switch the order of decraration something like
vertices[ ( j * 3 ) + 2 ].Position = _vertices[ _groups[ i ].faces[ j ].vIndex[ 0 ] - 1 ];
vertices[ ( j * 3 ) + 1 ].Position = _vertices[ _groups[ i ].faces[ j ].vIndex[ 1 ] - 1 ];
vertices[ ( j * 3 ) + 3 ].Position = _vertices[ _groups[ i ].faces[ j ].vIndex[ 2 ] - 1 ];

P.S. sorry for my englesh

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
vertices[ ( j * 3 ) + 2 ].Position = _vertices[ _groups[ i ].faces[ j ].vIndex[ 0 ] - 1 ];
vertices[ ( j * 3 ) + 1 ].Position = _vertices[ _groups[ i ].faces[ j ].vIndex[ 1 ] - 1 ];
vertices[ ( j * 3 ) + 0 ].Position = _vertices[ _groups[ i ].faces[ j ].vIndex[ 2 ] - 1 ];

Share this post


Link to post
Share on other sites

I can accomplish this outside of my render loop by simply changing the CullMode. This does flip the triangles around... however half of them are still facing the wrong way :) It just inverted ALL the faces. Is there a way of determining the direction the coords for the triangle is winding? I have a feeling like every other face is backwards for some reason :\ which doesn't make sense since it works fine in my opengl/c++ app. On a 2D plane it's simple to visually see which way is clockwide and counter-clockwise. I'm having trouble thinking how it would be done in a 3D plane, programatically. Any ideas?

Share this post


Link to post
Share on other sites
I think it's something like, if you have vertices of your triangle as v1, v2, v3, form of the two vectors a = v2-v1 and b = v3-v2, and then take the cross product a cross b. If that points towards you, then it's clockwise(?) and if it points away it's CCW. Of course you have to do this with transformed geometry. I might have those backwards, I usually think of the cross product in a right-handed coordinate system. Anyway it works in two dimensions of course (which is one of the reasons triangles are used, because they always lie in a plane) so you can figure it out in 2D.

Also, did you know that you can set up your projection matrices using a right-handed coordinate system? You might want to consider doing this, because XNA and (supposedly) future versions of Direct3D use/will use a right-handed coordinate system.

Share this post


Link to post
Share on other sites
I would agree that it sounds like the triangles are being expressed in strip order, but being drawn as a list. This is clearly not a chirality issue.

Share this post


Link to post
Share on other sites
In a guess that every other triangle was being rendered backwards, I simply flipped v1 and v3 for every other triangle. This didn't fix anything (laugh) but rules out that.

The .obj format is meant to be drawn as a list of triangles. The format "f v/vn/vt v/vn/vt v/vn/vt" corresponds to 3 seperate vertices, each specified by an index into the vertex array, index into the normals array, and vertex into the texture coordinates array. Just for kicks, I rendered it as a triangle strip and had no luck. :)

I tried changing the coord system to RH (perhaps I'm not doing it correctly) by using Matrix.PerspectiveFovRH and Matrix.LookAtRH instead of Matrix.PerspectiveFovLH and Matrix.LookAtLH. Is this all there is to that?

To keep things moving, I am going to be loading .x models for my project, but this bug has me stumped. I'm very interested in finding out what the problem is. Just out of interest (and the fact this bug stole a week from me :P) I'll reward anyone who can figure out what's going wrong. Thanks for everything so far.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!