More work on spline/bezier tesselation. Disabled for now, there are still issues.
This commit is contained in:
parent
250678fa63
commit
171fe00383
2 changed files with 152 additions and 97 deletions
|
@ -765,13 +765,9 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) {
|
||||||
DEBUG_LOG_REPORT(G3D, "Bezier + skinning: %i", vertTypeGetNumBoneWeights(gstate.vertType));
|
DEBUG_LOG_REPORT(G3D, "Bezier + skinning: %i", vertTypeGetNumBoneWeights(gstate.vertType));
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Get rid of this old horror...
|
GEPatchPrimType patchPrim = gstate.getPatchPrimitiveType();
|
||||||
int bz_ucount = data & 0xFF;
|
int bz_ucount = data & 0xFF;
|
||||||
int bz_vcount = (data >> 8) & 0xFF;
|
int bz_vcount = (data >> 8) & 0xFF;
|
||||||
//transformDraw_.DrawBezier(bz_ucount, bz_vcount);
|
|
||||||
|
|
||||||
// And instead use this.
|
|
||||||
GEPatchPrimType patchPrim = gstate.getPatchPrimitiveType();
|
|
||||||
transformDraw_.SubmitBezier(control_points, indices, bz_ucount, bz_vcount, patchPrim, gstate.vertType);
|
transformDraw_.SubmitBezier(control_points, indices, bz_ucount, bz_vcount, patchPrim, gstate.vertType);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -131,80 +131,78 @@ u32 TransformDrawEngine::NormalizeVertices(u8 *outPtr, u8 *bufPtr, const u8 *inP
|
||||||
return GE_VTYPE_TC_FLOAT | GE_VTYPE_COL_8888 | GE_VTYPE_NRM_FLOAT | GE_VTYPE_POS_FLOAT | (vertType & GE_VTYPE_IDX_MASK);
|
return GE_VTYPE_TC_FLOAT | GE_VTYPE_COL_8888 | GE_VTYPE_NRM_FLOAT | GE_VTYPE_POS_FLOAT | (vertType & GE_VTYPE_IDX_MASK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Just to get something on the screen, we'll just not subdivide correctly.
|
|
||||||
void TransformDrawEngine::DrawBezier(int ucount, int vcount) {
|
|
||||||
if ((ucount - 1) % 3 != 0 || (vcount - 1) % 3 != 0)
|
|
||||||
ERROR_LOG_REPORT(G3D, "Unsupported bezier parameters ucount=%i, vcount=%i", ucount, vcount);
|
|
||||||
|
|
||||||
u16 *indices = new u16[ucount * vcount * 6];
|
|
||||||
|
|
||||||
static bool reported = false;
|
|
||||||
if (!reported) {
|
|
||||||
Reporting::ReportMessage("Unsupported bezier curve");
|
|
||||||
reported = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if (gstate.patchprimitive)
|
|
||||||
// Generate indices for a rectangular mesh.
|
|
||||||
int c = 0;
|
|
||||||
for (int y = 0; y < ucount; y++) {
|
|
||||||
for (int x = 0; x < vcount - 1; x++) {
|
|
||||||
indices[c++] = y * (vcount - 1)+ x;
|
|
||||||
indices[c++] = y * (vcount - 1) + x + 1;
|
|
||||||
indices[c++] = (y + 1) * (vcount - 1) + x + 1;
|
|
||||||
indices[c++] = (y + 1) * (vcount - 1) + x + 1;
|
|
||||||
indices[c++] = (y + 1) * (vcount - 1) + x;
|
|
||||||
indices[c++] = y * (vcount - 1) + x;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// We are free to use the "decoded" buffer here.
|
|
||||||
// Let's split it into two to get a second buffer, there's enough space.
|
|
||||||
u8 *decoded2 = decoded + 65536 * 24;
|
|
||||||
|
|
||||||
// Alright, now for the vertex data.
|
|
||||||
// For now, we will simply inject UVs.
|
|
||||||
|
|
||||||
float customUV[4 * 4 * 2];
|
|
||||||
for (int y = 0; y < 4; y++) {
|
|
||||||
for (int x = 0; x < 4; x++) {
|
|
||||||
customUV[(y * 4 + x) * 2 + 0] = (float)x/3.0f;
|
|
||||||
customUV[(y * 4 + x) * 2 + 1] = (float)y/3.0f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!vertTypeGetTexCoordMask(gstate.vertType)) {
|
|
||||||
VertexDecoder *dec = GetVertexDecoder(gstate.vertType);
|
|
||||||
dec->SetVertexType(gstate.vertType);
|
|
||||||
u32 newVertType = dec->InjectUVs(decoded2, Memory::GetPointer(gstate_c.vertexAddr), customUV, 16);
|
|
||||||
SubmitPrim(decoded2, &indices[0], GE_PRIM_TRIANGLES, c, newVertType, GE_VTYPE_IDX_16BIT, 0);
|
|
||||||
} else {
|
|
||||||
SubmitPrim(Memory::GetPointer(gstate_c.vertexAddr), &indices[0], GE_PRIM_TRIANGLES, c, gstate.vertType, GE_VTYPE_IDX_16BIT, 0);
|
|
||||||
}
|
|
||||||
Flush(); // as our vertex storage here is temporary, it will only survive one draw.
|
|
||||||
|
|
||||||
delete [] indices;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Spline implementation copied and modified from neobrain's softgpu (orphis code?)
|
|
||||||
|
|
||||||
#define START_OPEN_U 1
|
#define START_OPEN_U 1
|
||||||
#define END_OPEN_U 2
|
#define END_OPEN_U 2
|
||||||
#define START_OPEN_V 4
|
#define START_OPEN_V 4
|
||||||
#define END_OPEN_V 8
|
#define END_OPEN_V 8
|
||||||
|
|
||||||
|
static float lerp(float a, float b, float x) {
|
||||||
|
return a + x * (b - a);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lerpColor(u8 a[4], u8 b[4], float x, u8 out[4]) {
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
out[i] = (float)a[i] + x * ((float)b[i] - (float)a[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// We decode all vertices into a common format for easy interpolation and stuff.
|
// We decode all vertices into a common format for easy interpolation and stuff.
|
||||||
// Not fast but can be optimized later.
|
// Not fast but can be optimized later.
|
||||||
struct HWSplinePatch {
|
struct HWSplinePatch {
|
||||||
SimpleVertex *points[16];
|
SimpleVertex *points[16];
|
||||||
int type;
|
int type;
|
||||||
|
|
||||||
// We need to generate both UVs and normals later...
|
|
||||||
|
|
||||||
// These are used to generate UVs.
|
// These are used to generate UVs.
|
||||||
int u_index, v_index;
|
int u_index, v_index;
|
||||||
|
|
||||||
|
// Interpolate colors between control points (bilinear, should be good enough).
|
||||||
|
void sampleColor(float u, float v, u8 color[4]) const {
|
||||||
|
u *= 3.0f;
|
||||||
|
v *= 3.0f;
|
||||||
|
int iu = (int)floorf(u);
|
||||||
|
int iv = (int)floorf(v);
|
||||||
|
int iu2 = iu + 1;
|
||||||
|
int iv2 = iv + 1;
|
||||||
|
float fracU = u - iu;
|
||||||
|
float fracV = v - iv;
|
||||||
|
if (iu2 > 3) iu2 = 3;
|
||||||
|
if (iv2 > 3) iv2 = 3;
|
||||||
|
|
||||||
|
int tl = iu + 4 * iv;
|
||||||
|
int tr = iu2 + 4 * iv;
|
||||||
|
int bl = iu + 4 * iv2;
|
||||||
|
int br = iu2 + 4 * iv2;
|
||||||
|
|
||||||
|
u8 upperColor[4], lowerColor[4];
|
||||||
|
lerpColor(points[tl]->color, points[tr]->color, fracU, upperColor);
|
||||||
|
lerpColor(points[bl]->color, points[br]->color, fracU, lowerColor);
|
||||||
|
lerpColor(upperColor, lowerColor, fracV, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sampleTexUV(float u, float v, float &tu, float &tv) const {
|
||||||
|
u *= 3.0f;
|
||||||
|
v *= 3.0f;
|
||||||
|
int iu = (int)floorf(u);
|
||||||
|
int iv = (int)floorf(v);
|
||||||
|
int iu2 = iu + 1;
|
||||||
|
int iv2 = iv + 1;
|
||||||
|
float fracU = u - iu;
|
||||||
|
float fracV = v - iv;
|
||||||
|
if (iu2 > 3) iu2 = 3;
|
||||||
|
if (iv2 > 3) iv2 = 3;
|
||||||
|
|
||||||
|
int tl = iu + 4 * iv;
|
||||||
|
int tr = iu2 + 4 * iv;
|
||||||
|
int bl = iu + 4 * iv2;
|
||||||
|
int br = iu2 + 4 * iv2;
|
||||||
|
|
||||||
|
float upperTU = lerp(points[tl]->uv[0], points[tr]->uv[0], fracU);
|
||||||
|
float upperTV = lerp(points[tl]->uv[1], points[tr]->uv[1], fracU);
|
||||||
|
float lowerTU = lerp(points[bl]->uv[0], points[br]->uv[0], fracU);
|
||||||
|
float lowerTV = lerp(points[bl]->uv[1], points[br]->uv[1], fracU);
|
||||||
|
tu = lerp(upperTU, lowerTU, fracV);
|
||||||
|
tv = lerp(upperTV, lowerTV, fracV);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static void CopyTriangle(u8 *&dest, SimpleVertex *v1, SimpleVertex *v2, SimpleVertex* v3) {
|
static void CopyTriangle(u8 *&dest, SimpleVertex *v1, SimpleVertex *v2, SimpleVertex* v3) {
|
||||||
|
@ -217,15 +215,39 @@ static void CopyTriangle(u8 *&dest, SimpleVertex *v1, SimpleVertex *v2, SimpleVe
|
||||||
dest += vertexSize;
|
dest += vertexSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#undef b2
|
||||||
|
|
||||||
|
// Bernstein basis functions
|
||||||
|
inline float bern0(float x) { return (1 - x) * (1 - x) * (1 - x); }
|
||||||
|
inline float bern1(float x) { return 3 * x * (1 - x) * (1 - x); }
|
||||||
|
inline float bern2(float x) { return 3 * x * x * (1 - x); }
|
||||||
|
inline float bern3(float x) { return x * x * x; }
|
||||||
|
|
||||||
|
// Not sure yet if these have any use
|
||||||
|
inline float bern0deriv(float x) { return -3 * (x - 1) * (x - 1); }
|
||||||
|
inline float bern1deriv(float x) { return 9 * x * x - 12 * x + 3; }
|
||||||
|
inline float bern2deriv(float x) { return 3 * (2 - 3 * x) * x; }
|
||||||
|
inline float bern3deriv(float x) { return 3 * x * x; }
|
||||||
|
|
||||||
|
|
||||||
// http://en.wikipedia.org/wiki/Bernstein_polynomial
|
// http://en.wikipedia.org/wiki/Bernstein_polynomial
|
||||||
Vec3f Bernstein3D(const Vec3f p0, const Vec3f p1, const Vec3f p2, const Vec3f p3, float u) {
|
Vec3f Bernstein3D(const Vec3f p0, const Vec3f p1, const Vec3f p2, const Vec3f p3, float x) {
|
||||||
return p0 * (1.0f - u*u*u) + p1 * (3 * u * (1 - u) * (1 - u)) + p2 * (3 * u * u * (1 - u)) + p3 * u * u * u;
|
return p0 * bern0(x) + p1 * bern1(x) + p2 * bern2(x) + p3 * bern3(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Vec3f Bernstein3DDerivative(const Vec3f p0, const Vec3f p1, const Vec3f p2, const Vec3f p3, float x) {
|
||||||
|
return p0 * bern0deriv(x) + p1 * bern1deriv(x) + p2 * bern2deriv(x) + p3 * bern3deriv(x);
|
||||||
|
}
|
||||||
|
|
||||||
void TesselatePatch(u8 *&dest, int &count, const HWSplinePatch &patch, u32 origVertType) {
|
void TesselatePatch(u8 *&dest, int &count, const HWSplinePatch &patch, u32 origVertType) {
|
||||||
if (true) {
|
const float third = 1.0f / 3.0f;
|
||||||
// TODO: Should do actual patch subdivision instead of just drawing the control points!
|
|
||||||
|
bool realTesselation = false;
|
||||||
|
|
||||||
|
if (!realTesselation) {
|
||||||
|
// Fast and easy way - just draw the control points, generate some very basic normal vector subsitutes.
|
||||||
|
// Very inaccurate though but okay for Loco Roco. Maybe should keep it as an option.
|
||||||
|
|
||||||
const int tile_min_u = (patch.type & START_OPEN_U) ? 0 : 1;
|
const int tile_min_u = (patch.type & START_OPEN_U) ? 0 : 1;
|
||||||
const int tile_min_v = (patch.type & START_OPEN_V) ? 0 : 1;
|
const int tile_min_v = (patch.type & START_OPEN_V) ? 0 : 1;
|
||||||
const int tile_max_u = (patch.type & END_OPEN_U) ? 3 : 2;
|
const int tile_max_u = (patch.type & END_OPEN_U) ? 3 : 2;
|
||||||
|
@ -234,8 +256,6 @@ void TesselatePatch(u8 *&dest, int &count, const HWSplinePatch &patch, u32 origV
|
||||||
float u_base = patch.u_index / 3.0f;
|
float u_base = patch.u_index / 3.0f;
|
||||||
float v_base = patch.v_index / 3.0f;
|
float v_base = patch.v_index / 3.0f;
|
||||||
|
|
||||||
const float third = 1.0f / 3.0f;
|
|
||||||
|
|
||||||
for (int tile_u = tile_min_u; tile_u < tile_max_u; ++tile_u) {
|
for (int tile_u = tile_min_u; tile_u < tile_max_u; ++tile_u) {
|
||||||
for (int tile_v = tile_min_v; tile_v < tile_max_v; ++tile_v) {
|
for (int tile_v = tile_min_v; tile_v < tile_max_v; ++tile_v) {
|
||||||
int point_index = tile_u + tile_v * 4;
|
int point_index = tile_u + tile_v * 4;
|
||||||
|
@ -278,53 +298,91 @@ void TesselatePatch(u8 *&dest, int &count, const HWSplinePatch &patch, u32 origV
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// TODO: This doesn't work yet, hence it's the else in an "if (true)".
|
// Full tesselation of spline patches.
|
||||||
|
// TODO: This still has serious bugs, for example in Loco Roco, and there are gaps between patches for unknown reasons.
|
||||||
|
|
||||||
int tess_u = gstate.getPatchDivisionU();
|
int tess_u = gstate.getPatchDivisionU();
|
||||||
int tess_v = gstate.getPatchDivisionV();
|
int tess_v = gstate.getPatchDivisionV();
|
||||||
|
|
||||||
const int tile_min_u = (patch.type & START_OPEN_U) ? 0 : tess_u / 3;
|
const int tile_min_u = (patch.type & START_OPEN_U) ? 0 : tess_u / 3;
|
||||||
const int tile_min_v = (patch.type & START_OPEN_V) ? 0 : tess_v / 3;
|
const int tile_min_v = (patch.type & START_OPEN_V) ? 0 : tess_v / 3;
|
||||||
const int tile_max_u = (patch.type & END_OPEN_U) ? tess_u + 1 : tess_u * 2 / 3;
|
const int tile_max_u = (patch.type & END_OPEN_U) ? tess_u : (tess_u + 0) * 2 / 3;
|
||||||
const int tile_max_v = (patch.type & END_OPEN_V) ? tess_v + 1: tess_v * 2 / 3;
|
const int tile_max_v = (patch.type & END_OPEN_V) ? tess_v : (tess_v + 0) * 2 / 3;
|
||||||
|
|
||||||
// First compute all the positions and put them in an array
|
// First compute all the vertices and put them in an array
|
||||||
Vec3f *positions = new Vec3f[(tess_u + 1) * (tess_v) + 1];
|
SimpleVertex *vertices = new SimpleVertex[(tess_u + 1) * (tess_v + 1)];
|
||||||
|
|
||||||
|
bool computeNormals = gstate.isLightingEnabled();
|
||||||
for (int tile_v = 0; tile_v < tess_v + 1; ++tile_v) {
|
for (int tile_v = 0; tile_v < tess_v + 1; ++tile_v) {
|
||||||
for (int tile_u = 0; tile_u < tess_u + 1; ++tile_u) {
|
for (int tile_u = 0; tile_u < tess_u + 1; ++tile_u) {
|
||||||
float u = ((float)tile_u / (float)tess_u);
|
float u = ((float)tile_u / (float)tess_u);
|
||||||
float v = ((float)tile_v / (float)tess_v);
|
float v = ((float)tile_v / (float)tess_v);
|
||||||
|
float bu = u;
|
||||||
|
float bv = v;
|
||||||
|
|
||||||
// It must be possible to do some zany iterative solution instead of fully evaluating at every point.
|
// TODO: Should be able to precompute the four curves per U, then just Bernstein per V. Will benefit large tesselation factors.
|
||||||
Vec3f pos1 = Bernstein3D(patch.points[0]->pos, patch.points[1]->pos, patch.points[2]->pos, patch.points[3]->pos, u);
|
Vec3f pos1 = Bernstein3D(patch.points[0]->pos, patch.points[1]->pos, patch.points[2]->pos, patch.points[3]->pos, bu);
|
||||||
Vec3f pos2 = Bernstein3D(patch.points[4]->pos, patch.points[5]->pos, patch.points[6]->pos, patch.points[7]->pos, u);
|
Vec3f pos2 = Bernstein3D(patch.points[4]->pos, patch.points[5]->pos, patch.points[6]->pos, patch.points[7]->pos, bu);
|
||||||
Vec3f pos3 = Bernstein3D(patch.points[8]->pos, patch.points[9]->pos, patch.points[10]->pos, patch.points[11]->pos, u);
|
Vec3f pos3 = Bernstein3D(patch.points[8]->pos, patch.points[9]->pos, patch.points[10]->pos, patch.points[11]->pos, bu);
|
||||||
Vec3f pos4 = Bernstein3D(patch.points[12]->pos, patch.points[13]->pos, patch.points[14]->pos, patch.points[15]->pos, u);
|
Vec3f pos4 = Bernstein3D(patch.points[12]->pos, patch.points[13]->pos, patch.points[14]->pos, patch.points[15]->pos, bu);
|
||||||
|
|
||||||
positions[tile_v * (tess_u + 1)] = Bernstein3D(pos1, pos2, pos3, pos4, v);
|
SimpleVertex &vert = vertices[tile_v * (tess_u + 1) + tile_u];
|
||||||
|
|
||||||
|
if (computeNormals) {
|
||||||
|
Vec3f derivU1 = Bernstein3DDerivative(patch.points[0]->pos, patch.points[1]->pos, patch.points[2]->pos, patch.points[3]->pos, bu);
|
||||||
|
Vec3f derivU2 = Bernstein3DDerivative(patch.points[4]->pos, patch.points[5]->pos, patch.points[6]->pos, patch.points[7]->pos, bu);
|
||||||
|
Vec3f derivU3 = Bernstein3DDerivative(patch.points[8]->pos, patch.points[9]->pos, patch.points[10]->pos, patch.points[11]->pos, bu);
|
||||||
|
Vec3f derivU4 = Bernstein3DDerivative(patch.points[12]->pos, patch.points[13]->pos, patch.points[14]->pos, patch.points[15]->pos, bu);
|
||||||
|
Vec3f derivU = Bernstein3D(derivU1, derivU2, derivU3, derivU4, bv);
|
||||||
|
Vec3f derivV = Bernstein3DDerivative(pos1, pos2, pos3, pos4, bv);
|
||||||
|
|
||||||
|
// TODO: Interpolate normals instead of generating them, if available?
|
||||||
|
vert.nrm = Cross(derivU, derivV).Normalized(); //.SetZero();
|
||||||
|
if (gstate.patchfacing & 1)
|
||||||
|
vert.nrm *= -1.0f;
|
||||||
|
} else {
|
||||||
|
vert.nrm.SetZero();
|
||||||
|
}
|
||||||
|
|
||||||
|
vert.pos = Bernstein3D(pos1, pos2, pos3, pos4, bv);
|
||||||
|
|
||||||
|
if ((origVertType & GE_VTYPE_TC_MASK) == 0) {
|
||||||
|
// Generate texcoord
|
||||||
|
vert.uv[0] = u + patch.u_index * third;
|
||||||
|
vert.uv[1] = v + patch.v_index * third;
|
||||||
|
} else {
|
||||||
|
// Sample UV from control points
|
||||||
|
patch.sampleTexUV(u, v, vert.uv[0], vert.uv[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (origVertType & GE_VTYPE_COL_MASK) {
|
||||||
|
patch.sampleColor(u, v, vert.color);
|
||||||
|
} else {
|
||||||
|
memcpy(vert.color, patch.points[0]->color, 4);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// Tesselate. TODO: Use indices so we only need to emit 4 vertices per pair of triangles instead of six.
|
||||||
for (int tile_v = tile_min_v; tile_v < tile_max_v; ++tile_v) {
|
for (int tile_v = tile_min_v; tile_v < tile_max_v; ++tile_v) {
|
||||||
for (int tile_u = tile_min_u; tile_u < tile_max_u; ++tile_u) {
|
for (int tile_u = tile_min_u; tile_u < tile_max_u; ++tile_u) {
|
||||||
Vec3f pos = Bernstein3D(patch.)
|
float u = ((float)tile_u / (float)tess_u);
|
||||||
|
float v = ((float)tile_v / (float)tess_v);
|
||||||
|
|
||||||
|
SimpleVertex *v0 = &vertices[tile_v * (tess_u + 1) + tile_u];
|
||||||
int point_index = tile_u + tile_v*4;
|
SimpleVertex *v1 = &vertices[tile_v * (tess_u + 1) + tile_u + 1];
|
||||||
|
SimpleVertex *v2 = &vertices[(tile_v + 1) * (tess_u + 1) + tile_u];
|
||||||
SimpleVertex v0 = patch.points[point_index];
|
SimpleVertex *v3 = &vertices[(tile_v + 1) * (tess_u + 1) + tile_u + 1];
|
||||||
SimpleVertex v1 = patch.points[point_index+1];
|
|
||||||
SimpleVertex v2 = patch.points[point_index+4];
|
|
||||||
SimpleVertex v3 = patch.points[point_index+5];
|
|
||||||
|
|
||||||
CopyTriangle(dest, v0, v2, v1);
|
CopyTriangle(dest, v0, v2, v1);
|
||||||
|
CopyTriangle(dest, v1, v2, v3);
|
||||||
count += 6;
|
count += 6;
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
delete [] vertices;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void TransformDrawEngine::SubmitSpline(void* control_points, void* indices, int count_u, int count_v, int type_u, int type_v, GEPatchPrimType prim_type, u32 vertType) {
|
void TransformDrawEngine::SubmitSpline(void* control_points, void* indices, int count_u, int count_v, int type_u, int type_v, GEPatchPrimType prim_type, u32 vertType) {
|
||||||
Flush();
|
Flush();
|
||||||
|
@ -365,7 +423,6 @@ void TransformDrawEngine::SubmitSpline(void* control_points, void* indices, int
|
||||||
for (int patch_u = 0; patch_u < num_patches_u; ++patch_u) {
|
for (int patch_u = 0; patch_u < num_patches_u; ++patch_u) {
|
||||||
for (int patch_v = 0; patch_v < num_patches_v; ++patch_v) {
|
for (int patch_v = 0; patch_v < num_patches_v; ++patch_v) {
|
||||||
HWSplinePatch& patch = patches[patch_u + patch_v * num_patches_u];
|
HWSplinePatch& patch = patches[patch_u + patch_v * num_patches_u];
|
||||||
|
|
||||||
for (int point = 0; point < 16; ++point) {
|
for (int point = 0; point < 16; ++point) {
|
||||||
int idx = (patch_u + point%4) + (patch_v + point/4) * count_u;
|
int idx = (patch_u + point%4) + (patch_v + point/4) * count_u;
|
||||||
if (indices)
|
if (indices)
|
||||||
|
@ -378,6 +435,8 @@ void TransformDrawEngine::SubmitSpline(void* control_points, void* indices, int
|
||||||
if (patch_v != 0) patch.type &= ~START_OPEN_V;
|
if (patch_v != 0) patch.type &= ~START_OPEN_V;
|
||||||
if (patch_u != num_patches_u-1) patch.type &= ~END_OPEN_U;
|
if (patch_u != num_patches_u-1) patch.type &= ~END_OPEN_U;
|
||||||
if (patch_v != num_patches_v-1) patch.type &= ~END_OPEN_V;
|
if (patch_v != num_patches_v-1) patch.type &= ~END_OPEN_V;
|
||||||
|
patch.u_index = patch_u;
|
||||||
|
patch.v_index = patch_v;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue