Browse Source

Fixed some issues with texture atlas, page and ID generation. Texture references generally seem to be in order now, but UVs are still a problem.

master
Nico de Poel 3 years ago
parent
commit
72d03aff9c
  1. 14
      main.cpp
  2. 2
      ps1bsp.h
  3. 18
      texture.cpp

14
main.cpp

@ -124,7 +124,7 @@ int process_faces(const world_t* world, const std::vector<ps1bsp_texture_t>& tex
outFace.planeId = face->plane_id; outFace.planeId = face->plane_id;
outFace.side = face->side; outFace.side = face->side;
outFace.firstFaceVertex = (unsigned short)outFaceVertices.size(); outFace.firstFaceVertex = (unsigned short)outFaceVertices.size();
outFace.textureId = (unsigned char)face->texinfo_id;
outFace.textureId = (unsigned char)texinfo->texture_id;
// Traverse the list of face edges to collect all of the face's vertices // Traverse the list of face edges to collect all of the face's vertices
Vec3 vertexSum; Vec3 vertexSum;
@ -140,19 +140,19 @@ int process_faces(const world_t* world, const std::vector<ps1bsp_texture_t>& tex
const vertex_t* vertex = &world->vertices[vertIndex]; const vertex_t* vertex = &world->vertices[vertIndex];
Vec3 vertexPoint = vertex->toVec(); Vec3 vertexPoint = vertex->toVec();
ps1bsp_facevertex_t faceVertex;
ps1bsp_facevertex_t faceVertex = { 0 };
faceVertex.index = vertIndex; faceVertex.index = vertIndex;
faceVertex.light = 0; faceVertex.light = 0;
outFaceVertices.push_back(faceVertex);
// Calculate texture UVs // Calculate texture UVs
float s = (vertexPoint.dotProduct(texinfo->vectorS) + texinfo->distS) / miptex->width; float s = (vertexPoint.dotProduct(texinfo->vectorS) + texinfo->distS) / miptex->width;
float t = (vertexPoint.dotProduct(texinfo->vectorT) + texinfo->distT) / miptex->height; float t = (vertexPoint.dotProduct(texinfo->vectorT) + texinfo->distT) / miptex->height;
while (s > 1) s -= 1; while (s < 0) s += 1; // TODO: this is a nasty fudge to deal with the lack of texture tiling on PS1 hardware
while (t > 1) t -= 1; while (t < 0) t += 1; // We'll need to break up the faces and manually tile I guess...
// Rescale the UVs to the dimensions of the mipmap we've selected for our texture atlas // Rescale the UVs to the dimensions of the mipmap we've selected for our texture atlas
faceVertex.u = (unsigned char)(s * ps1tex.w);
faceVertex.v = (unsigned char)(t * ps1tex.h);
faceVertex.u = (unsigned char)(fmodf(s * ps1tex.w, ps1tex.w)); // TODO: fmodf is a nasty fudge to deal with the lack of texture tiling on PS1 hardware
faceVertex.v = (unsigned char)(fmodf(t * ps1tex.h, ps1tex.h)); // We'll need to break up the faces and manually tile I guess...
outFaceVertices.push_back(faceVertex);
// Calculate bounding box of this face // Calculate bounding box of this face
if (edgeListIdx == 0) if (edgeListIdx == 0)

2
ps1bsp.h

@ -42,8 +42,8 @@ typedef struct
typedef struct typedef struct
{ {
unsigned char w, h; // These may be necessary for scaling UVs, especially since we use a mix of mip0 and mip1 textures unsigned char w, h; // These may be necessary for scaling UVs, especially since we use a mix of mip0 and mip1 textures
unsigned short tpage; // Texture page in PS1 VRAM (precalculated when generating the texture atlas)
unsigned char uoffs, voffs; // Texture coordinate offset within the texture page unsigned char uoffs, voffs; // Texture coordinate offset within the texture page
unsigned short tpage; // Texture page in PS1 VRAM (precalculated when generating the texture atlas)
unsigned short nextframe; // If non-zero, the texture is animated and this points to the next texture in the sequence unsigned short nextframe; // If non-zero, the texture is animated and this points to the next texture in the sequence
} ps1bsp_texture_t; } ps1bsp_texture_t;

18
texture.cpp

@ -49,7 +49,7 @@ bool process_textures(const world_t* world, std::vector<ps1bsp_texture_t>& outTe
if (strcmp(miptex->name, "clip") && strcmp(miptex->name, "trigger")) if (strcmp(miptex->name, "clip") && strcmp(miptex->name, "trigger"))
rectangles.emplace_back(rectpack2D::rect_xywh(0, 0, miptex->width >> ps1mip, miptex->height >> ps1mip)); rectangles.emplace_back(rectpack2D::rect_xywh(0, 0, miptex->width >> ps1mip, miptex->height >> ps1mip));
else else
rectangles.emplace_back(rectpack2D::rect_xywh(0, 0, 0, 0));
rectangles.emplace_back(rectpack2D::rect_xywh(0, 0, miptex->width >> 3, miptex->width >> 3)); // Add the lowest mip level so that it at least gets included in the final texture list, and we don't mess up the texture IDs
} }
// Automatic atlas packing. Nice but it tries to make a square atlas which is not what we want. (This is solved by hacking the header itself) // Automatic atlas packing. Nice but it tries to make a square atlas which is not what we want. (This is solved by hacking the header itself)
@ -110,27 +110,29 @@ bool process_textures(const world_t* world, std::vector<ps1bsp_texture_t>& outTe
} }
ps1bsp_texture_t ps1tex = { 0 }; ps1bsp_texture_t ps1tex = { 0 };
ps1tex.w = (u_char)miptex->width;
ps1tex.h = (u_char)miptex->height;
ps1tex.w = (u_char)rectangle.w;
ps1tex.h = (u_char)rectangle.h;
u_short x = rectangle.x + 512;
u_short y = rectangle.y + 256;
// prect is derived from the texture's position inside the atlas (rectangle.x/y) and the planned position of the atlas in VRAM (512, 256) // prect is derived from the texture's position inside the atlas (rectangle.x/y) and the planned position of the atlas in VRAM (512, 256)
// mode is always 1 (8-bit palletized) // mode is always 1 (8-bit palletized)
//texture->uoffs = (texture->prect.x % 64) << (2 - (texture->mode & 0x3)); //texture->uoffs = (texture->prect.x % 64) << (2 - (texture->mode & 0x3));
//texture->voffs = (texture->prect.y & 0xFF); //texture->voffs = (texture->prect.y & 0xFF);
u_short x = (rectangle.x / 2) + 512; // Divide by 2 to get the coordinate in 16-bit pixel units
u_short y = rectangle.y + 256;
/* /*
tp specifies the color depth for the texture page in the range of 0 to 2 (0:4-bit, 1:8-bit, 2:16-bit). tp specifies the color depth for the texture page in the range of 0 to 2 (0:4-bit, 1:8-bit, 2:16-bit).
abr specifies the blend operator for both non-textured and textured semi-transparent primitives which can be ignored for now and lastly, abr specifies the blend operator for both non-textured and textured semi-transparent primitives which can be ignored for now and lastly,
x,y specifies the X,Y coordinates of the VRAM in 16-bit pixel units. x,y specifies the X,Y coordinates of the VRAM in 16-bit pixel units.
Keep in mind that the coordinates will be rounded down to the next lowest texture page. */ Keep in mind that the coordinates will be rounded down to the next lowest texture page. */
ps1tex.tpage = getTPage(1, 0, x, y);
ps1tex.uoffs = (u_char)((x % 64) << 1);
const int mode = 1; // 8-bit per pixel, all Quake textures use this
ps1tex.tpage = getTPage(mode, 0, x, y);
ps1tex.uoffs = (u_char)((x % 64) << (2 - mode));
ps1tex.voffs = (u_char)(y & 0xFF); ps1tex.voffs = (u_char)(y & 0xFF);
// TODO: animated textures // TODO: animated textures
outTextures.push_back(ps1tex); outTextures.push_back(ps1tex);
} }
} }

Loading…
Cancel
Save