bspy 4.0__py3-none-any.whl → 4.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- bspy/__init__.py +16 -3
- bspy/_spline_domain.py +101 -9
- bspy/_spline_evaluation.py +82 -17
- bspy/_spline_fitting.py +244 -114
- bspy/_spline_intersection.py +467 -156
- bspy/_spline_operations.py +70 -49
- bspy/hyperplane.py +540 -0
- bspy/manifold.py +334 -31
- bspy/solid.py +842 -0
- bspy/spline.py +350 -71
- bspy/splineOpenGLFrame.py +262 -14
- bspy/spline_block.py +343 -0
- bspy/viewer.py +134 -90
- {bspy-4.0.dist-info → bspy-4.2.dist-info}/METADATA +17 -6
- bspy-4.2.dist-info/RECORD +18 -0
- {bspy-4.0.dist-info → bspy-4.2.dist-info}/WHEEL +1 -1
- bspy-4.0.dist-info/RECORD +0 -15
- {bspy-4.0.dist-info → bspy-4.2.dist-info}/LICENSE +0 -0
- {bspy-4.0.dist-info → bspy-4.2.dist-info}/top_level.txt +0 -0
bspy/splineOpenGLFrame.py
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
from collections import namedtuple
|
|
1
2
|
import numpy as np
|
|
2
|
-
import tkinter as tk
|
|
3
3
|
from OpenGL.GL import *
|
|
4
|
+
from OpenGL.GLU import *
|
|
5
|
+
from bspy.manifold import Manifold
|
|
4
6
|
import OpenGL.GL.shaders as shaders
|
|
5
7
|
try:
|
|
6
8
|
from pyopengltk import OpenGLFrame
|
|
@@ -958,6 +960,48 @@ class SplineOpenGLFrame(OpenGLFrame):
|
|
|
958
960
|
discard;
|
|
959
961
|
}
|
|
960
962
|
"""
|
|
963
|
+
|
|
964
|
+
trimmedSurfaceFragmentShaderCode = """
|
|
965
|
+
#version 410 core
|
|
966
|
+
|
|
967
|
+
flat in SplineInfo
|
|
968
|
+
{
|
|
969
|
+
int uOrder, vOrder;
|
|
970
|
+
int uN, vN;
|
|
971
|
+
int uKnot, vKnot;
|
|
972
|
+
float uFirst, vFirst;
|
|
973
|
+
float uSpan, vSpan;
|
|
974
|
+
float u, v;
|
|
975
|
+
float uInterval, vInterval;
|
|
976
|
+
} inData;
|
|
977
|
+
in vec3 worldPosition;
|
|
978
|
+
in vec3 splineColor;
|
|
979
|
+
in vec3 normal;
|
|
980
|
+
in vec2 parameters;
|
|
981
|
+
in vec2 pixelPer;
|
|
982
|
+
|
|
983
|
+
uniform vec4 uFillColor;
|
|
984
|
+
uniform vec4 uLineColor;
|
|
985
|
+
uniform vec3 uLightDirection;
|
|
986
|
+
uniform int uOptions;
|
|
987
|
+
uniform sampler2D uTrimTextureMap;
|
|
988
|
+
|
|
989
|
+
out vec4 color;
|
|
990
|
+
|
|
991
|
+
void main()
|
|
992
|
+
{
|
|
993
|
+
vec2 tex = vec2((parameters.x - inData.uFirst) / inData.uSpan, (parameters.y - inData.vFirst) / inData.vSpan);
|
|
994
|
+
float specular = pow(abs(dot(normal, normalize(uLightDirection + worldPosition / length(worldPosition)))), 25.0);
|
|
995
|
+
bool line = (uOptions & (1 << 2)) > 0 && (pixelPer.x * (parameters.x - inData.uFirst) < 1.5 || pixelPer.x * (inData.uFirst + inData.uSpan - parameters.x) < 1.5);
|
|
996
|
+
line = line || ((uOptions & (1 << 2)) > 0 && (pixelPer.y * (parameters.y - inData.vFirst) < 1.5 || pixelPer.y * (inData.vFirst + inData.vSpan - parameters.y) < 1.5));
|
|
997
|
+
line = line || ((uOptions & (1 << 3)) > 0 && pixelPer.x * (parameters.x - inData.u) < 1.5);
|
|
998
|
+
line = line || ((uOptions & (1 << 3)) > 0 && pixelPer.y * (parameters.y - inData.v) < 1.5);
|
|
999
|
+
color = line ? uLineColor : ((uOptions & (1 << 1)) > 0 ? vec4(splineColor, uFillColor.a) : vec4(0.0, 0.0, 0.0, 0.0));
|
|
1000
|
+
color.rgb = (0.3 + 0.5 * abs(dot(normal, uLightDirection)) + 0.2 * specular) * color.rgb;
|
|
1001
|
+
if (color.a * texture(uTrimTextureMap, tex).r == 0.0)
|
|
1002
|
+
discard;
|
|
1003
|
+
}
|
|
1004
|
+
"""
|
|
961
1005
|
|
|
962
1006
|
def __init__(self, *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):
|
|
963
1007
|
OpenGLFrame.__init__(self, *args, **kw)
|
|
@@ -972,6 +1016,9 @@ class SplineOpenGLFrame(OpenGLFrame):
|
|
|
972
1016
|
self.origin = None
|
|
973
1017
|
self.button = None
|
|
974
1018
|
self.mode = self.ROTATE
|
|
1019
|
+
|
|
1020
|
+
self.computeBSplineCode = self.computeBSplineCode.format(maxOrder=self.maxOrder)
|
|
1021
|
+
self.computeSurfaceSamplesCode = self.computeSurfaceSamplesCode.format(maxOrder=self.maxOrder)
|
|
975
1022
|
|
|
976
1023
|
self.SetBackgroundColor(0.0, 0.2, 0.2)
|
|
977
1024
|
|
|
@@ -1114,6 +1161,31 @@ class SplineOpenGLFrame(OpenGLFrame):
|
|
|
1114
1161
|
#print("GL_SHADING_LANGUAGE_VERSION: ", glGetString(GL_SHADING_LANGUAGE_VERSION))
|
|
1115
1162
|
#print("GL_MAX_TESS_GEN_LEVEL: ", glGetIntegerv(GL_MAX_TESS_GEN_LEVEL))
|
|
1116
1163
|
|
|
1164
|
+
# Set up frameBuffer into which we draw surface trims.
|
|
1165
|
+
self.frameBuffer = glGenFramebuffers(1)
|
|
1166
|
+
glBindFramebuffer(GL_FRAMEBUFFER, self.frameBuffer)
|
|
1167
|
+
|
|
1168
|
+
# Create the texture buffer for surface trims.
|
|
1169
|
+
self.trimTextureBuffer = glGenTextures(1)
|
|
1170
|
+
glActiveTexture(GL_TEXTURE1)
|
|
1171
|
+
glBindTexture(GL_TEXTURE_2D, self.trimTextureBuffer)
|
|
1172
|
+
glPixelStorei(GL_UNPACK_ALIGNMENT, 1)
|
|
1173
|
+
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER)
|
|
1174
|
+
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER)
|
|
1175
|
+
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
|
|
1176
|
+
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
|
|
1177
|
+
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, 512, 512, 0, GL_RED, GL_UNSIGNED_BYTE, None)
|
|
1178
|
+
glActiveTexture(GL_TEXTURE0)
|
|
1179
|
+
|
|
1180
|
+
# Attach trim texture buffer to framebuffer and validate framebuffer.
|
|
1181
|
+
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, self.trimTextureBuffer, 0)
|
|
1182
|
+
glDrawBuffers(1, (GL_COLOR_ATTACHMENT0,))
|
|
1183
|
+
if glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE:
|
|
1184
|
+
raise ValueError("Framebuffer incomplete")
|
|
1185
|
+
|
|
1186
|
+
# Set framebuffer back to default.
|
|
1187
|
+
glBindFramebuffer(GL_FRAMEBUFFER, 0)
|
|
1188
|
+
|
|
1117
1189
|
# Set up GL texture buffer for spline data
|
|
1118
1190
|
self.splineDataBuffer = glGenBuffers(1)
|
|
1119
1191
|
self.splineTextureBuffer = glGenTextures(1)
|
|
@@ -1132,13 +1204,12 @@ class SplineOpenGLFrame(OpenGLFrame):
|
|
|
1132
1204
|
glBufferData(GL_ARRAY_BUFFER, 4 * 4, np.array([0,0,0,0], np.float32), GL_STATIC_DRAW)
|
|
1133
1205
|
|
|
1134
1206
|
# Compile shaders and link programs
|
|
1135
|
-
self.computeBSplineCode = self.computeBSplineCode.format(maxOrder=self.maxOrder)
|
|
1136
|
-
self.computeSurfaceSamplesCode = self.computeSurfaceSamplesCode.format(maxOrder=self.maxOrder)
|
|
1137
1207
|
try:
|
|
1138
1208
|
# Must create CurveProgram first, because it checks and potentially resets tessellationEnabled flag.
|
|
1139
1209
|
self.curveProgram = CurveProgram(self)
|
|
1140
|
-
self.surface3Program = SurfaceProgram(self, 3, "", "", "", "splineColor = uFillColor.rgb;")
|
|
1141
|
-
self.
|
|
1210
|
+
self.surface3Program = SurfaceProgram(self, False, 3, "", "", "", "splineColor = uFillColor.rgb;")
|
|
1211
|
+
self.trimmedSurface3Program = SurfaceProgram(self, True, 3, "", "", "", "splineColor = uFillColor.rgb;")
|
|
1212
|
+
self.surface4Program = SurfaceProgram(self, False, 4,
|
|
1142
1213
|
"""
|
|
1143
1214
|
vec4 kVec = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
|
|
1144
1215
|
vec3 pVec;
|
|
@@ -1152,7 +1223,27 @@ class SplineOpenGLFrame(OpenGLFrame):
|
|
|
1152
1223
|
pVec = abs(fract(uFillColor.xxx + kVec.xyz) * 6.0 - kVec.www);
|
|
1153
1224
|
splineColor = uFillColor.z * mix(kVec.xxx, clamp(pVec - kVec.xxx, 0.0, 1.0), splineColor.r);
|
|
1154
1225
|
""")
|
|
1155
|
-
self.
|
|
1226
|
+
self.trimmedSurface4Program = SurfaceProgram(self, True, 4,
|
|
1227
|
+
"""
|
|
1228
|
+
vec4 kVec = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
|
|
1229
|
+
vec3 pVec;
|
|
1230
|
+
""", "splineColor = vec3(0.0, 0.0, 0.0);",
|
|
1231
|
+
"""
|
|
1232
|
+
splineColor.r += uBSpline[uB] * vBSpline[vB] * texelFetch(uSplineData, i+3).x;
|
|
1233
|
+
""",
|
|
1234
|
+
# Taken from http://lolengine.net/blog/2013/07/27/rgb-to-hsv-in-glsl
|
|
1235
|
+
# uFillColor is passed in as HSV
|
|
1236
|
+
"""
|
|
1237
|
+
pVec = abs(fract(uFillColor.xxx + kVec.xyz) * 6.0 - kVec.www);
|
|
1238
|
+
splineColor = uFillColor.z * mix(kVec.xxx, clamp(pVec - kVec.xxx, 0.0, 1.0), splineColor.r);
|
|
1239
|
+
""")
|
|
1240
|
+
self.surface6Program = SurfaceProgram(self, False, 6, "", "splineColor = vec3(0.0, 0.0, 0.0);",
|
|
1241
|
+
"""
|
|
1242
|
+
splineColor.r += uBSpline[uB] * vBSpline[vB] * texelFetch(uSplineData, i+3).x;
|
|
1243
|
+
splineColor.g += uBSpline[uB] * vBSpline[vB] * texelFetch(uSplineData, i+4).x;
|
|
1244
|
+
splineColor.b += uBSpline[uB] * vBSpline[vB] * texelFetch(uSplineData, i+5).x;
|
|
1245
|
+
""", "")
|
|
1246
|
+
self.trimmedSurface6Program = SurfaceProgram(self, True, 6, "", "splineColor = vec3(0.0, 0.0, 0.0);",
|
|
1156
1247
|
"""
|
|
1157
1248
|
splineColor.r += uBSpline[uB] * vBSpline[vB] * texelFetch(uSplineData, i+3).x;
|
|
1158
1249
|
splineColor.g += uBSpline[uB] * vBSpline[vB] * texelFetch(uSplineData, i+4).x;
|
|
@@ -1168,6 +1259,7 @@ class SplineOpenGLFrame(OpenGLFrame):
|
|
|
1168
1259
|
print(badLine)
|
|
1169
1260
|
quit()
|
|
1170
1261
|
|
|
1262
|
+
# Set default draw parameters.
|
|
1171
1263
|
glUseProgram(0)
|
|
1172
1264
|
glEnable( GL_DEPTH_TEST )
|
|
1173
1265
|
glClearColor(self.backgroundColor[0], self.backgroundColor[1], self.backgroundColor[2], self.backgroundColor[3])
|
|
@@ -1185,7 +1277,7 @@ class SplineOpenGLFrame(OpenGLFrame):
|
|
|
1185
1277
|
defaultAnchorDistance = np.linalg.norm(self.defaultEye - self.defaultCenter)
|
|
1186
1278
|
clipDistance = defaultAnchorDistance / np.sqrt(3.0)
|
|
1187
1279
|
near = 0.01 * defaultAnchorDistance / 3.0
|
|
1188
|
-
far =
|
|
1280
|
+
far = 3.0 * defaultAnchorDistance
|
|
1189
1281
|
top = clipDistance * near / defaultAnchorDistance # Choose frustum that displays [-clipDistance,clipDistance] in y for z = -defaultAnchorDistance
|
|
1190
1282
|
glFrustum(-top*xExtent, top*xExtent, -top, top, near, far)
|
|
1191
1283
|
#glOrtho(-xExtent, xExtent, -1.0, 1.0, -1.0, 1.0)
|
|
@@ -1196,8 +1288,11 @@ class SplineOpenGLFrame(OpenGLFrame):
|
|
|
1196
1288
|
|
|
1197
1289
|
self.curveProgram.ResetBounds(self)
|
|
1198
1290
|
self.surface3Program.ResetBounds(self)
|
|
1291
|
+
self.trimmedSurface3Program.ResetBounds(self)
|
|
1199
1292
|
self.surface4Program.ResetBounds(self)
|
|
1293
|
+
self.trimmedSurface4Program.ResetBounds(self)
|
|
1200
1294
|
self.surface6Program.ResetBounds(self)
|
|
1295
|
+
self.trimmedSurface6Program.ResetBounds(self)
|
|
1201
1296
|
|
|
1202
1297
|
glUseProgram(0)
|
|
1203
1298
|
glMatrixMode(GL_MODELVIEW)
|
|
@@ -1449,6 +1544,122 @@ class SplineOpenGLFrame(OpenGLFrame):
|
|
|
1449
1544
|
if not "animate" in spline.metadata:
|
|
1450
1545
|
spline.metadata["animate"] = None
|
|
1451
1546
|
|
|
1547
|
+
@staticmethod
|
|
1548
|
+
def tessellate2DSolid(solid):
|
|
1549
|
+
"""
|
|
1550
|
+
Returns an array of triangles that tessellate the given 2D solid
|
|
1551
|
+
"""
|
|
1552
|
+
assert solid.dimension == 2
|
|
1553
|
+
assert solid.containsInfinity == False
|
|
1554
|
+
|
|
1555
|
+
# First, collect all manifold contour endpoints, accounting for slight numerical error.
|
|
1556
|
+
class Endpoint:
|
|
1557
|
+
def __init__(self, curve, t, clockwise, isStart, otherEnd=None):
|
|
1558
|
+
self.curve = curve
|
|
1559
|
+
self.t = t
|
|
1560
|
+
self.xy = curve.manifold.evaluate((t,))
|
|
1561
|
+
self.clockwise = clockwise
|
|
1562
|
+
self.isStart = isStart
|
|
1563
|
+
self.otherEnd = otherEnd
|
|
1564
|
+
self.connection = None
|
|
1565
|
+
endpoints = []
|
|
1566
|
+
for curve in solid.boundaries:
|
|
1567
|
+
curve.domain.boundaries.sort(key=lambda boundary: (boundary.manifold.evaluate(0.0), -boundary.manifold.normal(0.0)))
|
|
1568
|
+
leftB = 0
|
|
1569
|
+
rightB = 0
|
|
1570
|
+
boundaryCount = len(curve.domain.boundaries)
|
|
1571
|
+
while leftB < boundaryCount:
|
|
1572
|
+
if curve.domain.boundaries[leftB].manifold.normal(0.0) < 0.0:
|
|
1573
|
+
leftPoint = curve.domain.boundaries[leftB].manifold.evaluate(0.0)[0]
|
|
1574
|
+
while rightB < boundaryCount:
|
|
1575
|
+
rightPoint = curve.domain.boundaries[rightB].manifold.evaluate(0.0)[0]
|
|
1576
|
+
if leftPoint - Manifold.minSeparation < rightPoint and curve.domain.boundaries[rightB].manifold.normal(0.0) > 0.0:
|
|
1577
|
+
t = curve.manifold.tangent_space(leftPoint)[:,0]
|
|
1578
|
+
n = curve.manifold.normal(leftPoint)
|
|
1579
|
+
clockwise = t[0] * n[1] - t[1] * n[0] > 0.0
|
|
1580
|
+
ep1 = Endpoint(curve, leftPoint, clockwise, rightPoint >= leftPoint)
|
|
1581
|
+
ep2 = Endpoint(curve, rightPoint, clockwise, rightPoint < leftPoint, ep1)
|
|
1582
|
+
ep1.otherEnd = ep2
|
|
1583
|
+
endpoints.append(ep1)
|
|
1584
|
+
endpoints.append(ep2)
|
|
1585
|
+
leftB = rightB
|
|
1586
|
+
rightB += 1
|
|
1587
|
+
break
|
|
1588
|
+
rightB += 1
|
|
1589
|
+
leftB += 1
|
|
1590
|
+
|
|
1591
|
+
# Second, collect all valid pairings of endpoints (normal not flipped between segments).
|
|
1592
|
+
Connection = namedtuple('Connection', ('distance', 'ep1', 'ep2'))
|
|
1593
|
+
connections = []
|
|
1594
|
+
for i, ep1 in enumerate(endpoints[:-1]):
|
|
1595
|
+
for ep2 in endpoints[i+1:]:
|
|
1596
|
+
if (ep1.clockwise == ep2.clockwise and ep1.isStart != ep2.isStart) or \
|
|
1597
|
+
(ep1.clockwise != ep2.clockwise and ep1.isStart == ep2.isStart):
|
|
1598
|
+
connections.append(Connection(np.linalg.norm(ep1.xy - ep2.xy), ep1, ep2))
|
|
1599
|
+
|
|
1600
|
+
# Third, only keep closest pairings (prune the rest).
|
|
1601
|
+
connections.sort(key=lambda connection: -connection.distance)
|
|
1602
|
+
while connections:
|
|
1603
|
+
connection = connections.pop()
|
|
1604
|
+
connection.ep1.connection = connection.ep2
|
|
1605
|
+
connection.ep2.connection = connection.ep1
|
|
1606
|
+
connections = [c for c in connections if c.ep1 is not connection.ep1 and c.ep1 is not connection.ep2 and \
|
|
1607
|
+
c.ep2 is not connection.ep1 and c.ep2 is not connection.ep2]
|
|
1608
|
+
|
|
1609
|
+
# Fourth, set up GLUT to tesselate the solid.
|
|
1610
|
+
tess = gluNewTess()
|
|
1611
|
+
gluTessProperty(tess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD)
|
|
1612
|
+
vertices = []
|
|
1613
|
+
def beginCallback(type=None):
|
|
1614
|
+
vertices = []
|
|
1615
|
+
def edgeFlagDataCallback(flag, polygonData):
|
|
1616
|
+
pass # Forces triangulation of polygons rather than triangle fans or strips
|
|
1617
|
+
def vertexCallback(vertex, otherData=None):
|
|
1618
|
+
vertices.append(vertex[:2])
|
|
1619
|
+
def combineCallback(vertex, neighbors, neighborWeights, outData=None):
|
|
1620
|
+
outData = vertex
|
|
1621
|
+
return outData
|
|
1622
|
+
def endCallback():
|
|
1623
|
+
pass
|
|
1624
|
+
gluTessCallback(tess, GLU_TESS_BEGIN, beginCallback)
|
|
1625
|
+
gluTessCallback(tess, GLU_TESS_EDGE_FLAG_DATA, edgeFlagDataCallback)
|
|
1626
|
+
gluTessCallback(tess, GLU_TESS_VERTEX, vertexCallback)
|
|
1627
|
+
gluTessCallback(tess, GLU_TESS_COMBINE, combineCallback)
|
|
1628
|
+
gluTessCallback(tess, GLU_TESS_END, endCallback)
|
|
1629
|
+
|
|
1630
|
+
# Fifth, trace the contours from pairing to pairing, using GLUT to tesselate the interior.
|
|
1631
|
+
gluTessBeginPolygon(tess, 0)
|
|
1632
|
+
while endpoints:
|
|
1633
|
+
start = endpoints[0]
|
|
1634
|
+
if not start.isStart:
|
|
1635
|
+
start = start.otherEnd
|
|
1636
|
+
# Run backwards until you hit start again or hit an end.
|
|
1637
|
+
if start.connection is not None:
|
|
1638
|
+
originalStart = start
|
|
1639
|
+
next = start.connection
|
|
1640
|
+
start = None
|
|
1641
|
+
while next is not None and start is not originalStart:
|
|
1642
|
+
start = next.otherEnd
|
|
1643
|
+
next = start.connection
|
|
1644
|
+
# Run forwards submitting vertices for the contour.
|
|
1645
|
+
next = start
|
|
1646
|
+
gluTessBeginContour(tess)
|
|
1647
|
+
while next is not None:
|
|
1648
|
+
endpoints.remove(next)
|
|
1649
|
+
endpoints.remove(next.otherEnd)
|
|
1650
|
+
subdivisions = max(int(abs(next.otherEnd.t - next.t) / 0.1), 20) if isinstance(next.curve.manifold, Spline) else 2
|
|
1651
|
+
for t in np.linspace(next.t, next.otherEnd.t, subdivisions):
|
|
1652
|
+
xy = next.curve.manifold.evaluate((t,))
|
|
1653
|
+
vertex = (*xy, 0.0)
|
|
1654
|
+
gluTessVertex(tess, vertex, vertex)
|
|
1655
|
+
next = next.otherEnd.connection
|
|
1656
|
+
if next is start:
|
|
1657
|
+
break
|
|
1658
|
+
gluTessEndContour(tess)
|
|
1659
|
+
gluTessEndPolygon(tess)
|
|
1660
|
+
gluDeleteTess(tess)
|
|
1661
|
+
return np.array(vertices, np.float32)
|
|
1662
|
+
|
|
1452
1663
|
def _DrawPoints(self, spline, drawCoefficients):
|
|
1453
1664
|
"""
|
|
1454
1665
|
Draw spline points for an nInd == 0 or order == 1 spline within a `SplineOpenGLFrame`. The self will call this method for you.
|
|
@@ -1530,14 +1741,15 @@ class SplineOpenGLFrame(OpenGLFrame):
|
|
|
1530
1741
|
fillColor = spline.metadata["fillColor"]
|
|
1531
1742
|
if spline.nDep <= 3:
|
|
1532
1743
|
nDep = 3
|
|
1533
|
-
program = self.surface3Program
|
|
1744
|
+
program = self.trimmedSurface3Program if "trim" in spline.cache else self.surface3Program
|
|
1534
1745
|
elif spline.nDep == 4:
|
|
1535
1746
|
nDep = 4
|
|
1747
|
+
program = self.trimmedSurface4Program if "trim" in spline.cache else self.surface4Program
|
|
1536
1748
|
program = self.surface4Program
|
|
1537
1749
|
fillColor = self.ConvertRGBToHSV(fillColor[0], fillColor[1], fillColor[2], fillColor[3])
|
|
1538
1750
|
elif spline.nDep <= 6:
|
|
1539
1751
|
nDep = 6
|
|
1540
|
-
program = self.surface6Program
|
|
1752
|
+
program = self.trimmedSurface6Program if "trim" in spline.cache else self.surface6Program
|
|
1541
1753
|
else:
|
|
1542
1754
|
raise ValueError("Can't draw surface.")
|
|
1543
1755
|
|
|
@@ -1595,14 +1807,15 @@ class SplineOpenGLFrame(OpenGLFrame):
|
|
|
1595
1807
|
lineColor = spline.metadata["lineColor"].copy()
|
|
1596
1808
|
if spline.nDep <= 3:
|
|
1597
1809
|
nDep = 3
|
|
1598
|
-
program = self.surface3Program
|
|
1810
|
+
program = self.trimmedSurface3Program if "trim" in spline.cache else self.surface3Program
|
|
1599
1811
|
elif spline.nDep == 4:
|
|
1600
1812
|
nDep = 4
|
|
1813
|
+
program = self.trimmedSurface4Program if "trim" in spline.cache else self.surface4Program
|
|
1601
1814
|
program = self.surface4Program
|
|
1602
1815
|
fillColor = self.ConvertRGBToHSV(fillColor[0], fillColor[1], fillColor[2], fillColor[3])
|
|
1603
1816
|
elif spline.nDep <= 6:
|
|
1604
1817
|
nDep = 6
|
|
1605
|
-
program = self.surface6Program
|
|
1818
|
+
program = self.trimmedSurface6Program if "trim" in spline.cache else self.surface6Program
|
|
1606
1819
|
else:
|
|
1607
1820
|
raise ValueError("Can't draw surface.")
|
|
1608
1821
|
fillColor[3] *= 0.5
|
|
@@ -1669,6 +1882,33 @@ class SplineOpenGLFrame(OpenGLFrame):
|
|
|
1669
1882
|
"""
|
|
1670
1883
|
Draw a spline within a `SplineOpenGLFrame`.
|
|
1671
1884
|
"""
|
|
1885
|
+
# Fill trim stencil.
|
|
1886
|
+
if "trim" in spline.cache:
|
|
1887
|
+
# Draw trim tessellation into trim texture framebuffer.
|
|
1888
|
+
glBindFramebuffer(GL_FRAMEBUFFER, self.frameBuffer)
|
|
1889
|
+
glDisable(GL_DEPTH_TEST)
|
|
1890
|
+
glViewport(0,0,512,512)
|
|
1891
|
+
glClearColor(0.0, 0.0, 0.0, 1.0)
|
|
1892
|
+
glClear(GL_COLOR_BUFFER_BIT)
|
|
1893
|
+
glMatrixMode(GL_PROJECTION)
|
|
1894
|
+
glLoadIdentity()
|
|
1895
|
+
bounds = spline.domain()
|
|
1896
|
+
glOrtho(bounds[0, 0], bounds[0, 1], bounds[1, 0], bounds[1, 1], -1.0, 1.0)
|
|
1897
|
+
glColor3f(1.0, 0.0, 0.0)
|
|
1898
|
+
glBegin(GL_TRIANGLES)
|
|
1899
|
+
for vertex in spline.cache["trim"]:
|
|
1900
|
+
glVertex2fv(vertex)
|
|
1901
|
+
glEnd()
|
|
1902
|
+
glFlush()
|
|
1903
|
+
# Reset view for main framebuffer.
|
|
1904
|
+
glBindFramebuffer(GL_FRAMEBUFFER, 0)
|
|
1905
|
+
glEnable(GL_DEPTH_TEST)
|
|
1906
|
+
glViewport(0, 0, self.width, self.height)
|
|
1907
|
+
glClearColor(self.backgroundColor[0], self.backgroundColor[1], self.backgroundColor[2], self.backgroundColor[3])
|
|
1908
|
+
glMatrixMode(GL_PROJECTION)
|
|
1909
|
+
glLoadMatrixf(self.projection)
|
|
1910
|
+
glMatrixMode(GL_MODELVIEW)
|
|
1911
|
+
|
|
1672
1912
|
# Retrieve transposed float32 coefficients.
|
|
1673
1913
|
coefs = spline.cache["coefs32"]
|
|
1674
1914
|
|
|
@@ -1754,8 +1994,12 @@ class CurveProgram:
|
|
|
1754
1994
|
|
|
1755
1995
|
class SurfaceProgram:
|
|
1756
1996
|
""" Compile surface program """
|
|
1757
|
-
def __init__(self, frame, nDep, splineColorDeclarations, initializeSplineColor, computeSplineColor, postProcessSplineColor):
|
|
1997
|
+
def __init__(self, frame, trimmed, nDep, splineColorDeclarations, initializeSplineColor, computeSplineColor, postProcessSplineColor):
|
|
1758
1998
|
if frame.tessellationEnabled:
|
|
1999
|
+
if trimmed:
|
|
2000
|
+
compiledFragmentShader = shaders.compileShader(frame.trimmedSurfaceFragmentShaderCode, GL_FRAGMENT_SHADER)
|
|
2001
|
+
else:
|
|
2002
|
+
compiledFragmentShader = shaders.compileShader(frame.surfaceFragmentShaderCode, GL_FRAGMENT_SHADER)
|
|
1759
2003
|
self.surfaceProgram = shaders.compileProgram(
|
|
1760
2004
|
shaders.compileShader(frame.surfaceVertexShaderCode, GL_VERTEX_SHADER),
|
|
1761
2005
|
shaders.compileShader(frame.surfaceTCShaderCode.format(
|
|
@@ -1770,7 +2014,7 @@ class SurfaceProgram:
|
|
|
1770
2014
|
computeSplineColor=computeSplineColor,
|
|
1771
2015
|
postProcessSplineColor=postProcessSplineColor,
|
|
1772
2016
|
maxOrder=frame.maxOrder), GL_TESS_EVALUATION_SHADER),
|
|
1773
|
-
|
|
2017
|
+
compiledFragmentShader,
|
|
1774
2018
|
validate = False)
|
|
1775
2019
|
else:
|
|
1776
2020
|
self.surfaceProgram = shaders.compileProgram(
|
|
@@ -1787,6 +2031,7 @@ class SurfaceProgram:
|
|
|
1787
2031
|
maxOrder=frame.maxOrder), GL_GEOMETRY_SHADER),
|
|
1788
2032
|
shaders.compileShader(frame.surfaceSimpleFragmentShaderCode, GL_FRAGMENT_SHADER))
|
|
1789
2033
|
|
|
2034
|
+
# Initialize program parameters.
|
|
1790
2035
|
glUseProgram(self.surfaceProgram)
|
|
1791
2036
|
self.aSurfaceParameters = glGetAttribLocation(self.surfaceProgram, "aParameters")
|
|
1792
2037
|
glBindBuffer(GL_ARRAY_BUFFER, frame.parameterBuffer)
|
|
@@ -1800,7 +2045,10 @@ class SurfaceProgram:
|
|
|
1800
2045
|
self.uSurfaceOptions = glGetUniformLocation(self.surfaceProgram, 'uOptions')
|
|
1801
2046
|
self.uSurfaceSplineData = glGetUniformLocation(self.surfaceProgram, 'uSplineData')
|
|
1802
2047
|
glUniform1i(self.uSurfaceSplineData, 0) # GL_TEXTURE0 is the spline buffer texture
|
|
1803
|
-
|
|
2048
|
+
if trimmed and frame.tessellationEnabled:
|
|
2049
|
+
self.uTrimTextureMap = glGetUniformLocation(self.surfaceProgram, 'uTrimTextureMap')
|
|
2050
|
+
glUniform1i(self.uTrimTextureMap, 1) # GL_TEXTURE1 is the trim texture map
|
|
2051
|
+
|
|
1804
2052
|
def ResetBounds(self, frame):
|
|
1805
2053
|
"""Reset bounds and other frame configuration for surface program"""
|
|
1806
2054
|
glUseProgram(self.surfaceProgram)
|