Enabled piecewise export

This commit is contained in:
Luke Campagnola 2013-06-18 10:55:25 -04:00
parent 2243082d4b
commit 3656b02237

View File

@ -34,6 +34,7 @@ class GLViewWidget(QtOpenGL.QGLWidget):
'elevation': 30, ## camera's angle of elevation in degrees 'elevation': 30, ## camera's angle of elevation in degrees
'azimuth': 45, ## camera's azimuthal angle in degrees 'azimuth': 45, ## camera's azimuthal angle in degrees
## (rotation around z-axis 0 points along x-axis) ## (rotation around z-axis 0 points along x-axis)
'viewport': None, ## glViewport params; None == whole widget
} }
self.items = [] self.items = []
self.noRepeatKeys = [QtCore.Qt.Key_Right, QtCore.Qt.Key_Left, QtCore.Qt.Key_Up, QtCore.Qt.Key_Down, QtCore.Qt.Key_PageUp, QtCore.Qt.Key_PageDown] self.noRepeatKeys = [QtCore.Qt.Key_Right, QtCore.Qt.Key_Left, QtCore.Qt.Key_Up, QtCore.Qt.Key_Down, QtCore.Qt.Key_PageUp, QtCore.Qt.Key_PageDown]
@ -66,25 +67,46 @@ class GLViewWidget(QtOpenGL.QGLWidget):
glClearColor(0.0, 0.0, 0.0, 0.0) glClearColor(0.0, 0.0, 0.0, 0.0)
self.resizeGL(self.width(), self.height()) self.resizeGL(self.width(), self.height())
def getViewport(self):
vp = self.opts['viewport']
if vp is None:
return (0, 0, self.width(), self.height())
else:
return vp
def resizeGL(self, w, h): def resizeGL(self, w, h):
glViewport(0, 0, w, h) pass
#glViewport(*self.getViewport())
#self.update() #self.update()
def setProjection(self): def setProjection(self, region=None):
# Xw = (Xnd + 1) * width/2 + X
if region is None:
region = (0, 0, self.width(), self.height())
## Create the projection matrix ## Create the projection matrix
glMatrixMode(GL_PROJECTION) glMatrixMode(GL_PROJECTION)
glLoadIdentity() glLoadIdentity()
w = self.width() #w = self.width()
h = self.height() #h = self.height()
x0, y0, w, h = self.getViewport()
dist = self.opts['distance'] dist = self.opts['distance']
fov = self.opts['fov'] fov = self.opts['fov']
nearClip = dist * 0.001 nearClip = dist * 0.001
farClip = dist * 1000. farClip = dist * 1000.
r = nearClip * np.tan(fov * 0.5 * np.pi / 180.) r = nearClip * np.tan(fov * 0.5 * np.pi / 180.)
t = r * h / w t = r * h / w
glFrustum( -r, r, -t, t, nearClip, farClip)
# convert screen coordinates (region) to normalized device coordinates
# Xnd = (Xw - X0) * 2/width - 1
## Note that X0 and width in these equations must be the values used in viewport
left = r * ((region[0]-x0) * (2.0/w) - 1)
right = r * ((region[0]+region[2]-x0) * (2.0/w) - 1)
bottom = t * ((region[1]-y0) * (2.0/h) - 1)
top = t * ((region[1]+region[3]-y0) * (2.0/h) - 1)
glFrustum( left, right, bottom, top, nearClip, farClip)
#glFrustum(-r, r, -t, t, nearClip, farClip)
def setModelview(self): def setModelview(self):
glMatrixMode(GL_MODELVIEW) glMatrixMode(GL_MODELVIEW)
@ -96,8 +118,17 @@ class GLViewWidget(QtOpenGL.QGLWidget):
glTranslatef(-center.x(), -center.y(), -center.z()) glTranslatef(-center.x(), -center.y(), -center.z())
def paintGL(self): def paintGL(self, region=None, viewport=None):
self.setProjection() """
viewport specifies the arguments to glViewport. If None, then we use self.opts['viewport']
region specifies the sub-region of self.opts['viewport'] that should be rendered.
Note that we may use viewport != self.opts['viewport'] when exporting.
"""
if viewport is None:
glViewport(*self.getViewport())
else:
glViewport(*viewport)
self.setProjection(region=region)
self.setModelview() self.setModelview()
glClear( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT ) glClear( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT )
self.drawItemTree() self.drawItemTree()
@ -316,39 +347,53 @@ class GLViewWidget(QtOpenGL.QGLWidget):
def renderToArray(self, size, format=GL_BGRA, type=GL_UNSIGNED_BYTE): def renderToArray(self, size, format=GL_BGRA, type=GL_UNSIGNED_BYTE):
w,h = size w,h = map(int, size)
self.makeCurrent() self.makeCurrent()
try: try:
output = np.empty((w, h, 4), dtype=np.ubyte)
fb = glfbo.glGenFramebuffers(1) fb = glfbo.glGenFramebuffers(1)
glfbo.glBindFramebuffer(glfbo.GL_FRAMEBUFFER, fb ) glfbo.glBindFramebuffer(glfbo.GL_FRAMEBUFFER, fb )
glEnable(GL_TEXTURE_2D) glEnable(GL_TEXTURE_2D)
tex = glGenTextures(1) tex = glGenTextures(1)
glBindTexture(GL_TEXTURE_2D, tex) glBindTexture(GL_TEXTURE_2D, tex)
data = np.zeros((w,h,4), dtype=np.ubyte) texwidth = 512
data = np.zeros((texwidth,texwidth,4), dtype=np.ubyte)
## Test texture dimensions first ## Test texture dimensions first
glTexImage2D(GL_PROXY_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, None) glTexImage2D(GL_PROXY_TEXTURE_2D, 0, GL_RGBA, texwidth, texwidth, 0, GL_RGBA, GL_UNSIGNED_BYTE, None)
if glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH) == 0: if glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH) == 0:
raise Exception("OpenGL failed to create 2D texture (%dx%d); too large for this hardware." % shape[:2]) raise Exception("OpenGL failed to create 2D texture (%dx%d); too large for this hardware." % shape[:2])
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, data.transpose((1,0,2))) ## create teture
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texwidth, texwidth, 0, GL_RGBA, GL_UNSIGNED_BYTE, data.transpose((1,0,2)))
## render to texture self.opts['viewport'] = (0, 0, w, h) # viewport is the complete image; this ensures that paintGL(region=...)
glfbo.glFramebufferTexture2D(glfbo.GL_FRAMEBUFFER, glfbo.GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0) # is interpreted correctly.
glViewport(0, 0, w, h)
self.paintGL()
## read texture back to array for x in range(0, w, texwidth):
data = glGetTexImage(GL_TEXTURE_2D, 0, format, type) for y in range(0, h, texwidth):
data = np.fromstring(data, dtype=np.ubyte).reshape(h,w,4).transpose(1,0,2)[:, ::-1] x2 = min(x+texwidth, w)
y2 = min(y+texwidth, h)
w2 = x2-x
h2 = y2-y
## render to texture
glfbo.glFramebufferTexture2D(glfbo.GL_FRAMEBUFFER, glfbo.GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0)
self.paintGL(region=(x, h-y-h2, w2, h2), viewport=(0, 0, w2, h2)) # only render sub-region
## read texture back to array
data = glGetTexImage(GL_TEXTURE_2D, 0, format, type)
data = np.fromstring(data, dtype=np.ubyte).reshape(texwidth,texwidth,4).transpose(1,0,2)[:, ::-1]
output[x:x2, y:y2] = data[:w2, -h2:]
finally: finally:
glViewport(0, 0, self.width(), self.height()) self.opts['viewport'] = None
glfbo.glBindFramebuffer(glfbo.GL_FRAMEBUFFER, 0) glfbo.glBindFramebuffer(glfbo.GL_FRAMEBUFFER, 0)
glBindTexture(GL_TEXTURE_2D, 0) glBindTexture(GL_TEXTURE_2D, 0)
return data return output