Stretched texture on custom geometry

Hi to all,

yet another simple question, I made a cube using custom geometry in panda3d version 1.7.2 [I’ll stick to finishing my project on this version at first, for easier distribution, given some of the issues that arise when using newer versions on old machines…]. I applied the texture to it, and this is the result:


I’ve tweaked it under different uv scales, offsets and texture-rotations, but the result is still the same; there is always the occurrence of stretching. Could anyone be kind enough to show me how I would avoid this, by creating a cube, then applying a texture to it that is free of stretching?

Can you show the code you are using to generate the cube? Most likely the UV assignments are incorrect.

Sorry, forgot to put the code, here it is:


#administrative data....
      array = GeomVertexArrayFormat()
      array.addColumn(InternalName.make('vertex'), 3,Geom.NTFloat32, Geom.CPoint)
      array = GeomVertexArrayFormat()
      array.addColumn(InternalName.make('vertex'), 3,Geom.NTFloat32, Geom.CPoint)
      array.addColumn(InternalName.make('texcoord'), 2,Geom.NTFloat32, Geom.CTexcoord)
      array.addColumn(InternalName.make('normal'), 3,Geom.NTFloat32, Geom.CVector)
      array.addColumn(InternalName.make('color'), 4,Geom.NTFloat32, Geom.CColor)
      format = GeomVertexFormat()
      format.addArray(array)
      format = GeomVertexFormat.registerFormat(format)
      vdata = GeomVertexData('name', format, Geom.UHStatic)
      vertex = GeomVertexWriter(self.vdata, 'vertex')
      normal = GeomVertexWriter(self.vdata, 'normal')
      color = GeomVertexWriter(self.vdata, 'color')
      texcoord = GeomVertexWriter(self.vdata, 'texcoord')
      geom = Geom(self.vdata)

#vertices...

           vertex.addData3f(-4,0,0)
           normal.addData3f(0, 0, 1)
           color.addData4f(1, 1, 1, 1)
           texcoord.addData2f(1, 0)


           vertex.addData3f(4, 0, 0)
           normal.addData3f(0, 0, 1)
           color.addData4f(1, 1, 1, 1)
           texcoord.addData2f(1, 1)

           vertex.addData3f(-4, 0, 8)
           normal.addData3f(0, 0, 1)
           color.addData4f(1, 1, 1, 1)
           texcoord.addData2f(0, 1)

           
           vertex.addData3f(4, 0, 8)
           normal.addData3f(0, 0, 1)
           color.addData4f(1, 1, 1, 1)
           texcoord.addData2f(0, 0)


           vertex.addData3f(-4,8,0)
           normal.addData3f(0, 0, 1)
           color.addData4f(1, 1, 1, 1)
           texcoord.addData2f(1, 0)


           vertex.addData3f(4, 8, 0)
           normal.addData3f(0, 0, 1)
           color.addData4f(1, 1, 1, 1)
           texcoord.addData2f(1, 1)

           vertex.addData3f(-4, 8, 8)
           normal.addData3f(0, 0, 1)
           color.addData4f(1, 1, 1, 1)
           texcoord.addData2f(0, 1)

           
           vertex.addData3f(4, 8, 8)
           normal.addData3f(0, 0, 1)
           color.addData4f(1, 1, 1, 1)
           texcoord.addData2f(0, 0)

#primitives....

           prim = GeomTriangles(Geom.UHStatic)
           prim.addVertices(0, 1, 3)
           prim.addVertices(0, 2, 3)

           
           prim1q = GeomTriangles(Geom.UHStatic)
           prim1q.addVertices(0, 4, 6)
           prim1q.addVertices(0, 2, 6)

           prim2q = GeomTriangles(Geom.UHStatic)
           prim2q.addVertices(1, 7, 5)
           prim2q.addVertices(1, 3, 7)

           prim3q = GeomTriangles(Geom.UHStatic)
           prim3q.addVertices(4, 5, 7)
           prim3q.addVertices(4, 6, 7)

           prim4q = GeomTriangles(Geom.UHStatic)
           prim4q.addVertices(2, 6, 3)
           prim4q.addVertices(3, 6, 7)

           prim5q = GeomTriangles(Geom.UHStatic)
           prim5q.addVertices(0, 1, 4)
           prim5q.addVertices(1, 4, 5)

#add the prims to the geom...

           geom.addPrimitive(prim)
           geom.addPrimitive(prim1q)
           geom.addPrimitive(prim2q)
           geom.addPrimitive(prim3q)
           geom.addPrimitive(prim4q)
           geom.addPrimitive(prim5q)

#make geom node....
      string='box'
      node = GeomNode(string)
      node.addGeom(geom)

#nodepath...
      self.nodePathaqq = render.attachNewNode(node)
      self.nodePathaqq.setTwoSided(True)

#textures...
      myTexture = loader.loadTexture("wooden.jpg")
      self.nodePathaqq.setTexture(myTexture, 1)
      self.nodePathaqq.setTexOffset(TextureStage.getDefault(), self.u_offset, self.v_offset)
      self.nodePathaqq.setTexRotate(TextureStage.getDefault(), self.tex_rotate)
      self.nodePathaqq.setTexScale(TextureStage.getDefault(), self.u_scale, self.v_scale)

#uv-related data can be changed, in the beginning all of them are 0,0
#offsets increase or decrease by 0.1
#scales increase or decrease by 0.1
#rotation increases or decreases by 1.

Don’t worry about the indentation or such things…anyways, is it the texcoords that causes the stretching? Am I doing that incorrectly? Or is it something else?

I appreciate the patience and help as always.

Yes, in order to apply the same texture on all cube faces properly you need to duplicate each vertex for each face. Which means you’re writing out four vertices per face.

By the way, don’t create so many GeomTriangles objects. That’s bad for performance. Just create one GeomTriangles and add the triangles for all faces to it.

Thanks for the answer, but it isn’t very clear to me what you mean when you say:

There are already four vertices per face, unless I misunderstand what you mean.
Could you kindly clarify on that, perhaps with some example code?

Thanks.

You currently have 8 vertices, one for each corner. You’re sharing the vertices between faces. What you need is 24 vertices, four for each face, so that you can define the UVs separately for each face vertex.

Ie.

# Bottom face
vertex.addData3f(4, 0, 0)
vertex.addData3f(4, 8, 0)
vertex.addData3f(-4, 8, 0)
vertex.addData3f(-4, 0, 0)
texcoord.addData2f(0, 0)
texcoord.addData2f(0, 1)
texcoord.addData2f(1, 0)
texcoord.addData2f(1, 1)

# Top face
vertex.addData3f(4, 0, 8)
vertex.addData3f(4, 8, 8)
vertex.addData3f(-4, 8, 8)
vertex.addData3f(-4, 0, 8)
texcoord.addData2f(0, 0)
texcoord.addData2f(0, 1)
texcoord.addData2f(1, 0)
texcoord.addData2f(1, 1)

Etc. for each face.

Thank you once again for the answer! I say, I would have never guessed that that was the problem. Thank you very much, I really do appreciate it.