class
SplineOpenGLFrame (pyopengltk.win32.OpenGLFrame ):
A tkinter OpenGLFrame
with shaders to display a Spline
.
SplineOpenGLFrame ( * args , eye = ( 0.0 , 0.0 , 3.0 ) , center = ( 0.0 , 0.0 , 0.0 ) , up = ( 0.0 , 1.0 , 0.0 ) , draw_func = None , ** kw )
Construct a frame widget with the parent MASTER.
Valid resource names: background, bd, bg, borderwidth, class,
colormap, container, cursor, height, highlightbackground,
highlightcolor, highlightthickness, relief, takefocus, visual, width.
ROTATE =
1
Default view mode in which dragging the left mouse rotates the view.
PAN =
2
View mode in which dragging the left mouse pans the view.
FLY =
3
View mode in which dragging the left mouse flies toward the mouse position.
MsPerFrame =
50
Milliseconds per frame when animating or flying.
maxOrder =
9
Maximum order for drawable splines.
maxKnots =
1024
Maximum number of 2D knots for drawable splines (order[0] + nCoef[0] + order[1] + nCoef[1] + 4, includes 4 header values).
maxCoefficients =
16384
Maximum number of 2D coefficients for drawable splines (nCoef[0] * nCoef[1], textures must support this width).
HULL =
1
Option to draw the convex hull of the spline (the coefficients). Off by default.
SHADED =
2
Option to draw the spline shaded (only useful for nInd >= 2). On by default.
BOUNDARY =
4
Option to draw the boundary of the spline in the line color (only useful for nInd >= 2). On by default.
ISOPARMS =
8
Option to draw the lines of constant knot values of the spline in the line color (only useful for nInd >= 2). Off by default.
computeBSplineCode =
'\n void ComputeBSpline(in int offset, in int order, in int n, in int knot, in float u, \n out float uBSpline[{maxOrder}], out float duBSpline[{maxOrder}])\n {{\n int degree = 1;\n\n for (int i = 0; i < {maxOrder}; i++)\n {{\n uBSpline[i] = 0.0;\n duBSpline[i] = 0.0;\n }}\n uBSpline[order-1] = 1.0;\n\n while (degree < order - 1)\n {{\n int b = order - degree;\n for (int i = knot - degree; i < knot; i++)\n {{\n float knotValue = texelFetch(uKnots, offset + i).x; // knots[i]\n float alpha = (u - knotValue) / (texelFetch(uKnots, offset + i + degree).x - knotValue); // (u - knots[i]) / (knots[i+degree] - knots[i]);\n uBSpline[b-1] += (1.0 - alpha) * uBSpline[b];\n uBSpline[b] *= alpha;\n b++;\n }}\n degree++;\n }}\n if (degree < order)\n {{\n int b = order - degree;\n for (int i = knot - degree; i < knot; i++)\n {{\n float knotValue = texelFetch(uKnots, offset + i).x; // knots[i]\n float gap = texelFetch(uKnots, offset + i + degree).x - knotValue; // knots[i+degree] - knots[i]\n float alpha = degree / gap;\n duBSpline[b-1] += -alpha * uBSpline[b];\n duBSpline[b] = alpha * uBSpline[b];\n\n alpha = (u - knotValue) / gap; // (u - knots[i]) / gap;\n uBSpline[b-1] += (1.0 - alpha) * uBSpline[b];\n uBSpline[b] *= alpha;\n b++;\n }}\n }}\n }}\n '
computeCurveSamplesCode =
"\n void ComputeCurveSamples(in int maxSamples, out float uSamples)\n {{\n float sampleRate = 0.0;\n if (outData.uInterval > 0.0)\n {{\n float minRate = 1.0 / outData.uInterval;\n if (outData.uOrder < 3)\n {{\n // It's a line or point, so just do the minimum sample.\n sampleRate = minRate;\n }}\n else\n {{\n int i = outData.uKnot - outData.uOrder;\n int coefficientOffset = i;\n vec3 coefficient0 = texelFetch(uXYZCoefs, coefficientOffset{lod}).xyz;\n coefficientOffset++;\n vec3 coefficient1 = texelFetch(uXYZCoefs, coefficientOffset{lod}).xyz;\n float gap = texelFetch(uKnots, header + i+outData.uOrder).x - texelFetch(uKnots, header + i+1).x; // uKnots[i+uOrder] - uKnots[i+1]\n vec3 dPoint0 = ((outData.uOrder - 1) / gap) * (coefficient1 - coefficient0);\n while (i < outData.uKnot-2)\n {{\n coefficientOffset++;\n vec3 coefficient2 = texelFetch(uXYZCoefs, coefficientOffset{lod}).xyz;\n gap = texelFetch(uKnots, header + i+1+outData.uOrder).x - texelFetch(uKnots, header + i+2).x; // uKnots[i+1+uOrder] - uKnots[i+2]\n vec3 dPoint1 = ((outData.uOrder - 1) / gap) * (coefficient2 - coefficient1);\n gap = texelFetch(uKnots, header + i+outData.uOrder).x - texelFetch(uKnots, header + i+2).x; // uKnots[i+uOrder] - uKnots[i+2]\n vec3 d2Point = ((outData.uOrder - 2) / gap) * (dPoint1 - dPoint0);\n\n sampleRate = max(sampleRate, ComputeSampleRate(coefficient0, dPoint0, d2Point, minRate));\n sampleRate = max(sampleRate, ComputeSampleRate(coefficient1, dPoint0, d2Point, minRate));\n sampleRate = max(sampleRate, ComputeSampleRate(coefficient1, dPoint1, d2Point, minRate));\n sampleRate = max(sampleRate, ComputeSampleRate(coefficient2, dPoint1, d2Point, minRate));\n\n coefficient0 = coefficient1;\n coefficient1 = coefficient2;\n dPoint0 = dPoint1;\n i++;\n }}\n }}\n }}\n uSamples = min(floor(0.5 + outData.uInterval * sampleRate), maxSamples);\n }}\n "
curveTEShaderCode =
'\n #version 410 core\n\n layout (isolines) in;\n\n const int header = 2;\n\n patch in SplineInfo\n {{\n int uOrder;\n int uN;\n int uKnot;\n float u;\n float uInterval;\n }} inData;\n\n uniform mat4 uProjectionMatrix;\n uniform samplerBuffer uKnots;\n uniform sampler1D uXYZCoefs;\n\n {computeBSplineCode}\n\n void main()\n {{\n float uBSpline[{maxOrder}];\n float duBSpline[{maxOrder}];\n ComputeBSpline(header, inData.uOrder, inData.uN, inData.uKnot,\n inData.u + gl_TessCoord.x * inData.uInterval, \n uBSpline, duBSpline);\n \n vec4 point = vec4(0.0, 0.0, 0.0, 1.0);\n int i = inData.uKnot - inData.uOrder;\n for (int b = 0; b < inData.uOrder; b++) // loop from coefficient[uKnot-order] to coefficient[uKnot]\n {{\n point.xyz += uBSpline[b] * texelFetch(uXYZCoefs, i, 0).xyz;\n i++;\n }}\n\n gl_Position = uProjectionMatrix * point;\n }}\n '
curveGeometryShaderCode =
"\n #version 330 core\n\n layout( points ) in;\n layout( line_strip, max_vertices = 256 ) out;\n\n const int header = 2;\n\n in SplineInfo\n {{\n int uOrder;\n int uN;\n int uKnot;\n float u;\n float uInterval;\n }} inData[];\n\n uniform mat4 uProjectionMatrix;\n uniform vec3 uScreenScale;\n uniform vec4 uClipBounds;\n uniform samplerBuffer uKnots;\n uniform samplerBuffer uXYZCoefs;\n\n struct SplineInfoStruct\n {{\n int uOrder;\n int uN;\n int uKnot;\n float u;\n float uInterval;\n }} outData; // We don't output outData (too many components per vertex), but we do use it in ComputeCurveSamples.\n\n {computeSampleRateCode}\n\n {computeCurveSamplesCode}\n\n {computeBSplineCode}\n\n void main()\n {{\n float uSamples = 0.0;\n\n outData.uOrder = inData[0].uOrder;\n outData.uN = inData[0].uN;\n outData.uKnot = inData[0].uKnot;\n outData.u = inData[0].u;\n outData.uInterval = inData[0].uInterval;\n ComputeCurveSamples(gl_MaxGeometryOutputVertices - 1, uSamples);\n\n if (uSamples > 0.0)\n {{\n float uBSpline[{maxOrder}];\n float duBSpline[{maxOrder}];\n float u = outData.u;\n float deltaU = outData.uInterval / uSamples;\n int iOffset = outData.uKnot - outData.uOrder;\n\n for (int uSample = 0; uSample <= uSamples; uSample++)\n {{\n ComputeBSpline(header, outData.uOrder, outData.uN, outData.uKnot,\n u, uBSpline, duBSpline);\n \n vec4 point = vec4(0.0, 0.0, 0.0, 1.0);\n int i = iOffset;\n for (int b = 0; b < outData.uOrder; b++) // loop from coefficient[uKnot-order] to coefficient[uKnot]\n {{\n point.xyz += uBSpline[b] * texelFetch(uXYZCoefs, i).xyz;\n i++;\n }}\n\n gl_Position = uProjectionMatrix * point;\n EmitVertex();\n u += deltaU; \n }}\n EndPrimitive();\n }}\n }}\n "
surfaceVertexShaderCode =
'\n #version 410 core\n\n const int header = 4;\n \n attribute vec4 aParameters;\n\n uniform samplerBuffer uKnots;\n\n out SplineInfo\n {\n int uOrder, vOrder;\n int uN, vN;\n int uKnot, vKnot;\n float uFirst, vFirst;\n float uSpan, vSpan;\n float u, v;\n float uInterval, vInterval;\n } outData;\n\n void main()\n {\n outData.uOrder = int(texelFetch(uKnots, 0).x);\n outData.vOrder = int(texelFetch(uKnots, 1).x);\n outData.uN = int(texelFetch(uKnots, 2).x);\n outData.vN = int(texelFetch(uKnots, 3).x);\n int stride = outData.uN - outData.uOrder + 1;\n int strides = gl_InstanceID / stride;\n\n outData.uKnot = gl_InstanceID - stride * strides + outData.uOrder;\n outData.vKnot = strides + outData.vOrder;\n outData.uFirst = texelFetch(uKnots, header + outData.uOrder - 1).x; // uKnots[uOrder-1]\n outData.vFirst = texelFetch(uKnots, header + outData.uOrder + outData.uN + outData.vOrder - 1).x; // vKnots[vOrder-1]\n outData.uSpan = texelFetch(uKnots, header + outData.uN).x - outData.uFirst; // uKnots[uN] - uKnots[uOrder-1]\n outData.vSpan = texelFetch(uKnots, header + outData.uOrder + outData.uN + outData.vN).x - outData.vFirst; // vKnots[vN] - vKnots[vOrder-1]\n outData.u = texelFetch(uKnots, header + outData.uKnot - 1).x; // uKnots[uKnot-1]\n outData.v = texelFetch(uKnots, header + outData.uOrder + outData.uN + outData.vKnot - 1).x; // vKnots[vKnot-1]\n outData.uInterval = texelFetch(uKnots, header + outData.uKnot).x - outData.u; // uKnots[uKnot] - uKnots[uKnot-1]\n outData.vInterval = texelFetch(uKnots, header + outData.uOrder + outData.uN + outData.vKnot).x - outData.v; // vKnots[vKnot] - vKnots[vKnot-1]\n gl_Position = aParameters;\n }\n '
computeSurfaceSamplesCode =
"\n void ComputeSurfaceSamples(in int maxSamples, out float uSamples[3], out float vSamples[3])\n {{\n // Computes sample counts for u and v for the left side ([0]), middle ([1]), and right side ([2]).\n // The left side sample count matches the right side sample count for the previous knot.\n // The middle sample count is the number of samples between knots (same as ComputeCurveSamples).\n float sampleRate[3] = float[3](0.0, 0.0, 0.0);\n if (outData.uInterval > 0.0)\n {{\n float minRate = 1.0 / outData.uInterval;\n if (outData.uOrder < 3)\n {{\n // It's a plane or point, so just do the minimum sample.\n sampleRate = float[3](minRate, minRate, minRate);\n }}\n else\n {{\n float sampleRateLeft[{maxOrder}];\n float sampleRateRight[{maxOrder}];\n\n for (int k = 0; k < outData.uOrder; k++)\n {{\n sampleRateLeft[k] = 0.0;\n sampleRateRight[k] = 0.0;\n }}\n for (int j = outData.vKnot-outData.vOrder; j < outData.vKnot; j++)\n {{\n int i = max(outData.uKnot - 1 - outData.uOrder, 0);\n int iLimit = min(outData.uKnot - 1, outData.uN - 2);\n int coefficientOffset = outData.uN*j + i;\n vec3 coefficient0 = texelFetch(uXYZCoefs, coefficientOffset{lod}).xyz;\n coefficientOffset++;\n vec3 coefficient1 = texelFetch(uXYZCoefs, coefficientOffset{lod}).xyz;\n float gap = texelFetch(uKnots, header + i+outData.uOrder).x - texelFetch(uKnots, header + i+1).x; // uKnots[i+uOrder] - uKnots[i+1]\n vec3 dPoint0 = ((outData.uOrder - 1) / gap) * (coefficient1 - coefficient0);\n while (i < iLimit)\n {{\n coefficientOffset++;\n vec3 coefficient2 = texelFetch(uXYZCoefs, coefficientOffset{lod}).xyz;\n gap = texelFetch(uKnots, header + i+1+outData.uOrder).x - texelFetch(uKnots, header + i+2).x; // uKnots[i+1+uOrder] - uKnots[i+2]\n vec3 dPoint1 = ((outData.uOrder - 1) / gap) * (coefficient2 - coefficient1);\n gap = texelFetch(uKnots, header + i+outData.uOrder).x - texelFetch(uKnots, header + i+2).x; // uKnots[i+uOrder] - uKnots[i+2]\n vec3 d2Point = ((outData.uOrder - 2) / gap) * (dPoint1 - dPoint0);\n\n int k = i - outData.uKnot + 1 + outData.uOrder;\n sampleRateLeft[k] = max(sampleRateLeft[k], ComputeSampleRate(coefficient0, dPoint0, d2Point, minRate));\n sampleRateLeft[k] = max(sampleRateLeft[k], ComputeSampleRate(coefficient1, dPoint0, d2Point, minRate));\n sampleRateRight[k] = max(sampleRateRight[k], ComputeSampleRate(coefficient1, dPoint1, d2Point, minRate));\n sampleRateRight[k] = max(sampleRateRight[k], ComputeSampleRate(coefficient2, dPoint1, d2Point, minRate));\n\n coefficient0 = coefficient1;\n coefficient1 = coefficient2;\n dPoint0 = dPoint1;\n i++;\n }}\n }}\n for (int k = 1; k < outData.uOrder - 1; k++)\n {{\n sampleRate[0] = max(sampleRate[0], sampleRateRight[k-1]);\n sampleRate[0] = max(sampleRate[0], sampleRateLeft[k]);\n sampleRate[1] = max(sampleRate[1], sampleRateLeft[k]);\n sampleRate[1] = max(sampleRate[1], sampleRateRight[k]);\n sampleRate[2] = max(sampleRate[2], sampleRateRight[k]);\n sampleRate[2] = max(sampleRate[2], sampleRateLeft[k+1]);\n }}\n }}\n }}\n uSamples[0] = min(floor(0.5 + outData.uInterval * sampleRate[0]), maxSamples);\n uSamples[1] = min(floor(0.5 + outData.uInterval * sampleRate[1]), maxSamples);\n uSamples[2] = min(floor(0.5 + outData.uInterval * sampleRate[2]), maxSamples);\n\n sampleRate = float[3](0.0, 0.0, 0.0);\n if (outData.vInterval > 0.0)\n {{\n float minRate = 1.0 / outData.vInterval;\n if (outData.vOrder < 3)\n {{\n // It's a plane or point, so just do the minimum sample.\n sampleRate = float[3](minRate, minRate, minRate);\n }}\n else\n {{\n float sampleRateLeft[{maxOrder}];\n float sampleRateRight[{maxOrder}];\n\n for (int k = 0; k < outData.vOrder; k++)\n {{\n sampleRateLeft[k] = 0.0;\n sampleRateRight[k] = 0.0;\n }}\n for (int i = outData.uKnot-outData.uOrder; i < outData.uKnot; i++)\n {{\n int j = max(outData.vKnot - 1 - outData.vOrder, 0);\n int jLimit = min(outData.vKnot - 1, outData.vN - 2);\n int coefficientOffset = outData.uN*j + i;\n vec3 coefficient0 = texelFetch(uXYZCoefs, coefficientOffset{lod}).xyz;\n coefficientOffset += outData.uN;\n vec3 coefficient1 = texelFetch(uXYZCoefs, coefficientOffset{lod}).xyz;\n float gap = texelFetch(uKnots, header + outData.uOrder+outData.uN + j+outData.vOrder).x - texelFetch(uKnots, header + outData.uOrder+outData.uN + j+1).x; // vKnots[j+vOrder] - vKnots[j+1]\n vec3 dPoint0 = ((outData.vOrder - 1) / gap) * (coefficient1 - coefficient0);\n while (j < jLimit)\n {{\n coefficientOffset += outData.uN;\n vec3 coefficient2 = texelFetch(uXYZCoefs, coefficientOffset{lod}).xyz;\n gap = texelFetch(uKnots, header + outData.uOrder+outData.uN + j+1+outData.vOrder).x - texelFetch(uKnots, header + outData.uOrder+outData.uN + j+2).x; // vKnots[j+1+vOrder] - vKnots[j+2]\n vec3 dPoint1 = ((outData.vOrder - 1) / gap) * (coefficient2 - coefficient1);\n gap = texelFetch(uKnots, header + outData.uOrder+outData.uN + j+outData.vOrder).x - texelFetch(uKnots, header + outData.uOrder+outData.uN + j+2).x; // vKnots[j+vOrder] - vKnots[j+2]\n vec3 d2Point = ((outData.vOrder - 2) / gap) * (dPoint1 - dPoint0);\n\n int k = j - outData.vKnot + 1 + outData.vOrder;\n sampleRateLeft[k] = max(sampleRateLeft[k], ComputeSampleRate(coefficient0, dPoint0, d2Point, minRate));\n sampleRateLeft[k] = max(sampleRateLeft[k], ComputeSampleRate(coefficient1, dPoint0, d2Point, minRate));\n sampleRateRight[k] = max(sampleRateRight[k], ComputeSampleRate(coefficient1, dPoint1, d2Point, minRate));\n sampleRateRight[k] = max(sampleRateRight[k], ComputeSampleRate(coefficient2, dPoint1, d2Point, minRate));\n\n coefficient0 = coefficient1;\n coefficient1 = coefficient2;\n dPoint0 = dPoint1;\n j++;\n }}\n }}\n for (int k = 1; k < outData.vOrder - 1; k++)\n {{\n sampleRate[0] = max(sampleRate[0], sampleRateRight[k-1]);\n sampleRate[0] = max(sampleRate[0], sampleRateLeft[k]);\n sampleRate[1] = max(sampleRate[1], sampleRateLeft[k]);\n sampleRate[1] = max(sampleRate[1], sampleRateRight[k]);\n sampleRate[2] = max(sampleRate[2], sampleRateRight[k]);\n sampleRate[2] = max(sampleRate[2], sampleRateLeft[k+1]);\n }}\n }}\n }}\n vSamples[0] = min(floor(0.5 + outData.vInterval * sampleRate[0]), maxSamples);\n vSamples[1] = min(floor(0.5 + outData.vInterval * sampleRate[1]), maxSamples);\n vSamples[2] = min(floor(0.5 + outData.vInterval * sampleRate[2]), maxSamples);\n }}\n "
surfaceTCShaderCode =
'\n #version 410 core\n\n layout (vertices = 1) out;\n\n const int header = 4;\n\n in SplineInfo\n {{\n int uOrder, vOrder;\n int uN, vN;\n int uKnot, vKnot;\n float uFirst, vFirst;\n float uSpan, vSpan;\n float u, v;\n float uInterval, vInterval;\n }} inData[];\n\n uniform vec3 uScreenScale;\n uniform vec4 uClipBounds;\n uniform samplerBuffer uKnots;\n uniform sampler1D uXYZCoefs;\n\n patch out SplineInfo\n {{\n int uOrder, vOrder;\n int uN, vN;\n int uKnot, vKnot;\n float uFirst, vFirst;\n float uSpan, vSpan;\n float u, v;\n float uInterval, vInterval;\n }} outData;\n\n {computeSampleRateCode}\n\n {computeSurfaceSamplesCode}\n\n void main()\n {{\n outData = inData[gl_InvocationID];\n gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n\n float uSamples[3];\n float vSamples[3];\n ComputeSurfaceSamples(gl_MaxTessGenLevel, uSamples, vSamples);\n gl_TessLevelOuter[0] = vSamples[0] > 0.0 ? vSamples[0] : vSamples[1];\n gl_TessLevelOuter[1] = uSamples[0] > 0.0 ? uSamples[0] : uSamples[1];\n gl_TessLevelOuter[2] = vSamples[2] > 0.0 ? vSamples[2] : vSamples[1];\n gl_TessLevelOuter[3] = uSamples[2] > 0.0 ? uSamples[2] : uSamples[1];\n gl_TessLevelInner[0] = uSamples[1];\n gl_TessLevelInner[1] = vSamples[1];\n }}\n '
surfaceTEShaderCode =
'\n #version 410 core\n\n layout (quads) in;\n\n const int header = 4;\n\n patch in SplineInfo\n {{\n int uOrder, vOrder;\n int uN, vN;\n int uKnot, vKnot;\n float uFirst, vFirst;\n float uSpan, vSpan;\n float u, v;\n float uInterval, vInterval;\n }} inData;\n\n uniform mat4 uProjectionMatrix;\n uniform vec3 uScreenScale;\n uniform vec4 uFillColor;\n uniform samplerBuffer uKnots;\n uniform sampler1D uXYZCoefs;\n uniform samplerBuffer uColorCoefs;\n\n flat out SplineInfo\n {{\n int uOrder, vOrder;\n int uN, vN;\n int uKnot, vKnot;\n float uFirst, vFirst;\n float uSpan, vSpan;\n float u, v;\n float uInterval, vInterval;\n }} outData;\n out vec3 worldPosition;\n out vec3 splineColor;\n out vec3 normal;\n out vec2 parameters;\n out vec2 pixelPer;\n\n {computeBSplineCode}\n\n void main()\n {{\n float uBSpline[{maxOrder}];\n float duBSpline[{maxOrder}];\n parameters.x = inData.u + gl_TessCoord.x * inData.uInterval;\n ComputeBSpline(header, inData.uOrder, inData.uN, inData.uKnot, parameters.x, uBSpline, duBSpline);\n\n float vBSpline[{maxOrder}];\n float dvBSpline[{maxOrder}];\n parameters.y = inData.v + gl_TessCoord.y * inData.vInterval;\n ComputeBSpline(header + inData.uOrder+inData.uN, inData.vOrder, inData.vN, inData.vKnot, parameters.y, vBSpline, dvBSpline);\n\n {splineColorDeclarations}\n\n vec4 point = vec4(0.0, 0.0, 0.0, 1.0);\n vec3 duPoint = vec3(0.0, 0.0, 0.0);\n vec3 dvPoint = vec3(0.0, 0.0, 0.0);\n {initializeSplineColor}\n int j = (inData.vKnot - inData.vOrder) * inData.uN;\n for (int vB = 0; vB < inData.vOrder; vB++)\n {{\n int i = j + inData.uKnot - inData.uOrder;\n for (int uB = 0; uB < inData.uOrder; uB++)\n {{\n vec3 coefs = texelFetch(uXYZCoefs, i, 0).xyz;\n point.xyz += uBSpline[uB] * vBSpline[vB] * coefs;\n duPoint += duBSpline[uB] * vBSpline[vB] * coefs;\n dvPoint += uBSpline[uB] * dvBSpline[vB] * coefs;\n {computeSplineColor}\n i++;\n }}\n j += inData.uN;\n }}\n {postProcessSplineColor}\n\n outData = inData;\n\n worldPosition = point.xyz;\n normal = normalize(cross(duPoint, dvPoint));\n float zScale = 1.0 / (point.z * point.z);\n pixelPer.x = zScale * max(uScreenScale.x * abs(point.x * duPoint.z - duPoint.x * point.z), uScreenScale.y * abs(point.y * duPoint.z - duPoint.y * point.z));\n pixelPer.y = zScale * max(uScreenScale.x * abs(point.x * dvPoint.z - dvPoint.x * point.z), uScreenScale.y * abs(point.y * dvPoint.z - dvPoint.y * point.z));\n gl_Position = uProjectionMatrix * point;\n }}\n '
surfaceGeometryShaderCode =
"\n #version 330 core\n\n layout( points ) in;\n layout( triangle_strip, max_vertices = 256 ) out;\n\n const int header = 4;\n\n in SplineInfo\n {{\n int uOrder, vOrder;\n int uN, vN;\n int uKnot, vKnot;\n float uFirst, vFirst;\n float uSpan, vSpan;\n float u, v;\n float uInterval, vInterval;\n }} inData[];\n\n uniform mat4 uProjectionMatrix;\n uniform vec3 uScreenScale;\n uniform vec4 uClipBounds;\n uniform vec4 uFillColor;\n uniform vec3 uLightDirection;\n uniform samplerBuffer uKnots;\n uniform samplerBuffer uXYZCoefs;\n uniform samplerBuffer uColorCoefs;\n\n out vec3 splineColor; // We restrict our output to color to reduce the number of components per vertex.\n\n struct SplineInfoStruct\n {{\n int uOrder, vOrder;\n int uN, vN;\n int uKnot, vKnot;\n float uFirst, vFirst;\n float uSpan, vSpan;\n float u, v;\n float uInterval, vInterval;\n }} outData; // We don't output outData (too many components per vertex), but we do use it in ComputeSurfaceSamples.\n\n {computeSampleRateCode}\n\n {computeSurfaceSamplesCode}\n\n {computeBSplineCode}\n\n void main() \n {{\n float uFullSamples[3];\n float vFullSamples[3];\n\n outData.uOrder = inData[0].uOrder;\n outData.vOrder = inData[0].vOrder;\n outData.uN = inData[0].uN;\n outData.vN = inData[0].vN;\n outData.uKnot = inData[0].uKnot;\n outData.vKnot = inData[0].vKnot;\n outData.u = inData[0].u;\n outData.v = inData[0].v;\n outData.uInterval = inData[0].uInterval;\n outData.vInterval = inData[0].vInterval;\n int maxVertices = gl_MaxGeometryTotalOutputComponents / 7; // The number of output components per vertex is 7 = position.xyzw + splineColor.rgb\n ComputeSurfaceSamples(maxVertices, uFullSamples, vFullSamples);\n\n if (uFullSamples[1] > 0.0 && vFullSamples[1] > 0.0)\n {{\n float alpha = maxVertices / (2.0 * uFullSamples[1] * (vFullSamples[1] + 1.0));\n if (alpha < 1.0)\n {{\n alpha = sqrt(alpha);\n uFullSamples[1] = alpha * uFullSamples[1];\n vFullSamples[1] = alpha * (vFullSamples[1] + 1.0) - 1.0;\n }}\n int uSamples = int(uFullSamples[1]);\n int vSamples = int(vFullSamples[1]);\n\n {splineColorDeclarations}\n\n float uBSpline[{maxOrder}];\n float duBSpline[{maxOrder}];\n float uBSplineNext[{maxOrder}];\n float duBSplineNext[{maxOrder}];\n float vBSpline[{maxOrder}];\n float dvBSpline[{maxOrder}];\n float deltaU = outData.uInterval / uSamples;\n float deltaV = outData.vInterval / vSamples;\n float u = outData.u;\n ComputeBSpline(header, outData.uOrder, outData.uN, outData.uKnot, u, uBSpline, duBSpline);\n\n int jOffset = (outData.vKnot - outData.vOrder) * outData.uN;\n int iOffset = outData.uKnot - outData.uOrder;\n\n for (int uSample = 0; uSample < uSamples; uSample++)\n {{\n float uNext = u + deltaU;\n ComputeBSpline(header, outData.uOrder, outData.uN, outData.uKnot, uNext, uBSplineNext, duBSplineNext);\n \n float v = outData.v;\n for (int vSample = 0; vSample <= vSamples; vSample++)\n {{\n ComputeBSpline(header + outData.uOrder+outData.uN, outData.vOrder, outData.vN, outData.vKnot, v, vBSpline, dvBSpline);\n\n vec4 point = vec4(0.0, 0.0, 0.0, 1.0);\n vec3 duPoint = vec3(0.0, 0.0, 0.0);\n vec3 dvPoint = vec3(0.0, 0.0, 0.0);\n {initializeSplineColor}\n int j = jOffset;\n for (int vB = 0; vB < outData.vOrder; vB++)\n {{\n int i = j + iOffset;\n for (int uB = 0; uB < outData.uOrder; uB++)\n {{\n vec3 coefs = texelFetch(uXYZCoefs, i).xyz;\n point.xyz += uBSpline[uB] * vBSpline[vB] * coefs;\n duPoint += duBSpline[uB] * vBSpline[vB] * coefs;\n dvPoint += uBSpline[uB] * dvBSpline[vB] * coefs;\n {computeSplineColor}\n i++;\n }}\n j += outData.uN;\n }}\n {postProcessSplineColor}\n vec3 normal = normalize(cross(duPoint, dvPoint));\n float specular = pow(abs(dot(normal, normalize(uLightDirection + point.xyz / length(point)))), 25.0);\n splineColor = (0.3 + 0.5 * abs(dot(normal, uLightDirection)) + 0.2 * specular) * splineColor;\n gl_Position = uProjectionMatrix * point;\n EmitVertex();\n\n point = vec4(0.0, 0.0, 0.0, 1.0);\n duPoint = vec3(0.0, 0.0, 0.0);\n dvPoint = vec3(0.0, 0.0, 0.0);\n {initializeSplineColor}\n j = jOffset;\n for (int vB = 0; vB < outData.vOrder; vB++)\n {{\n int i = j + iOffset;\n for (int uB = 0; uB < outData.uOrder; uB++)\n {{\n vec3 coefs = texelFetch(uXYZCoefs, i).xyz;\n point.xyz += uBSplineNext[uB] * vBSpline[vB] * coefs;\n duPoint += duBSplineNext[uB] * vBSpline[vB] * coefs;\n dvPoint += uBSplineNext[uB] * dvBSpline[vB] * coefs;\n {computeSplineColor}\n i++;\n }}\n j += outData.uN;\n }}\n {postProcessSplineColor}\n normal = normalize(cross(duPoint, dvPoint));\n specular = pow(abs(dot(normal, normalize(uLightDirection + point.xyz / length(point)))), 25.0);\n splineColor = (0.3 + 0.5 * abs(dot(normal, uLightDirection)) + 0.2 * specular) * splineColor;\n gl_Position = uProjectionMatrix * point;\n EmitVertex();\n\n v += deltaV; \n }}\n EndPrimitive();\n u = uNext;\n uBSpline = uBSplineNext;\n duBSpline = duBSplineNext;\n }}\n }}\n }}\n "
surfaceFragmentShaderCode =
'\n #version 410 core\n \n flat in SplineInfo\n {\n int uOrder, vOrder;\n int uN, vN;\n int uKnot, vKnot;\n float uFirst, vFirst;\n float uSpan, vSpan;\n float u, v;\n float uInterval, vInterval;\n } inData;\n in vec3 worldPosition;\n in vec3 splineColor;\n in vec3 normal;\n in vec2 parameters;\n in vec2 pixelPer;\n\n uniform vec4 uFillColor;\n uniform vec4 uLineColor;\n uniform vec3 uLightDirection;\n uniform int uOptions;\n\n out vec4 color;\n \n void main()\n {\n float specular = pow(abs(dot(normal, normalize(uLightDirection + worldPosition / length(worldPosition)))), 25.0);\n bool line = (uOptions & (1 << 2)) > 0 && (pixelPer.x * (parameters.x - inData.uFirst) < 1.5 || pixelPer.x * (inData.uFirst + inData.uSpan - parameters.x) < 1.5);\n line = line || ((uOptions & (1 << 2)) > 0 && (pixelPer.y * (parameters.y - inData.vFirst) < 1.5 || pixelPer.y * (inData.vFirst + inData.vSpan - parameters.y) < 1.5));\n line = line || ((uOptions & (1 << 3)) > 0 && pixelPer.x * (parameters.x - inData.u) < 1.5);\n line = line || ((uOptions & (1 << 3)) > 0 && pixelPer.y * (parameters.y - inData.v) < 1.5);\n color = line ? uLineColor : ((uOptions & (1 << 1)) > 0 ? vec4(splineColor, uFillColor.a) : vec4(0.0, 0.0, 0.0, 0.0));\n color.rgb = (0.3 + 0.5 * abs(dot(normal, uLightDirection)) + 0.2 * specular) * color.rgb;\n if (color.a == 0.0)\n discard;\n }\n '
trimmedSurfaceFragmentShaderCode =
'\n #version 410 core\n \n flat in SplineInfo\n {\n int uOrder, vOrder;\n int uN, vN;\n int uKnot, vKnot;\n float uFirst, vFirst;\n float uSpan, vSpan;\n float u, v;\n float uInterval, vInterval;\n } inData;\n in vec3 worldPosition;\n in vec3 splineColor;\n in vec3 normal;\n in vec2 parameters;\n in vec2 pixelPer;\n\n uniform vec4 uFillColor;\n uniform vec4 uLineColor;\n uniform vec3 uLightDirection;\n uniform int uOptions;\n uniform sampler2D uTrimTextureMap;\n\n out vec4 color;\n \n void main()\n {\n \tvec2 tex = vec2((parameters.x - inData.uFirst) / inData.uSpan, (parameters.y - inData.vFirst) / inData.vSpan);\n float specular = pow(abs(dot(normal, normalize(uLightDirection + worldPosition / length(worldPosition)))), 25.0);\n bool line = (uOptions & (1 << 2)) > 0 && (pixelPer.x * (parameters.x - inData.uFirst) < 1.5 || pixelPer.x * (inData.uFirst + inData.uSpan - parameters.x) < 1.5);\n line = line || ((uOptions & (1 << 2)) > 0 && (pixelPer.y * (parameters.y - inData.vFirst) < 1.5 || pixelPer.y * (inData.vFirst + inData.vSpan - parameters.y) < 1.5));\n line = line || ((uOptions & (1 << 3)) > 0 && pixelPer.x * (parameters.x - inData.u) < 1.5);\n line = line || ((uOptions & (1 << 3)) > 0 && pixelPer.y * (parameters.y - inData.v) < 1.5);\n color = line ? uLineColor : ((uOptions & (1 << 1)) > 0 ? vec4(splineColor, uFillColor.a) : vec4(0.0, 0.0, 0.0, 0.0));\n color.rgb = (0.3 + 0.5 * abs(dot(normal, uLightDirection)) + 0.2 * specular) * color.rgb;\n if (color.a * texture(uTrimTextureMap, tex).r == 0.0)\n discard;\n }\n '
@staticmethod
def
compute_color_vector (r , g = None , b = None , a = None ):
Return an float32 array with the specified color.
Parameters
r (float
, int
or array-like of floats or ints):
The red value [0, 1] as a float, [0, 255] as an int, or the rgb or rgba value as floats or ints (default).
g (float
or int
):
The green value [0, 1] as a float or [0, 255] as an int.
b (float
or int
):
The blue value [0, 1] as a float or [0, 255] as an int.
a (float
, int
, or None):
The alpha value [0, 1] as a float or [0, 255] as an int. If None
then alpha is set to 1.
Returns
color (numpy.array
):
The specified color as an array of 4 float32 values between 0 and 1.
def
SetDefaultView (self , eye , center , up ):
Set the default view values used when resetting the view.
def
SetBackgroundColor (self , r , g = None , b = None , a = None ):
Set the background color for the frame.
Parameters
r (float
, int
or array-like of floats or ints):
The red value [0, 1] as a float, [0, 255] as an int, or the rgb or rgba value as floats or ints (default).
g (float
or int
):
The green value [0, 1] as a float or [0, 255] as an int.
b (float
or int
):
The blue value [0, 1] as a float or [0, 255] as an int.
a (float
, int
, or None):
The alpha value [0, 1] as a float or [0, 255] as an int. If None
then alpha is set to 1.
def
ResetView (self ):
Update the view position to default values.
def
initgl (self ):
Handle OpenGLFrame
initgl action. Calls CreateGLResources
and HandleScreenSizeUpdate
.
def
CreateGLResources (self ):
Create OpenGL resources upon creation of the frame and window recovery (un-minimize).
def
ResetBounds (self ):
Handle window size and/or clipping plane update (typically after a window resize).
def
redraw (self ):
Handle OpenGLFrame
redraw action. Updates view and draws spline list.
def
Update (self ):
Update the frame, typically after updating the spline list.
def
Reset (self ):
Reset the view and update the frame.
def
SetMode (self , mode ):
Set the view mode for the frame.
Parameters
mode (int
with the following values:):
def
SetScale (self , scale ):
Set anchor distance and/or flying speed (depending on mode).
Parameters
scale (float
):
Scale between 0 and 1.
def
SetAnimating (self , animating ):
def
MouseDown (self , event ):
def
MouseMove (self , event ):
def
MouseUp (self , event ):
def
MouseWheel (self , event ):
Handle mouse wheel event.
@staticmethod
def
make_drawable (spline ):
Ensure a Spline
can be drawn in a SplineOpenGLFrame
. Converts 1D splines into 3D drawable curves,
2D splines into drawable surfaces (y-axis hold amplitude), and 3D splines into drawable solids.
Spline surfaces and solids with more than 3 dependent variables will have their added dimensions rendered
as colors (up to 6 dependent variables are supported).
def
tessellate2DSolid (self , solid ):
Returns an array of triangles that tessellate the given 2D solid
@staticmethod
def
ConvertRGBToHSV (r , g , b , a ):
def
DrawSpline (self , spline , transform ):
Inherited Members
pyopengltk.win32.OpenGLFrame
tkCreateContext
tkMakeCurrent
tkSwapBuffers
pyopengltk.base.BaseOpenGLFrame
cb
context_created
tkMap
printContext
tkExpose
tkResize
tkinter.BaseWidget
widgetName
destroy
tkinter.Misc
deletecommand
tk_strictMotif
tk_bisque
tk_setPalette
wait_variable
waitvar
wait_window
wait_visibility
setvar
getvar
getint
getdouble
getboolean
focus_set
focus
focus_force
focus_get
focus_displayof
focus_lastfor
tk_focusFollowsMouse
tk_focusNext
tk_focusPrev
after
after_idle
after_cancel
bell
clipboard_get
clipboard_clear
clipboard_append
grab_current
grab_release
grab_set
grab_set_global
grab_status
option_add
option_clear
option_get
option_readfile
selection_clear
selection_get
selection_handle
selection_own
selection_own_get
send
lower
tkraise
lift
winfo_atom
winfo_atomname
winfo_cells
winfo_children
winfo_class
winfo_colormapfull
winfo_containing
winfo_depth
winfo_exists
winfo_fpixels
winfo_geometry
winfo_height
winfo_id
winfo_interps
winfo_ismapped
winfo_manager
winfo_name
winfo_parent
winfo_pathname
winfo_pixels
winfo_pointerx
winfo_pointerxy
winfo_pointery
winfo_reqheight
winfo_reqwidth
winfo_rgb
winfo_rootx
winfo_rooty
winfo_screen
winfo_screencells
winfo_screendepth
winfo_screenheight
winfo_screenmmheight
winfo_screenmmwidth
winfo_screenvisual
winfo_screenwidth
winfo_server
winfo_toplevel
winfo_viewable
winfo_visual
winfo_visualid
winfo_visualsavailable
winfo_vrootheight
winfo_vrootwidth
winfo_vrootx
winfo_vrooty
winfo_width
winfo_x
winfo_y
update
update_idletasks
bindtags
bind
unbind
bind_all
unbind_all
bind_class
unbind_class
mainloop
quit
nametowidget
register
configure
config
cget
keys
pack_propagate
propagate
pack_slaves
slaves
place_slaves
grid_anchor
anchor
grid_bbox
bbox
grid_columnconfigure
columnconfigure
grid_location
grid_propagate
grid_rowconfigure
rowconfigure
grid_size
size
grid_slaves
event_add
event_delete
event_generate
event_info
image_names
image_types
tkinter.Pack
pack_configure
pack_forget
forget
pack_info
info
pack
tkinter.Place
place_configure
place_forget
place_info
place
tkinter.Grid
grid_configure
grid_forget
grid_remove
grid_info
grid
location