Hello there!
I'm doing my own Source BSP renderer as well and in researching the face displacement algorithm I found your repo, and saw that you were having problems with it too.
I just spent 2 days reverse engineering the format and found the solution.
I don't have much time to open a PR so I'll leave the code here:
void generatePatch(const std::vector<glm::vec3>& inVertices, const std::vector<unsigned int>& inIndices, std::vector<glm::vec3>& outVertices, std::vector<glm::vec2>& uvs, std::vector<unsigned int>& indices, ddispinfo_t dispInfo, float tv[2][4], dface_t face) {
auto lerp = [](glm::vec3 a, glm::vec3 b, float t) -> glm::vec3 {
return a + t * (b - a);
};
std::vector<glm::vec3> v = { inVertices[0], inVertices[1], inVertices[2], inVertices[3] };
//check which corner has the minimum value, to use it as starting point
float startDist = 10000000000000; //big number, nothing special
int startIndex = -1;
for (int j = 0; j < 4; j++) {
const float dist = glm::distance(v[j], dispInfo.startPosition);
if (dist < startDist) {
startIndex = j;
startDist = dist;
}
}
//rotate the vector to put the lowest point first
if (startIndex != 0)
std::rotate(v.begin(), v.begin() + startIndex, v.end());
int power = dispInfo.power;
int numVerts = glm::pow((glm::pow(2, power) + 1), 2);
int length = (1 << power) + 1;
outVertices.resize(numVerts);
glm::vec3 v0{};
glm::vec3 v1{};
for (int i = 0; i < length; i++) {
const float ty = (float)i / (float)(length - 1);
v0 = lerp(v[0], v[1], ty);
v1 = lerp(v[3], v[2], ty);
for (int j = 0; j < length; j++) {
int index = dispInfo.DispVertStart + (i * length) + j;
auto& dispVertex = m_pBspFileData.vertDisps[index];
const float tx = (float)j / (float)(length - 1.0f);
glm::vec3 vtx = lerp(v0, v1, tx);
//Generate texcoords
float u = (tv[0][0] * vtx.x) + (tv[0][1] * vtx.y) + (tv[0][2] * vtx.z) + tv[0][3];
float v = (tv[1][0] * vtx.x) + (tv[1][1] * vtx.y) + (tv[1][2] * vtx.z) + tv[1][3];
uvs.push_back(glm::vec2(u, v));
//displace
vtx += dispVertex.vec * dispVertex.dist;
outVertices[i * length + j] = vtx;
}
}
//Triangulate
int edge = 0;
for (int i = 0; i < numVerts - length; i++) {
if (edge == length - 1) {
edge = 0;
continue;
}
indices.push_back(i + 1);
indices.push_back(i);
indices.push_back(i + length);
indices.push_back(i + 1);
indices.push_back(i + length);
indices.push_back(i + length + 1);
edge++;
}
}
Hello there!
I'm doing my own Source BSP renderer as well and in researching the face displacement algorithm I found your repo, and saw that you were having problems with it too.
I just spent 2 days reverse engineering the format and found the solution.
I don't have much time to open a PR so I'll leave the code here:
Anyway, I hope you find this useful
Good luck!