diff --git a/GPU/Common/SplineCommon.cpp b/GPU/Common/SplineCommon.cpp index fdf441749..d5fccea3a 100644 --- a/GPU/Common/SplineCommon.cpp +++ b/GPU/Common/SplineCommon.cpp @@ -15,6 +15,13 @@ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. +/* +#define WIN32_LEAN_AND_MEAN +#include +#undef min +#undef max +*/ + #include #include @@ -294,16 +301,10 @@ static void SplinePatchFullQuality(u8 *&dest, u16 *indices, int &count, const Sp // Full (mostly) correct tessellation of spline patches. // Not very fast. - // First, generate knot vectors. - int n = spatch.count_u - 1; - int m = spatch.count_v - 1; - - - - float *knot_u = new float[n + 5]; - float *knot_v = new float[m + 5]; - spline_knot(n, spatch.type_u, knot_u); - spline_knot(m, spatch.type_v, knot_v); + float *knot_u = new float[spatch.count_u + 4]; + float *knot_v = new float[spatch.count_v + 4]; + spline_knot(spatch.count_u - 1, spatch.type_u, knot_u); + spline_knot(spatch.count_v - 1, spatch.type_v, knot_v); // Increase tesselation based on the size. Should be approximately right? int patch_div_s = (spatch.count_u - 3) * gstate.getPatchDivisionU(); @@ -313,28 +314,34 @@ static void SplinePatchFullQuality(u8 *&dest, u16 *indices, int &count, const Sp patch_div_t /= quality; } - if (patch_div_s < 2) patch_div_s = 2; - if (patch_div_t < 2) patch_div_t = 2; - // Downsample until it fits, in case crazy tesselation factors are sent. while ((patch_div_s + 1) * (patch_div_t + 1) > maxVertices) { patch_div_s /= 2; patch_div_t /= 2; } + if (patch_div_s < 2) patch_div_s = 2; + if (patch_div_t < 2) patch_div_t = 2; + // First compute all the vertices and put them in an array SimpleVertex *&vertices = (SimpleVertex*&)dest; float tu_width = (float)spatch.count_u - 3.0f; float tv_height = (float)spatch.count_v - 3.0f; + // int max_idx = spatch.count_u * spatch.count_v; + bool computeNormals = gstate.isLightingEnabled(); + + float one_over_patch_div_s = 1.0f / (float)(patch_div_s); + float one_over_patch_div_t = 1.0f / (float)(patch_div_t); + for (int tile_v = 0; tile_v < patch_div_t + 1; tile_v++) { - float v = ((float)tile_v * (float)(m - 2) / (float)(patch_div_t + 0.00001f)); // epsilon to prevent division by 0 in spline_s + float v = (float)tile_v * (float)(spatch.count_v - 3) * one_over_patch_div_t; if (v < 0.0f) v = 0.0f; for (int tile_u = 0; tile_u < patch_div_s + 1; tile_u++) { - float u = ((float)tile_u * (float)(n - 2) / (float)(patch_div_s + 0.00001f)); + float u = (float)tile_u * (float)(spatch.count_u - 3) * one_over_patch_div_s; if (u < 0.0f) u = 0.0f; SimpleVertex *vert = &vertices[tile_v * (patch_div_s + 1) + tile_u]; @@ -354,22 +361,29 @@ static void SplinePatchFullQuality(u8 *&dest, u16 *indices, int &count, const Sp vert->uv[0] = 0.0f; vert->uv[1] = 0.0f; } else { - vert->uv[0] = tu_width * ((float)tile_u / (float)patch_div_s); - vert->uv[1] = tv_height * ((float)tile_v / (float)patch_div_t); + vert->uv[0] = tu_width * ((float)tile_u * one_over_patch_div_s); + vert->uv[1] = tv_height * ((float)tile_v * one_over_patch_div_t); } + // Collect influences from surrounding control points. float u_weights[4]; float v_weights[4]; int iu = (int)u; int iv = (int)v; + + // TODO: Would really like to fix the surrounding logic somehow to get rid of these but I can't quite get it right.. + // Without the previous epsilons and with large count_u, we will end up doing an out of bounds access later without these. + if (iu >= spatch.count_u - 3) iu = spatch.count_u - 4; + if (iv >= spatch.count_v - 3) iv = spatch.count_v - 4; + spline_n_4(iu, u, knot_u, u_weights); spline_n_4(iv, v, knot_v, v_weights); // Handle degenerate patches. without this, spatch.points[] may read outside the number of initialized points. - int patch_w = std::min(spatch.count_u, 4); - int patch_h = std::min(spatch.count_v, 4); + int patch_w = std::min(spatch.count_u - iu, 4); + int patch_h = std::min(spatch.count_v - iv, 4); for (int ii = 0; ii < patch_w; ++ii) { for (int jj = 0; jj < patch_h; ++jj) { @@ -384,6 +398,13 @@ static void SplinePatchFullQuality(u8 *&dest, u16 *indices, int &count, const Sp Vec4f fv = Vec4f::AssignToAll(f); #endif int idx = spatch.count_u * (iv + jj) + (iu + ii); + /* + if (idx >= max_idx) { + char temp[512]; + snprintf(temp, sizeof(temp), "count_u: %d count_v: %d patch_w: %d patch_h: %d ii: %d jj: %d iu: %d iv: %d patch_div_s: %d patch_div_t: %d\n", spatch.count_u, spatch.count_v, patch_w, patch_h, ii, jj, iu, iv, patch_div_s, patch_div_t); + OutputDebugStringA(temp); + DebugBreak(); + }*/ SimpleVertex *a = spatch.points[idx]; AccumulateWeighted(vert_pos, a->pos, fv); if (origTc) {