180 lines
5.3 KiB
Python
180 lines
5.3 KiB
Python
|
from OpenGL.GL import *
|
||
|
from .. GLGraphicsItem import GLGraphicsItem
|
||
|
from pyqtgraph.Qt import QtGui
|
||
|
import numpy as np
|
||
|
|
||
|
__all__ = ['GLVolumeItem']
|
||
|
|
||
|
class GLVolumeItem(GLGraphicsItem):
|
||
|
def initializeGL(self):
|
||
|
n = 128
|
||
|
self.data = np.random.randint(0, 255, size=4*n**3).astype(np.uint8).reshape((n,n,n,4))
|
||
|
self.data[...,3] *= 0.1
|
||
|
for i in range(n):
|
||
|
self.data[i,:,:,0] = i*256./n
|
||
|
glEnable(GL_TEXTURE_3D)
|
||
|
self.texture = glGenTextures(1)
|
||
|
glBindTexture(GL_TEXTURE_3D, self.texture)
|
||
|
#glTexImage3D( GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, void *data );
|
||
|
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
|
||
|
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
|
||
|
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER)
|
||
|
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER)
|
||
|
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_BORDER)
|
||
|
#glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_BORDER_COLOR, ) ## black/transparent by default
|
||
|
glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, n, n, n, 0, GL_RGBA, GL_UNSIGNED_BYTE, self.data)
|
||
|
glDisable(GL_TEXTURE_3D)
|
||
|
|
||
|
self.lists = {}
|
||
|
for ax in [0,1,2]:
|
||
|
for d in [-1, 1]:
|
||
|
l = glGenLists(1)
|
||
|
self.lists[(ax,d)] = l
|
||
|
glNewList(l, GL_COMPILE)
|
||
|
self.drawVolume(ax, d)
|
||
|
glEndList()
|
||
|
|
||
|
|
||
|
def paint(self):
|
||
|
|
||
|
glEnable(GL_TEXTURE_3D)
|
||
|
glBindTexture(GL_TEXTURE_3D, self.texture)
|
||
|
|
||
|
glDisable(GL_DEPTH_TEST)
|
||
|
#glDisable(GL_CULL_FACE)
|
||
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
|
||
|
glEnable( GL_BLEND )
|
||
|
glEnable( GL_ALPHA_TEST )
|
||
|
|
||
|
view = self.view()
|
||
|
cam = view.cameraPosition()
|
||
|
cam = np.array([cam.x(), cam.y(), cam.z()])
|
||
|
ax = np.argmax(abs(cam))
|
||
|
d = 1 if cam[ax] > 0 else -1
|
||
|
glCallList(self.lists[(ax,d)]) ## draw axes
|
||
|
glDisable(GL_TEXTURE_3D)
|
||
|
|
||
|
def drawVolume(self, ax, d):
|
||
|
slices = 256
|
||
|
N = 5
|
||
|
|
||
|
imax = [0,1,2]
|
||
|
imax.remove(ax)
|
||
|
|
||
|
tp = [[0,0,0],[0,0,0],[0,0,0],[0,0,0]]
|
||
|
vp = [[0,0,0],[0,0,0],[0,0,0],[0,0,0]]
|
||
|
tp[0][imax[0]] = 0
|
||
|
tp[0][imax[1]] = 0
|
||
|
tp[1][imax[0]] = 1
|
||
|
tp[1][imax[1]] = 0
|
||
|
tp[2][imax[0]] = 1
|
||
|
tp[2][imax[1]] = 1
|
||
|
tp[3][imax[0]] = 0
|
||
|
tp[3][imax[1]] = 1
|
||
|
|
||
|
vp[0][imax[0]] = -N
|
||
|
vp[0][imax[1]] = -N
|
||
|
vp[1][imax[0]] = N
|
||
|
vp[1][imax[1]] = -N
|
||
|
vp[2][imax[0]] = N
|
||
|
vp[2][imax[1]] = N
|
||
|
vp[3][imax[0]] = -N
|
||
|
vp[3][imax[1]] = N
|
||
|
r = range(slices)
|
||
|
if d == -1:
|
||
|
r = r[::-1]
|
||
|
|
||
|
glBegin(GL_QUADS)
|
||
|
for i in r:
|
||
|
z = float(i)/(slices-1.)
|
||
|
w = float(i)*10./(slices-1.) - 5.
|
||
|
|
||
|
tp[0][ax] = z
|
||
|
tp[1][ax] = z
|
||
|
tp[2][ax] = z
|
||
|
tp[3][ax] = z
|
||
|
|
||
|
vp[0][ax] = w
|
||
|
vp[1][ax] = w
|
||
|
vp[2][ax] = w
|
||
|
vp[3][ax] = w
|
||
|
|
||
|
|
||
|
glTexCoord3f(*tp[0])
|
||
|
glVertex3f(*vp[0])
|
||
|
glTexCoord3f(*tp[1])
|
||
|
glVertex3f(*vp[1])
|
||
|
glTexCoord3f(*tp[2])
|
||
|
glVertex3f(*vp[2])
|
||
|
glTexCoord3f(*tp[3])
|
||
|
glVertex3f(*vp[3])
|
||
|
glEnd()
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
## Interesting idea:
|
||
|
## remove projection/modelview matrixes, recreate in texture coords.
|
||
|
## it _sorta_ works, but needs tweaking.
|
||
|
#mvm = glGetDoublev(GL_MODELVIEW_MATRIX)
|
||
|
#pm = glGetDoublev(GL_PROJECTION_MATRIX)
|
||
|
#m = QtGui.QMatrix4x4(mvm.flatten()).inverted()[0]
|
||
|
#p = QtGui.QMatrix4x4(pm.flatten()).inverted()[0]
|
||
|
|
||
|
#glMatrixMode(GL_PROJECTION)
|
||
|
#glPushMatrix()
|
||
|
#glLoadIdentity()
|
||
|
#N=1
|
||
|
#glOrtho(-N,N,-N,N,-100,100)
|
||
|
|
||
|
#glMatrixMode(GL_MODELVIEW)
|
||
|
#glLoadIdentity()
|
||
|
|
||
|
|
||
|
#glMatrixMode(GL_TEXTURE)
|
||
|
#glLoadIdentity()
|
||
|
#glMultMatrixf(m.copyDataTo())
|
||
|
|
||
|
#view = self.view()
|
||
|
#w = view.width()
|
||
|
#h = view.height()
|
||
|
#dist = view.opts['distance']
|
||
|
#fov = view.opts['fov']
|
||
|
#nearClip = dist * .1
|
||
|
#farClip = dist * 5.
|
||
|
#r = nearClip * np.tan(fov)
|
||
|
#t = r * h / w
|
||
|
|
||
|
#p = QtGui.QMatrix4x4()
|
||
|
#p.frustum( -r, r, -t, t, nearClip, farClip)
|
||
|
#glMultMatrixf(p.inverted()[0].copyDataTo())
|
||
|
|
||
|
|
||
|
#glBegin(GL_QUADS)
|
||
|
|
||
|
#M=1
|
||
|
#for i in range(500):
|
||
|
#z = i/500.
|
||
|
#w = -i/500.
|
||
|
#glTexCoord3f(-M, -M, z)
|
||
|
#glVertex3f(-N, -N, w)
|
||
|
#glTexCoord3f(M, -M, z)
|
||
|
#glVertex3f(N, -N, w)
|
||
|
#glTexCoord3f(M, M, z)
|
||
|
#glVertex3f(N, N, w)
|
||
|
#glTexCoord3f(-M, M, z)
|
||
|
#glVertex3f(-N, N, w)
|
||
|
#glEnd()
|
||
|
#glDisable(GL_TEXTURE_3D)
|
||
|
|
||
|
#glMatrixMode(GL_PROJECTION)
|
||
|
#glPopMatrix()
|
||
|
|
||
|
|
||
|
|