How to set texture coordinate indices

Hi all,



I have some problem making a texture show properly. I have an array of texture coordinates and an array of texture coordinate indices.

Anyone knows how to set the texture coordinate indices on the geometry ? so far I can only find a method for setting the texture coords.

In Java3D there was a method called "setTextureCoordinateIndices()".

This is what I do but the result looks all wrong. Thanks.


mesh = new TriMesh(name);
mesh.setVertexBuffer(vertices);
mesh.setIndexBuffer(indices);
mesh.setNormalBuffer(normals);
TexCoords t = new TexCoords(textureCoords);


The same indices are used for all other information. That is, the indices you setup for your vertices should correspond to those of your normals and your texture coordinates as well.

duenez said:

The same indices are used for all other information. That is, the indices you setup for your vertices should correspond to those of your normals and your texture coordinates as well.


Thanks for your response but right now the two arrays of indices are different...
And I don't  how I can use the same indices for everything.
What I mean is that what should you do if you import from a format that has two arrays of indices, one for vertices and one for texture coordinates..OBJ has that, for example.


The index buffer (in regards to mesh.setIndexBuffer(…) ) corresponds to how the vertices,normals,and tex coordinates should be put together to form triangles. So every index element corresponds to a vertex/normal/tex triplet, and every three index elements forms a triangle.



Come to think of it, I don't think TriMesh has a method to set the texcoords, though usually you'd just use TriMesh's reconstruct method. One of TriMesh's constructors also takes in the texcoord buffer.



Look at the javadoc for the TexCoord and TriMesh classes and the wiki page talking about TriMeshes:



http://www.jmonkeyengine.com/wiki/doku.php?id=trimesh

Thanks…I'm still not seeing the big picture though. The documentation says that somehow all idices should be bundles inside one array. But I can't see how this:

// The indexes of Vertex/Normal/Color/TexCoord sets.  Every 3 makes a triangle.
        int[] indexes={
            0,1,2,1,2,3
        };



Can describe anything else than the faces...unless vertex indices and texcoord indices always have the same value.

there needs to be a texture coordinate (s, t, r etc) per vertex…

however you can have different values for the texture coordinate per texture…

e.g.



if you have a quad with a pt (-5, -5, 5) which has 2 textures (unit 0 and unit 1) then

texture coordinate for texture 0 could be 0, 0

texture coordinate for texture 1 could be 1, 0



to get the texture coordinate for a particular texture it's just a look up;


  1. get the vertex index from the vertex indicies
  2. get the current texture unit
  3. get the texture coordinate from geometry.textureCoordinates[textureUnit].coords[vertex index]



    does this help?
Baune said:

Thanks..I'm still not seeing the big picture though. The documentation says that somehow all idices should be bundles inside one array. But I can't see how this:

// The indexes of Vertex/Normal/Color/TexCoord sets.  Every 3 makes a triangle.
        int[] indexes={
            0,1,2,1,2,3
        };



Can describe anything else than the faces...unless vertex indices and texcoord indices always have the same value.


In that example from the wiki, there are two triangles.

Each index value corresponds to the index of the vertex/normal/texCoord arrays. So the first vertex rendered in that example uses the coordinates at vertexes[0], the normal vector at normals[0], texture coordinates at texCoords[0], and color values at colors[0]. And so on.

It can be a bit confusing at first, but it's really just telling us which bits of data to use. If you notice, all those buffers only have 4 elements, yet there are two triangles. In reality you should have 6 vertices, 6 normals, 6 texture coordinates. So data's re-used, and the indices tell us which.

Now if lets say you build a trimesh where you specify 6 vertices, 6 normals, 6 tex coords etc and the first three make the first triangle, and the second three make the second triangle. Then it's real simple, the index buffer would look like this:

0,1,2,3,4,5

Hope that clarifies...it's all about how your vertex, normals, texcoord, and color buffers line up and specifying the renderer that order. So if the first three vertices in your array make up a triangle, they better line up with the first three texcoords in your texcoord array, else you'll have mismatch and your rendered triangle will be messed up if the first three texcoords were meant for -another- triangle (like a triangle with vertices in the 3rd, 4th, and 5th spots in the vertex array).

So if you have an vertex index buffer that looks like this : 1,2,3,4 your texture coordinate indice buffer must also be 1,2,3,4 and color buffer also. So they in fact just share the same indices.



But what if a vertex could have different textcoord, depending on which face it belongs to ?







What I have is two different arrays, ex. vertex buffer : 1,2,3,4, tic buffer :1,3,4,6 (just and example).






the texture coordinate buffer is just that…

actual texture coordinates…

the only buffer with indices is the index buffer which defines for each point in the triangle which vertex, colour, texture coordinate to use…

e.g.



index buffer

0, 1, 2



vertexbuffer (x, y, z)

0 0 0

1 0 0

1 1 0



texture buffer (s, t)

0 0

1 0

0.5 0.5



would give a triangle with

pts (0 0 0, 1 0 0, 1 1 0) using the following corresponding texture coordinates (0 0, 1 0, 0.5 0.5)

So,  you're saying that index buffer = texture index buffer ?

The index buffer used by OpenGL describes triangles by having 3 integers per triangle. Each int is the “vertex number” so 3 of those would give you 3 vertexes or one triangle. The OBJ format for example uses different indices for each attribute, so it is necessary to process the triangles so that only one index buffer is used, see OBJLoader class in jME3 for an example of how to do it.

Baune said:

So,  you're saying that index buffer = texture index buffer ?


as far as i'm aware yes...
as in the index in the index buffer is the offset into the vertex list of the vertex to use and the index into the texture coordinate list of the texture coordinate to use for that texture...
here is the output of the buffers for a Quad...maybe this makes more sense

Vertex Buffer
vertex buffer length 12
vertex count 4
(v 0) -2.5, 2.5, 0.0
(v 1) -2.5, -2.5, 0.0
(v 2) 2.5, -2.5, 0.0
(v 3) 2.5, 2.5, 0.0

IndexBuffer
Num indices = 6
0 1 2
0 2 3

TexCoords
tex coords entry 0 (coords per vert = 2)
0.0, 1.0,
0.0, 0.0,
1.0, 0.0,
1.0, 1.0,

NormalBuffer
0.0, 0.0, 1.0
0.0, 0.0, 1.0
0.0, 0.0, 1.0
0.0, 0.0, 1.0

!!!!!!!!!!! No Colours In Buffer !!!!!!!!!!!!!!!

World Data
tx 0.00, 0.00, 0.00
rot 0.00, 0.00, 0.00, 1.00
bound c(0.00, 0.00, 0.00) e(3.54, 3.54, 3.54)

It all makes sense now…but I still have a format where index buffer is not the same as TIC buffer…that format was working in java3d…but not in  jmonkey, at least not without some conversion.



I think I will have to take a look at the objloader.


I'm still not sure how to crack this one but thanks everyone.

The important thing to take into account is what does the texture coords index buffer contain. In jME the idea is to have one array of indices that manage which values get associated with each vertex (be it a normal, a color, a position or a texture coordinate). If you know what the texture index buffer contains, then you can simply create a new array with texture coordinates (not indices, but the actual data) and simply place in it, from your original array, the tex-coordinates that correspond to your vertices in the same order as they appear in the colors, normal, and positions. Then simply scrap the old tex-coords array and indices.



I hope this helps.

duenez said:

The important thing to take into account is what does the texture coords index buffer contain. In jME the idea is to have one array of indices that manage which values get associated with each vertex (be it a normal, a color, a position or a texture coordinate). If you know what the texture index buffer contains, then you can simply create a new array with texture coordinates (not indices, but the actual data) and simply place in it, from your original array, the tex-coordinates that correspond to your vertices in the same order as they appear in the colors, normal, and positions. Then simply scrap the old tex-coords array and indices.

I hope this helps.

Thanks, that was just the advice I needed.
So I wrote this routine here  that does that, and it  seems to work :

public float  [] convert(int [] texIndices,int [] faces, float [] textureCoords) {
      
      float [] resultArray = new float[textureCoords.length];
      for (int count = 0; count < texIndices.length;count++) {
         int index = texIndices[count];
         float u = textureCoords[index*2];
         float v = textureCoords[index*2+1];
         int index2 = faces[count];
         resultArray[index2*2]=u;
         resultArray[index2*2+1]=v;
      }
       return resultArray;
      }


Edit seems like there's still some small errors in the textures, not much though..wonder what that could be..

Edit: it will never work, because in the data I have a vertex can have more than one UV coordinate..

If a vertex has multiple UV coordinates, for each UV coordinate you need to duplicate that vertex. Maybe looking at the model converters in the source will help?



It may also be easier, if possible, to not work with large arrays of vertices/texcoords, and deal with things on a triangle level. I know some of the converters do that (and so does my deled importer).

Yes I understand this…but this is not an easy task, and not something you want to spend time with when you already  have all data ready. My cousin rewrote my  blender exporter so it would duplicate vertices…the routine to assign vertices to skin bones also had to be altered. It took him a while…and he is a phd in math. So any noob trying is doomed to fail.

The best thing would be for Jmonkey to support this, as I understand it, rather common feature. Java3D can, OSG can just to name a few. .I mean it should  be easy to get content into an engine.



Not to criticize just trying to make JME even better. And thanks for your help all !