diff --git a/main.cpp b/main.cpp index 028d457..0c04fcd 100644 --- a/main.cpp +++ b/main.cpp @@ -124,7 +124,7 @@ int process_faces(const world_t* world, const std::vector& tex outFace.planeId = face->plane_id; outFace.side = face->side; 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 Vec3 vertexSum; @@ -140,19 +140,19 @@ int process_faces(const world_t* world, const std::vector& tex const vertex_t* vertex = &world->vertices[vertIndex]; Vec3 vertexPoint = vertex->toVec(); - ps1bsp_facevertex_t faceVertex; + ps1bsp_facevertex_t faceVertex = { 0 }; faceVertex.index = vertIndex; faceVertex.light = 0; - outFaceVertices.push_back(faceVertex); // Calculate texture UVs float s = (vertexPoint.dotProduct(texinfo->vectorS) + texinfo->distS) / miptex->width; 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 - 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 if (edgeListIdx == 0) diff --git a/ps1bsp.h b/ps1bsp.h index ee293d7..d825739 100644 --- a/ps1bsp.h +++ b/ps1bsp.h @@ -42,8 +42,8 @@ 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 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 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 } ps1bsp_texture_t; diff --git a/texture.cpp b/texture.cpp index dd784bd..78b325c 100644 --- a/texture.cpp +++ b/texture.cpp @@ -49,7 +49,7 @@ bool process_textures(const world_t* world, std::vector& outTe if (strcmp(miptex->name, "clip") && strcmp(miptex->name, "trigger")) rectangles.emplace_back(rectpack2D::rect_xywh(0, 0, miptex->width >> ps1mip, miptex->height >> ps1mip)); 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) @@ -110,27 +110,29 @@ bool process_textures(const world_t* world, std::vector& outTe } 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) // mode is always 1 (8-bit palletized) //texture->uoffs = (texture->prect.x % 64) << (2 - (texture->mode & 0x3)); //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). 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. 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); // TODO: animated textures + outTextures.push_back(ps1tex); } }