1
\$\begingroup\$

I am currently writing a UV texture mapper.

But i don't know how to convert UV coordinates to texel coordinates.

And i also have no idea how i should convert texel coordinates to "array coordinates".

By "array coordinates", i mean number that represents a part of an array (in this case a bitmap).

Here is my code:

 su =  (u0)  * (tx-1) ;
 sv =  (v0)  * (ty-1) ;


 texloc = ((sv >>16)* bytes_per_row) +((su>>16)* bytes_per_pixel);

Also i use fixedpoint math to interpolate between the uv coordinates.

tx and ty are the dimensions of the texturemap.

\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

WARNING: pointer math ahead.

texloc is the "array coordinate" or rather it's the byte offset:

uint32_t the_rgba8888_pixel = *((const uint32_t *) (((const uint8_t *)my_texture_data) + texloc));

Make sure you wrap u0 and v0 to (0 ... (1-epsilon)) first:

unsigned int su =  (u0 & 0xFFFF) * tx;
unsigned int sv =  (v0 & 0xFFFF) * ty;

texloc = ((sv >>16)* bytes_per_row) +((su>>16)* bytes_per_pixel);

uint8_t  pixel_8  = *((const uint8_t  *) (((const uint8_t *)my_texture_data) + texloc)); // 8bits
uint16_t pixel_16 = *((const uint16_t *) (((const uint8_t *)my_texture_data) + texloc)); // 16bits
uint32_t pixel_32 = *((const uint32_t *) (((const uint8_t *)my_texture_data) + texloc)); // 32bits

You can make this faster by pre-multiplying the UV coordinates by the texture size pre-interpolation, changing the mask to ((size-1) << 16), the shift amount and removing the multiplication of bytes_per_pixels and bytes_per_row.

For example 256x512 pixels, 32bpp:

((u0 & 0xFF0000u) >> 14) + ((v0 & 0x1FF0000u) >> 6).

That's

14 = (16 - bytes_per_pixel_as_shift_amount(4 = 1 << 2) ) 

and

6 = (16 - bytes_per_row_as_shift_amount(1024 = (256 x 4 bytes) = 1 << 10) )

This way you don't need to mask u0 and v0 first.

\$\endgroup\$
5
  • \$\begingroup\$ I there a non pointer math aproach? While, i do like this aproach. I am not good at pointer math. \$\endgroup\$ Commented Dec 26, 2014 at 22:40
  • \$\begingroup\$ Not for variable-sized arrays in C++ which you would need for different texture sizes, you will have to use linear arrays and calculate the offset yourself (pointer math) which is what texloc is. Any other solution will be slower as the compiler cannot fold the x4 or x2 (for 32bits and 16 bits) into the variable right-shifts and will need to do it in the read instruction. Although many CPUs support x4 and x2 right in the address calculation this prevents folding the variable shift right into the memory-read instruction (ARM), or may adds uOPs (x86) Practice makes perfect. \$\endgroup\$ Commented Dec 26, 2014 at 23:01
  • \$\begingroup\$ And thanks to user glampert for the formatting improvements. \$\endgroup\$ Commented Dec 26, 2014 at 23:01
  • \$\begingroup\$ I am using linear arrays for textures. \$\endgroup\$ Commented Dec 27, 2014 at 20:06
  • \$\begingroup\$ Doing array_pointer[x + y * width] is a form of pointer math. In C and C++ you can rewrite this as (array_pointer + y * width)[x] and (array_pointer + x + y * width)[0] and *(array_pointer + x + y * width) which all come down to the same result. \$\endgroup\$ Commented Dec 27, 2014 at 23:30

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .