Vedo: Is there an option to add texture-coordinates?

Created on 20 Nov 2019  路  5Comments  路  Source: marcomusy/vedo

I really like this python package, as it is simple to use for a beginner like me. I have a small question: is there a way to add in texture coordinates? I have a few simple 3D objects consisting of polygons, each with a texture that needs to be mapped to it according to X and Y texture coordinates within a [0, 1] interval. Through the tutorials in the documentation I was able to create a sample 3D object and add the textures, but without the texture coordinates the objects look quite wrong. Do you have any suggestions that could help me?

Here is a small example:

from vtkplotter import *

# six polygons consisting of points with X, Y, and Z coordinates 

polygon_a = [
    [
        (371982, 5812893, 47),
        (371987, 5812889, 47),
        (371993, 5812896, 47),
        (371988, 5812900, 47),
        (371982, 5812893, 47),
    ],
    [[0, 1, 2, 3, 4]],
]
polygon_b = [
    [
        (371987, 5812889, 44),
        (371987, 5812889, 47),
        (371982, 5812893, 47),
        (371982, 5812893, 44),
        (371987, 5812889, 44),
    ],
    [[0, 1, 2, 3, 4]],
]

polygon_c = [
    [
        (371993, 5812896, 44),
        (371993, 5812896, 47),
        (371987, 5812889, 47),
        (371987, 5812889, 44),
        (371993, 5812896, 44),
    ],
    [[0, 1, 2, 3, 4]],
]
polygon_d = [
    [
        (371982, 5812893, 44),
        (371982, 5812893, 47),
        (371988, 5812900, 47),
        (371988, 5812900, 44),
        (371982, 5812893, 44),
    ],
    [[0, 1, 2, 3, 4]],
]
polygon_e = [
    [
        (371988, 5812900, 44),
        (371988, 5812900, 47),
        (371993, 5812896, 47),
        (371993, 5812896, 44),
        (371988, 5812900, 44),
    ],
    [[0, 1, 2, 3, 4]],
]
polygon_f = [
    [
        (371987, 5812889, 44),
        (371982, 5812893, 44),
        (371988, 5812900, 44),
        (371993, 5812896, 44),
        (371987, 5812889, 44),
    ],
    [[0, 1, 2, 3, 4]],
]

# texture coordinates of X, Y with interval [0, 1]

texture_coords_a = [
    0.993515,
    0.590665,
    0.583403,
    0.995886,
    0.001318,
    0.409513,
    0.411194,
    0.00281,
    0.993515,
    0.590665,
]
texture_coords_b = [
    0.814495,
    0.004965,
    0.986562,
    0.175202,
    0.172649,
    0.994582,
    0.004011,
    0.820917,
    0.814495,
    0.004965,
]
texture_coords_c = [
    0.992976,
    0.869131,
    0.867654,
    0.99699,
    0.009377,
    0.134356,
    0.138307,
    0.010153,
    0.992976,
    0.869131,
]
texture_coords_d = [
    0.007693,
    0.148416,
    0.15451,
    0.00767,
    0.994519,
    0.86112,
    0.844256,
    0.998197,
    0.007693,
    0.148416,
]
texture_coords_e = [
    0.997322,
    0.660826,
    0.89938,
    0.990736,
    0.006374,
    0.337104,
    0.106732,
    0.00748,
    0.997322,
    0.660826,
]

# textures for some of the polygons as .jpg-files

img_a = "tex_2962910"
img_b = "tex_2962971"
img_c = "tex_2962990"
img_d = "tex_2962933"
img_e = "tex_2962915"

a = Actor(polygon_a)
b = Actor(polygon_b)
c = Actor(polygon_c)
d = Actor(polygon_d)
e = Actor(polygon_e)
f = Actor(polygon_f)

a.texture(img_a)
b.texture(img_b)
c.texture(img_c)
d.texture(img_d)
e.texture(img_e)

polygons = actors.Assembly([a, b, c, d, e, f])

printc("getPolygons() format is    :", a.getPolygons(), c=3)
printc("getConnectivity() format is:", a.getConnectivity(), c=3)

show(polygons, Text(__doc__), viewup="z", axes=8)
enhancement

Most helpful comment

It works perfectly! Thank you very much for your quick help!

All 5 comments

Hi @MarkusRosen at the minute the texture functionality is indeed quite basic in vtkplotter (partly because of my lack of understanding of how it really works..) ,
but i'm happy to improve it over some specific example!
I don't have the image files you would like to apply, and/or the desired output, so i cannot run your code, but i'll see what i can do.

Thanks for your quick response! I uploaded the mentioned textures (link will be offline in 7 days). https://send.firefox.com/download/800fe0acb4d53312/#epJwYzlAidXbZdY6Ihkhsg
The textures show a small building with a roof and 4 walls, all pretty low resolution from aerial photography.

The texture-coordinates in my example are of the form [X1, Y1, X2, Y2...], where X represents the width of the image and (1 - Y) the height of the image. PyVista seems to have such a feature with the t_coords property, it would be great if such a functionality could be added to vtkplotter!

https://docs.pyvista.org/examples/02-plot/texture.html#repeating-textures

Yep! Indeed I've already added the functionality - it was fairly trivial..
Later today I will commit a new version,
Thanks

image

Hi @MarkusRosen please try:
pip install vtkplotter -U

You can now pass texture coordinates to a mesh directly, along with a nr. of other options.
Your code above becomes:

from vtkplotter import *
import numpy as np

# six polygons consisting of points with X, Y, and Z coordinates
polygon_a = [
    [
        (371982, 5812893, 47),
        (371987, 5812889, 47),
        (371993, 5812896, 47),
        (371988, 5812900, 47),
        (371982, 5812893, 47),
    ],
    [[0, 1, 2, 3, 4]],
]
polygon_b = [
    [
        (371987, 5812889, 44),
        (371987, 5812889, 47),
        (371982, 5812893, 47),
        (371982, 5812893, 44),
        (371987, 5812889, 44),
    ],
    [[0, 1, 2, 3, 4]],
]

polygon_c = [
    [
        (371993, 5812896, 44),
        (371993, 5812896, 47),
        (371987, 5812889, 47),
        (371987, 5812889, 44),
        (371993, 5812896, 44),
    ],
    [[0, 1, 2, 3, 4]],
]
polygon_d = [
    [
        (371982, 5812893, 44),
        (371982, 5812893, 47),
        (371988, 5812900, 47),
        (371988, 5812900, 44),
        (371982, 5812893, 44),
    ],
    [[0, 1, 2, 3, 4]],
]
polygon_e = [
    [
        (371988, 5812900, 44),
        (371988, 5812900, 47),
        (371993, 5812896, 47),
        (371993, 5812896, 44),
        (371988, 5812900, 44),
    ],
    [[0, 1, 2, 3, 4]],
]
polygon_f = [
    [
        (371987, 5812889, 44),
        (371982, 5812893, 44),
        (371988, 5812900, 44),
        (371993, 5812896, 44),
        (371987, 5812889, 44),
    ],
    [[0, 1, 2, 3, 4]],
]

# texture coordinates of X, Y with interval [0, 1]
texture_coords_a = [
    0.993515,
    0.590665,
    0.583403,
    0.995886,
    0.001318,
    0.409513,
    0.411194,
    0.00281,
    0.993515,
    0.590665,
]
texture_coords_b = [
    0.814495,
    0.004965,
    0.986562,
    0.175202,
    0.172649,
    0.994582,
    0.004011,
    0.820917,
    0.814495,
    0.004965,
]
texture_coords_c = [
    0.992976,
    0.869131,
    0.867654,
    0.99699,
    0.009377,
    0.134356,
    0.138307,
    0.010153,
    0.992976,
    0.869131,
]
texture_coords_d = [
    0.007693,
    0.148416,
    0.15451,
    0.00767,
    0.994519,
    0.86112,
    0.844256,
    0.998197,
    0.007693,
    0.148416,
]
texture_coords_e = [
    0.997322,
    0.660826,
    0.89938,
    0.990736,
    0.006374,
    0.337104,
    0.106732,
    0.00748,
    0.997322,
    0.660826,
]

# reformat lists above as [(u,v), ...]
texture_coords_a = np.split(np.array(texture_coords_a), 5)
texture_coords_b = np.split(np.array(texture_coords_b), 5)
texture_coords_c = np.split(np.array(texture_coords_c), 5)
texture_coords_d = np.split(np.array(texture_coords_d), 5)
texture_coords_e = np.split(np.array(texture_coords_e), 5)

# textures for some of the polygons as .jpg-files
img_a = "tex_2962910.jpg"
img_b = "tex_2962971.jpg"
img_c = "tex_2962990.jpg"
img_d = "tex_2962933.jpg"
img_e = "tex_2962915.jpg"

a = Actor(polygon_a)
b = Actor(polygon_b)
c = Actor(polygon_c)
d = Actor(polygon_d)
e = Actor(polygon_e)
f = Actor(polygon_f)

a.texture(img_a, tcoords=texture_coords_a)
b.texture(img_b, tcoords=texture_coords_b)
c.texture(img_c, tcoords=texture_coords_c)
d.texture(img_d, tcoords=texture_coords_d)
e.texture(img_e, tcoords=texture_coords_e)

polygons = Assembly([a, b, c, d, e, f])

show(polygons, viewup="z", axes=8)

Also check out a new example here:

from vtkplotter import Actor, Text, datadir, show

# define a polygon of 4 vertices:
polygon_a = [
    [(82, 92, 47), (87, 88, 47), # x,y,z of vertices
     (93, 95, 47), (88, 99, 47)],
    [[0, 1, 2, 3]],              # vertex connectivity
]

# texture coordinates, one (u,v) pair for each vertex:
tc = [(0,0), (1,0), (1,1), (0,1)]
#tc = [(0,0), (2,0), (2,2), (0,2)]

# create the vtkActor
a = Actor(polygon_a)

a.texture(datadir+"images/dog.jpg",
          tcoords=tc,
          interpolate=True,
          repeat=True,      # when tcoords extend beyond [0,1]
          edgeClamp=False,  #  only used when repeat is False
         )

show(a,  axes=8)

Note that you don't need to repeat the first point at the last position.

Thanks for drawing my attention to the issue. Let me know if it gives you the expected result.

It works perfectly! Thank you very much for your quick help!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

FedeClaudi picture FedeClaudi  路  6Comments

m-albert picture m-albert  路  7Comments

kemo993 picture kemo993  路  6Comments

jrdkr picture jrdkr  路  7Comments

vigji picture vigji  路  3Comments