A few days ago, I began to effectively analyze bezier curves, and I came across this method, developed by Charles Peter and Jim Blinn, which seemed very interesting. Be that as it may, after a lot of experiments with their algorithm, I just can't get it to display cubic curves. The squares are beautiful, no problem.
The only resources I have found so far are the following:
GPU Graphics 3 Chapter 25
Curvy blues
Independent graphics curve using graphics hardware
To quickly test testing, I do this in XNA. Basically, I transfer the coordinates of the texture with my vertices to the GPU, apply perspective transformation and use the formula specified in all the articles in the pixel shader to make the final result. Be that as it may, the problem (I think) is how I calculate the coordinates of the texture. Check this code:
public void Update() { float a1 = Vector3.Dot(p1, Vector3.Cross(p4, p3)); float a2 = Vector3.Dot(p2, Vector3.Cross(p1, p4)); float a3 = Vector3.Dot(p3, Vector3.Cross(p2, p2)); float d1 = a1 - 2 * a2 + 3 * a3; float d2 = -a2 + 3 * a3; float d3 = 3 * a3; float discr = d1 * d1 * (3 * d2 * d2 - 4 * d1 * d3); if (discr > 0) { Type = CurveTypes.Serpentine; float ls = 3 * d2 - (float)Math.Sqrt(9 * d2 * d2 - 12 * d1 * d3); float lt = 6 * d1; float ms = 3 * d2 + (float)Math.Sqrt(9 * d2 * d2 - 12 * d1 * d3); float mt = 6 * d1; TexCoord1 = new Vector3(ls * ms, (float)Math.Pow(ls, 3), (float)Math.Pow(ms, 3)); TexCoord2 = new Vector3((3 * ls * ms - ls * mt - lt * ms) / 3, ls * ls * (ls - lt), ms * ms * (ms - mt)); TexCoord3 = new Vector3((lt * (mt - 2 * ms) + ls * (3 * ms - 2 * mt)) / 3, (float)Math.Pow(lt - ls, 2) * ls, (float)Math.Pow(mt - ms, 2) * ms); TexCoord4 = new Vector3((lt - ls) * (mt - ms), -(float)Math.Pow(lt - ls, 3), -(float)Math.Pow(mt - ms, 3)); } else if (discr == 0) { Type = CurveTypes.Cusp; } else if (discr < 0) { Type = CurveTypes.Loop; } }
Sorry mess, this is just some test code. p1 ... p4 are the control points in world space, and TexCoord1 ... TexCoord4 are the corresponding coordinates of the texture. This is a replication of what the GPU Gems article says.
There are several issues here. First, when calculating a3, we use p2 for both parameters, which, of course, always leads to a (0,0,0) vector and takes the point product of this and p3 will always give us 0. This is pretty useless, so why should they mention this article?
This, of course, will make the wrong one wrong, and we wonβt even be able to determine what type of curve it has.
After working a little with this code, I decided to try to do exactly what they did in the paper Loop and Blinn. From this I get something like this:
public void Update() { Matrix m1 = new Matrix( p4.X, p4.Y, 1, 0, p3.X, p3.Y, 1, 0, p2.X, p2.Y, 1, 0, 0, 0, 0, 1); Matrix m2 = new Matrix( p4.X, p4.Y, 1, 0, p3.X, p3.Y, 1, 0, p1.X, p1.Y, 1, 0, 0, 0, 0, 1); Matrix m3 = new Matrix( p4.X, p4.Y, 1, 0, p2.X, p2.Y, 1, 0, p1.X, p1.Y, 1, 0, 0, 0, 0, 1); Matrix m4 = new Matrix( p3.X, p3.Y, 1, 0, p2.X, p2.Y, 1, 0, p1.X, p1.Y, 1, 0, 0, 0, 0, 1); float det1 = m1.Determinant(); float det2 = -m2.Determinant(); float det3 = m3.Determinant(); float det4 = -m4.Determinant(); float tet1 = det1 * det3 - det2 * det2; float tet2 = det2 * det3 - det1 * det4; float tet3 = det2 * det4 - det3 * det3; float discr = 4 * tet1 * tet3 - tet2 * tet2; if (discr > 0) { Type = CurveTypes.Serpentine; float ls = 2 * det2; float lt = det3 + (float)((1 / Math.Sqrt(3)) * Math.Sqrt(3 * det3 * det3 - 4 * det2 * det4)); float ms = 2 * det2; float mt = det3 - (float)((1 / Math.Sqrt(3)) * Math.Sqrt(3 * det3 * det3 - 4 * det2 * det4)); TexCoord1 = new Vector3(lt * mt, (float)Math.Pow(lt, 3), (float)Math.Pow(mt, 3)); TexCoord2 = new Vector3(-ms * lt - ls * mt, -3 * ls * lt * lt, -3 * ms * mt * mt); TexCoord3 = new Vector3(ls * ms, 3 * ls * ls * lt, 3 * ms * ms * mt); TexCoord4 = new Vector3(0, -ls * ls * ls, -ms * ms * ms); } else if (discr == 0) { Type = CurveTypes.Cusp; } else if (discr < 0) { Type = CurveTypes.Loop; } }
Guess what didn't work either. Be that as it may, now it seems that this is a little more correct. At least it has the right sign, and it is zero when the control points are positioned so as to form a point. However, I still get the same visual result, except that the curve disappears randomly (the pixel shader formula is always greater than zero) and returns after I moved the control point back to a large square shape. Here is the pixel shader code:
PixelToFrame PixelShader(VertexToPixel PSIn) { PixelToFrame Output = (PixelToFrame)0; if(pow(PSIn.TexCoords.x, 3) - PSIn.TexCoords.y * PSIn.TexCoords.z > 0) { Output.Color = float4(0,0,0,0.1); } else { Output.Color = float4(0,1,0,1); } return Output; }
Here's all the helpful information I can think of now. Does anyone know what is going on? Because I'm running from them.