Dealing with OBJ vetices formats

Member
Posts: 312
Joined: 2006.10
Post: #16
Why would it matter that I store the OBJ indices in an array starting at the first element?
Quote this message in a reply
Moderator
Posts: 3,579
Joined: 2003.06
Post: #17
??? You *should* be storing the OBJ indices in an array starting at the first element.

But *what* are you storing? If the file says 1 for the first element of an array, and you try to access the first element of an array with 1, like verts[1], you will be accessing the *second* element, not the first as you intended. Obj indices start with 1, not 0! (there, that's THREE posts I've said that now) C/C++ start with 0, not 1, last time I checked...
Quote this message in a reply
Member
Posts: 312
Joined: 2006.10
Post: #18
I understand that. I'm not trying to access the 1st element of an C++ array with one. Basically, I use scanf to load all the vertices, vertex one goes into element zero of the array/vector, vertex two goes into element 1 or the array/vector, ect... Same goes for the Faces and their indices, except each face has their own array of indices of either three or four elements (depending if it's a tri or quad).

Then, to access the first vertex of the vertices I *could* access it like this
Code:
mVertices[0];

Aren't I correct in doing this, or am I doing something blantly wrong?
Quote this message in a reply
Moderator
Posts: 3,579
Joined: 2003.06
Post: #19
That's all correct, except for ONE crucial fact: Obj indices start with 1 and not 0! (four times)

We'll connect on this, I promise.Wink

When you load a face line, it looks something like this: f 1/2/3 2/3/4 etc... That `1' means to access the first element of your array. You loaded that line directly into your VertIndices as `1'. `1' is the number that you loaded, and the number you loaded was `1'. Not 0, 2, 3, 4, 5, or 6, but 1. 1 is *not* the first element of your vertex array (in memory) -- 0 is.

[edit] this: f 1/2/3 2/3/4 should be this: f 0/1/2 1/2/3 but it's not, so you need to make that adjustment after you load it so that those obj indices synch up with what you actually have in memory [/edit]
Quote this message in a reply
Member
Posts: 312
Joined: 2006.10
Post: #20
OHHHH, I understand you now! Let me try subtracting one from each of my indices! Then I'll report back Rasp

Heh, it works now! Thanks a lot. I knew I wasn't getting something Rasp
Quote this message in a reply
Moderator
Posts: 3,579
Joined: 2003.06
Post: #21
Right on! Grin
Quote this message in a reply
Moderator
Posts: 771
Joined: 2003.04
Post: #22
AnotherJake Wrote:`1' is the number that you loaded, and the number you loaded was `1'.

Awesome! LOL
Quote this message in a reply
Moderator
Posts: 3,579
Joined: 2003.06
Post: #23
Hehe... Thanks. A little Monte Python moment there.Cool

BTW, I started working with GLU tessellation last night. I haven't quite gotten to the results yet, but so far it appears to be surprisingly nice to work with. I wish I had known about it when I had written n>4-sided polygon loaders before. It looks like I'll be able to get the raw post-tessellation data from GLU on the spot during load. All the examples I had read previously gave me the impression that you'd need to call OGL routines for the callbacks and wrap all that in display lists to make any use of it, but after studying a little closer I realized that I can simply construct my data during the callbacks and not involve OGL at all. I don't know if that makes *any* sense to anyone, but it's pretty cool to me if it works as I suspect it will. And it seems pretty darn fast so far to!
Quote this message in a reply
Moderator
Posts: 3,579
Joined: 2003.06
Post: #24
Just a follow-up to my GLU tessellation experiment: It works!

I had to read the tessellators section in the Red Book probably four times before I could wrap my mind around it, but after that it was pretty easy. Here are a few thoughts on it:

You do not need to call OpenGL or be drawing at all to use the GLU tessellation functions. The Red Book examples make it seem like you do. In fact, to *really* make it seem like you do, under `Tessellation Performance Tips' on page 484 of the version 1.2 book it suggests that you cache the output of the tessellator in a display list or other user structure. What would be `other user structure'? I don't know. But what *really* threw me off was that the very next sentence suggests that if you want the post-tessellation vertex coordinates you can tessellate your polygons while in feedback mode. Why someone would want to do that, I don't know either.

What I did is, instead of calling OpenGL drawing functions during the tessellator callbacks, I simply took the data myself and put it into my geometry arrays for later use with glDrawElements. The only minor issue is that the GLU tessellator will send back triangle fans and strips where it thinks they'd be appropriate, and I just want triangles, so I had to break up the strips and fans on the fly as they were fed to me from GLU. I wish GLU had a setting to turn off strips and fans. I do this is all during loading. If I don't do duplicate vertex removal, it's actually surprisingly fast, and provides excellent results from the testing I've done so far.

So the bottom line is that using the GLU tessellator works great, and it really isn't very hard to use at all. It was just a little tricky to figure out at first because I wasn't able to find any examples out there that did what I wanted -- they all tessellated into display lists, and I wanted the raw tessellated geometry back.
Quote this message in a reply
Member
Posts: 312
Joined: 2006.10
Post: #25
Glad you got that working, I may have to use it! Rasp

Instead of using immediate mode, I tried organizing it into an array, and triangles work fine (and I can confirm the triangles are correct this time Rasp), but quads are really messed up... It's pretty much the same as the drawing was before, anything look wrong?

Code:
void CModelOBJ::CreateVertArrays()
{
    int k = 0;
    
    if( type == GL_QUADS ) mVerticeArray = new CVector3D[mTotalFaces*4];
    else mVerticeArray = new CVector3D[mTotalFaces*3];
        
    if( HasTextureCoords && type == GL_QUADS ) mTextureArray = new CTexCoord[mTotalFaces*4];
    else if( HasTextureCoords && type == GL_TRIANGLES ) mTextureArray = new CTexCoord[mTotalFaces*3];
    
    if( HasNormals && type == GL_QUADS ) mNormalArray = new CVector3D[mTotalFaces*4];
    else if( HasNormals && type == GL_TRIANGLES ) mNormalArray = new CVector3D[mTotalFaces*3];
    
    
    
    for( int i = 0; i < mTotalFaces; i++)
    {
        CVector3D vTemp;
        CVector3D vNormal;
        CTexCoord vTexture;
        CPoly face = mFaces.at(i);

        for( int j = 0; j < face.NumVerts; j++ )
        {
            vTemp = mVertices[face.VertIndices[j]];
            mVerticeArray[k] = vTemp;
            
            if( HasTextureCoords )
            {
                vTexture = mTexCoords[face.TexIndices[j]];
                mTextureArray[k] = vTexture;
            }
            
            if( HasNormals )
            {
                vNormal = mNormals[face.NormalIndices[j]];
                mNormalArray[k] = vNormal;
            }
    
            printf( "(%f, %f, %f)\n", mVerticeArray[k].x, mVerticeArray[k].y, mVerticeArray[k].z );
            k++;
        }
    }
}

And the drawing
Code:
void CModelOBJ::Render()
{
    // IMPLEMENT TEXTURING
    if( HasTextureCoords )
    {
        glEnableClientState(GL_TEXTURE_COORD_ARRAY);
        glTexCoordPointer(2, GL_FLOAT, 0, mTextureArray);
    }
    
    if( HasNormals )
    {
        glEnableClientState(GL_NORMAL_ARRAY);
        glNormalPointer(GL_FLOAT, 0, mNormalArray);
    }
    
    if( type == GL_TRIANGLES )
    {
        glEnableClientState(GL_VERTEX_ARRAY);
        glVertexPointer(3, GL_FLOAT, 0, mVerticeArray);
        glDrawArrays(GL_TRIANGLES, 0, mTotalFaces*3 );
    }
    else if( type == GL_QUADS )
    {
        glEnableClientState(GL_VERTEX_ARRAY);
        glVertexPointer(4, GL_FLOAT, 0, mVerticeArray);
        glDrawArrays(GL_QUADS, 0, mTotalFaces*4 );
    }
      
}

var "type" is being set correctly also.

Edit - Is it worth using vertex arrays, or is glBegin fast enough (usually)?
Quote this message in a reply
Moderator
Posts: 3,579
Joined: 2003.06
Post: #26
I don't see anything that sticks out, but I'm pretty brain-fried right now...

As far as using vertex arrays, yeah, it's almost always worth going that direction if possible. You get a major benefit by sending data in batches to the renderer with arrays instead of incurring the extra overhead of repeated function calls between glBegin and glEnd to get the job done. Pretty much the only time I use glBegin/end is for sprites on quads. Plus, using arrays opens up the possibility of using VBOs for caching vertex data on the video hardware for a really big boost on basically anything other than a GMA950, which does vertex processing on the cpu.
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #27
VBOs are also the fast path for the GMA 950 (they allow the OpenGL MP Engine to help, if nothing else).
Quote this message in a reply
Moderator
Posts: 3,579
Joined: 2003.06
Post: #28
Yeah, as I've heard, VBOs are still the recommended path on the GMA950 too, but there's really no benefit right now that I've seen yet -- not that there won't be in the future though, and I haven't played with MP yet...
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #29
You say there's no benefit, but have you tried enabling the MP engine?

I wouldn't expect you to see much, if anything, if you haven't.
Quote this message in a reply
Moderator
Posts: 3,579
Joined: 2003.06
Post: #30
OneSadCookie Wrote:You say there's no benefit, but have you tried enabling the MP engine?
No I haven't.
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  Music formats that loop without gaps? MattDiamond 15 8,106 Oct 26, 2004 07:01 AM
Last Post: aarku
  (BSD Sockets) Dealing with Multiple Connections Zenith 12 7,397 Aug 29, 2003 10:00 AM
Last Post: Zenith