Jump to content
  • Advertisement
Sign in to follow this  
trexmaster78

OpenGL Questions about rendering an object

This topic is 4162 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

Hello, I have several questions about rendering an object. Let me explain the situation first : - I load an object from an .obj file (yeah I know, not the best format around, but it's simple so I can practice on it) into 3 arrays : vertices, normals and texture coordinates - I want to use Opengl arrays to render the object on screen. It works (i.e. it renders the object correctly on the screen), but I'm quite not satisfied with the way I did it... - As I want the texture to be repeated on each face of the object (and if you not guessed what the object is and have not looked at the file, it's a stupid cube), I have 3 times more texture coordinates as I have vertices (in the file that is, in fact there are only 4 different tex coords). - The "way" I found to render my object, I duplicate each vertex each time it's drawn, and thus I end up with an array that's 3 times bigger that it should actually be, something like that : |v1|v2|v3|...|v6|v3|v4|...|v3|v8| with a corresponding texture coordinates array : |t1|t2|t3|...|t6|t3|t4|...|t3|t8| and I then send it to the gl*Pointer() functions and render with glDrawArrays(). So, while it does what I want (i.e render the textured object), I'm still a bit frustrated that the vertex array I send to OpenGL is 3 times bigger that it actually needs to. So here are my "questions " : a) Could this be done using indexed arrays ? I'd have to use two different indices arrays (one for vertices and one for tex coords) and switch between them while rendering. Wouldn't it be a bit too much of an overhead just for that ? And how could I do it (switching that is) ? b) Maybe I should compare the texture coordinates in the array to determine which ones are reduntant and rebuild the array so I end up with as many coordinates as I have vertices, and use indexed arrays for rendering ? c) Maybe I just suck at generating a UV map from an object in Blender and should go practice that ? d) Maybe Blender sucks at generating UV maps and I should use an other package ? e) Other options ? [EDIT] f) I saw in this thread that :
Quote:
Original post by hplus0603 Actually, splitting the vertices is necessary when they don't share the same normal or U/V information. It's as efficient as it can be. If you store separate arrays and separate indices, it'll actually take MORE space for any mesh of real complexity, than storing the single pre-split vertex array. Not to mention that's the way the hardware wants it. Also: the cube is pretty much the worst example, because each vertex splits into three. Most normal, more complex, meshes only get a split ratio of 10-30%.
Can someone confirm ? [/EDIT] Please help ! I'd like to understand that before moving on ... Thanks in advance, Trexmaster78 [Edited by - trexmaster78 on July 24, 2007 12:15:36 AM]

Share this post


Link to post
Share on other sites
Advertisement
you only get a 1-to-1 relationship between vertices and tex coords if you have a continuous map with continuous texture coordinates

If its a cube as you mentioned you probably did select the 6 sides seperately and assign vertex coords with this uvmapping plane

So you probably get some corners where uv(1,1) & uv(0,1) meet, just an example

I see no way you could change this except that you reassign your coordinates.

Thats just a guess, could you post the .obj file?

Share this post


Link to post
Share on other sites
Quote:
Original post by Basiror
Thats just a guess, could you post the .obj file?


Thanks for your answer. The obj file is linked in my first post (right where I say "I load and object from an .obj file").

Share this post


Link to post
Share on other sites
The problem is a bit of what is named a vertex. IMHO the better definition would be that a vertex is a structure build of
* point (location)
* normal
* color(s)
* n tex co-ordinates
* ...
where all but the location is optional. Whenever a single part of this structure differs from all other vertices of the mesh, it is a vertex that needs to be defined as its own in the vertex array. Indexing allows you to use such a vertex several times, but you have to use it entirely (as long as gfx APIs don't provide tuples for indexing).

So yes, you have to copy parts of vertices into other vertices, e.g. the location of a cube's corner into 3 (or more) vertices if e.g. their respective tex-coords differ.

EDIT: On the other hand, a common situation is that your mesh is smooth and uses a continuous UV mapping. Then it shows the same normal for all adjacent faces on a vertex and it shows the same te-coords. Hence indexing would be a great improvement. (An exception is when the API calculates the normals on-the-fly, of course, because you have not to define them one-by-one.)

Share this post


Link to post
Share on other sites
So, I finally managed to write a perl script that parses an .obj file, split the faces into triangles, build an array of indices for those triangles and build the ordered array of vertices.

Each vertex is of the form :
position.x|position.y|position.z|texture.u|texture.v|normal.x|normal.y|normal.z

I believe it's working correctly (but haven't tested the result yet), but I'd like you to take a look at it and see if you see any Big Mistake.

Here it is :

#!/usr/bin/perl
#-------------------------------------------------------------------------------------------
# Author : Me
# License : Whatever
#-------------------------------------------------------------------------------------------

$filename = $ARGV[0];

@file_data = `cat $filename`;

$vertexIndex = 0;

for ($i=0; $i<=$#file_data; $i++) {

$line = $file_data[$i];

if ($line =~ /^vt/) {
@tmp = split /\s+/, $line;
push (@texcoords, $tmp[1], $tmp[2]);
}

elsif ($line =~ /^vn/) {
@tmp = split /\s+/, $line;
push (@normals, $tmp[1], $tmp[2], $tmp[3]);
}

elsif ($line =~ /^v/) {
@tmp = split /\s+/, $line;
push (@vertices, $tmp[1], $tmp[2], $tmp[3]);
}

elsif ($line =~ /^f/) {
@tmp = split /\s+/, $line;

for ($j=1; $j<=$#tmp; $j++) {

@tmpVertex = split /\//, $tmp[$j];

$vIndex = ($tmpVertex[0]-1) * 3;
$tIndex = ($tmpVertex[1]-1) * 2;
$nIndex = ($tmpVertex[2]-1) * 3;

$vx = $vertices[$vIndex];
$vy = $vertices[$vIndex+1];
$vz = $vertices[$vIndex+2];

$tu = $texcoords[$tIndex];
$tv = $texcoords[$tIndex+1];

$nx = $normals[$nIndex];
$ny = $normals[$nIndex+1];
$nz = $normals[$nIndex+2];

if (!defined($vertexTab[0])) {

push (@vertexTab, $vx, $vy, $vz, $tu, $tv, $nx, $ny, $nz);
$vertexIndex = 0;
$indexToAdd = 0;

} else {

for ($k = 0; $k <= $vertexIndex; $k++) {

$index = $k * 8;

$tmpvx = $vertexTab[$index];
$tmpvy = $vertexTab[$index+1];
$tmpvz = $vertexTab[$index+2];

$tmptu = $vertexTab[$index+3];
$tmptv = $vertexTab[$index+4];

$tmpnx = $vertexTab[$index+5];
$tmpny = $vertexTab[$index+6];
$tmpnz = $vertexTab[$index+7];

if (($vx == $tmpvx) && ($vy == $tmpvy) && ($vz == $tmpvz)
&& ($tu == $tmptu) && ($tv == $tmptv)) {

$indexToAdd = $k;
$newVertex = 0;
last;

} else {

$newVertex = 1;

}


}

if ($newVertex) {

push (@vertexTab, $vx, $vy, $vz, $tu, $tv, $nx, $ny, $nz);
$vertexIndex++;
$indexToAdd = $vertexIndex;
}

}

if ($j <= 3) {

push (@indices, $indexToAdd);

} else {

push (@indices, $indices[$#indices-1], $indices[$#indices], $indexToAdd);

}

}

}

}

print "Indices : @indices\n";
$numVertices = ($#vertexTab+1) / 8;
print "Nb Vertices : $numVertices\n";

for ($i = 0; $i <= $#vertexTab; $i += 8) {

print "$vertexTab[$i] $vertexTab[$i+1] $vertexTab[$i+2] $vertexTab[$i+3] $vertexTab[$i+4] ";
print "$vertexTab[$i+5] $vertexTab[$i+6] $vertexTab[$i+7]\n";

}

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.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!