I'm writing a BSP viewer for a university project. So far I have the main geometry loaded properly, and the PVS working.

Now I'm trying to apply the lightmaps, but I can't seem to get the texture coordinates for the lightmaps calculated properly.

According to here: http://developer.valvesoftware.com/wiki/The_Source_Engine_BSP_File_Format

struct texinfo_t
    float textureVecs[2][4];  // [s/t][xyz offset]
    float lightmapVecs[2][4]; // [s/t][xyz offset] - length is in units of texels/area
    int flags;                // miptex flags overrides
    int texdata;               // Pointer to texture name, size, etc.

The first array of floats is in essence two vectors that represent how the texture is orientated and scaled when rendered on the world geometry. The two vectors, s and t, are the mapping of the left-to-right and down-to-up directions in the texture pixel coordinate space, onto the world. Each vector has an x, y, and z component, plus an offset which is the "shift" of the texture in that direction relative to the world. The length of the vectors represent the scaling of the texture in each direction.

The 2D coordinates (u, v) of a texture pixel (or texel) are mapped to the world coordinates (x, y, z) of a point on a face by:

u = tv0,0 * x + tv0,1 * y + tv0,2 * z + tv0,3

v = tv1,0 * x + tv1,1 * y + tv1,2 * z + tv1,3

(ie. The dot product of the vectors with the vertex plus the offset in that direction. Where tvA,B is textureVecs[A][B].

Furthermore, after calculating (u, v), to convert them to texture coordinates which you would send to your graphics card, divide u and v by the width and height of the texture respectively.

So I am doing the calculation as follows. Take the dot product of the vertex and the lightmap vector(lightmapVecs[0][0], lightmapVecs0, lightmapVecs[0][2]) add the offset (lightmapVecs[0][3]), subtract the mins, and divide the result by the width/height.

float s = Vector3f.dot(v, new Vector3f(lightmapVecs[0][0], lightmapVecs[0][1], lightmapVecs[0][2])) + lightmapVecs[0][3] - f.LightmapTextureMinsInLuxels[0];
float t = Vector3f.dot(v, new Vector3f(lightmapVecs[1][0], lightmapVecs[1][1], lightmapVecs[1][2])) + lightmapVecs[1][3] - f.LightmapTextureMinsInLuxels[1];
s /= (f.LightmapTextureSizeInLuxels[0] + 1);
t /= (f.LightmapTextureSizeInLuxels[1] + 1);

However it ends up looking like this: lightmaps

Here's a sample calculation for the texture coord 't' for one vertex.

vertex = 352.0, -144.00027, -224.0
lightmap vector = -4, 0, 0
lightmap offset = 0
lightmap mins = 9
lightmap height = 14

So the dot product is -1408

(-1408 + 0 - 9) / 14

t = -101.21

This seems way off.

  • \$\begingroup\$ If you can post a picture link in the comments, someone can edit it in for you. \$\endgroup\$ Mar 31, 2011 at 15:36
  • \$\begingroup\$ Thanks. I got a few vote ups so i can post pictures now. :) \$\endgroup\$
    – terryhau
    Mar 31, 2011 at 18:00
  • \$\begingroup\$ Why are you dividing by 14? Is your lightmap's size really "14"? Most lightmaps are powers of 2... \$\endgroup\$
    – PatrickB
    Apr 1, 2011 at 1:38

2 Answers 2


I eventually figured out, I was reading the data in wrong. All the code above is correct.


You should normalize the vectors before calculating the dot product.


You must log in to answer this question.

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