Added basic OpenGL scenegraph system
- rotate/scalable view widget - volumetric data item
This commit is contained in:
parent
6a7021797f
commit
872fcb17ff
60
opengl/GLGraphicsItem.py
Normal file
60
opengl/GLGraphicsItem.py
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
from pyqtgraph.Qt import QtGui, QtCore
|
||||||
|
|
||||||
|
class GLGraphicsItem(QtCore.QObject):
|
||||||
|
def __init__(self, parentItem=None):
|
||||||
|
QtCore.QObject.__init__(self)
|
||||||
|
self.__parent = None
|
||||||
|
self.__view = None
|
||||||
|
self.__children = set()
|
||||||
|
self.setParentItem(parentItem)
|
||||||
|
self.setDepthValue(0)
|
||||||
|
|
||||||
|
def setParentItem(self, item):
|
||||||
|
if self.__parent is not None:
|
||||||
|
self.__parent.__children.remove(self)
|
||||||
|
if item is not None:
|
||||||
|
item.__children.add(self)
|
||||||
|
self.__parent = item
|
||||||
|
|
||||||
|
def parentItem(self):
|
||||||
|
return self.__parent
|
||||||
|
|
||||||
|
def childItems(self):
|
||||||
|
return list(self.__children)
|
||||||
|
|
||||||
|
def _setView(self, v):
|
||||||
|
self.__view = v
|
||||||
|
|
||||||
|
def view(self):
|
||||||
|
return self.__view
|
||||||
|
|
||||||
|
def setDepthValue(self, value):
|
||||||
|
"""
|
||||||
|
Sets the depth value of this item. Default is 0.
|
||||||
|
This controls the order in which items are drawn--those with a greater depth value will be drawn later.
|
||||||
|
Items with negative depth values are drawn before their parent.
|
||||||
|
(This is analogous to QGraphicsItem.zValue)
|
||||||
|
The depthValue does NOT affect the position of the item or the values it imparts to the GL depth buffer.
|
||||||
|
'"""
|
||||||
|
self.__depthValue = value
|
||||||
|
|
||||||
|
def depthValue(self):
|
||||||
|
"""Return the depth value of this item. See setDepthValue for mode information."""
|
||||||
|
return self.__depthValue
|
||||||
|
|
||||||
|
def initializeGL(self):
|
||||||
|
"""
|
||||||
|
Called after an item is added to a GLViewWidget.
|
||||||
|
The widget's GL context is made current before this method is called.
|
||||||
|
(So this would be an appropriate time to generate lists, upload textures, etc.)
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def paint(self):
|
||||||
|
"""
|
||||||
|
Called by the GLViewWidget to draw this item.
|
||||||
|
It is the responsibility of the item to set up its own modelview matrix,
|
||||||
|
but the caller will take care of pushing/popping.
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
199
opengl/GLViewWidget.py
Normal file
199
opengl/GLViewWidget.py
Normal file
@ -0,0 +1,199 @@
|
|||||||
|
from pyqtgraph.Qt import QtCore, QtGui, QtOpenGL
|
||||||
|
from OpenGL.GL import *
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
Vector = QtGui.QVector3D
|
||||||
|
|
||||||
|
class GLViewWidget(QtOpenGL.QGLWidget):
|
||||||
|
"""
|
||||||
|
Basic widget for displaying 3D data
|
||||||
|
- Rotation/scale controls
|
||||||
|
- Axis/grid display
|
||||||
|
- Export options
|
||||||
|
|
||||||
|
"""
|
||||||
|
def __init__(self, parent=None):
|
||||||
|
QtOpenGL.QGLWidget.__init__(self, parent)
|
||||||
|
self.opts = {
|
||||||
|
'center': Vector(0,0,0), ## will always appear at the center of the widget
|
||||||
|
'distance': 10.0, ## distance of camera from center
|
||||||
|
'fov': 60, ## horizontal field of view in degrees
|
||||||
|
'elevation': 30, ## camera's angle of elevation in degrees
|
||||||
|
'azimuth': 45, ## camera's azimuthal angle in degrees
|
||||||
|
## (rotation around z-axis 0 points along x-axis)
|
||||||
|
}
|
||||||
|
self.items = []
|
||||||
|
|
||||||
|
def addItem(self, item):
|
||||||
|
self.items.append(item)
|
||||||
|
if hasattr(item, 'initializeGL'):
|
||||||
|
self.makeCurrent()
|
||||||
|
item.initializeGL()
|
||||||
|
item._setView(self)
|
||||||
|
#print "set view", item, self, item.view()
|
||||||
|
self.updateGL()
|
||||||
|
|
||||||
|
def initializeGL(self):
|
||||||
|
glClearColor(0.0, 0.0, 0.0, 0.0)
|
||||||
|
glEnable(GL_DEPTH_TEST)
|
||||||
|
|
||||||
|
glEnable( GL_ALPHA_TEST )
|
||||||
|
self.resizeGL(self.width(), self.height())
|
||||||
|
self.generateAxes()
|
||||||
|
#self.generatePoints()
|
||||||
|
|
||||||
|
def resizeGL(self, w, h):
|
||||||
|
glViewport(0, 0, w, h)
|
||||||
|
#self.updateGL()
|
||||||
|
|
||||||
|
def setProjection(self):
|
||||||
|
## Create the projection matrix
|
||||||
|
glMatrixMode(GL_PROJECTION)
|
||||||
|
glLoadIdentity()
|
||||||
|
w = self.width()
|
||||||
|
h = self.height()
|
||||||
|
dist = self.opts['distance']
|
||||||
|
fov = self.opts['fov']
|
||||||
|
|
||||||
|
nearClip = dist * 0.001
|
||||||
|
farClip = dist * 1000.
|
||||||
|
|
||||||
|
r = nearClip * np.tan(fov)
|
||||||
|
t = r * h / w
|
||||||
|
glFrustum( -r, r, -t, t, nearClip, farClip)
|
||||||
|
|
||||||
|
def setModelview(self):
|
||||||
|
glMatrixMode(GL_MODELVIEW)
|
||||||
|
glLoadIdentity()
|
||||||
|
glTranslatef( 0.0, 0.0, -self.opts['distance'])
|
||||||
|
glRotatef(self.opts['elevation']-90, 1, 0, 0)
|
||||||
|
glRotatef(self.opts['azimuth']+90, 0, 0, -1)
|
||||||
|
center = self.opts['center']
|
||||||
|
glTranslatef(center.x(), center.y(), center.z())
|
||||||
|
|
||||||
|
|
||||||
|
def paintGL(self):
|
||||||
|
self.setProjection()
|
||||||
|
self.setModelview()
|
||||||
|
|
||||||
|
glClear( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT )
|
||||||
|
glDisable( GL_DEPTH_TEST )
|
||||||
|
#print "draw list:", self.axisList
|
||||||
|
glCallList(self.axisList) ## draw axes
|
||||||
|
#glCallList(self.pointList)
|
||||||
|
#self.drawPoints()
|
||||||
|
#self.drawAxes()
|
||||||
|
|
||||||
|
self.drawItemTree()
|
||||||
|
|
||||||
|
def drawItemTree(self, item=None):
|
||||||
|
if item is None:
|
||||||
|
items = [x for x in self.items if x.parentItem() is None]
|
||||||
|
else:
|
||||||
|
items = item.childItems()
|
||||||
|
items.append(item)
|
||||||
|
items.sort(lambda a,b: cmp(a.depthValue(), b.depthValue()))
|
||||||
|
for i in items:
|
||||||
|
if i is item:
|
||||||
|
glMatrixMode(GL_MODELVIEW)
|
||||||
|
glPushMatrix()
|
||||||
|
i.paint()
|
||||||
|
glMatrixMode(GL_MODELVIEW)
|
||||||
|
glPopMatrix()
|
||||||
|
else:
|
||||||
|
self.drawItemTree(i)
|
||||||
|
|
||||||
|
|
||||||
|
def cameraPosition(self):
|
||||||
|
"""Return current position of camera based on center, dist, elevation, and azimuth"""
|
||||||
|
center = self.opts['center']
|
||||||
|
dist = self.opts['distance']
|
||||||
|
elev = self.opts['elevation'] * np.pi/180.
|
||||||
|
azim = self.opts['azimuth'] * np.pi/180.
|
||||||
|
|
||||||
|
pos = Vector(
|
||||||
|
center.x() + dist * np.cos(elev) * np.cos(azim),
|
||||||
|
center.y() + dist * np.cos(elev) * np.sin(azim),
|
||||||
|
center.z() + dist * np.sin(elev)
|
||||||
|
)
|
||||||
|
|
||||||
|
return pos
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def generateAxes(self):
|
||||||
|
self.axisList = glGenLists(1)
|
||||||
|
glNewList(self.axisList, GL_COMPILE)
|
||||||
|
|
||||||
|
#glShadeModel(GL_FLAT)
|
||||||
|
#glFrontFace(GL_CCW)
|
||||||
|
#glEnable( GL_LIGHT_MODEL_TWO_SIDE )
|
||||||
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
|
||||||
|
glEnable( GL_BLEND )
|
||||||
|
glEnable( GL_ALPHA_TEST )
|
||||||
|
#glAlphaFunc( GL_ALWAYS,0.5 )
|
||||||
|
glEnable( GL_POINT_SMOOTH )
|
||||||
|
glDisable( GL_DEPTH_TEST )
|
||||||
|
glBegin( GL_LINES )
|
||||||
|
|
||||||
|
glColor4f(1, 1, 1, .3)
|
||||||
|
for x in range(-10, 11):
|
||||||
|
glVertex3f(x, -10, 0)
|
||||||
|
glVertex3f(x, 10, 0)
|
||||||
|
for y in range(-10, 11):
|
||||||
|
glVertex3f(-10, y, 0)
|
||||||
|
glVertex3f( 10, y, 0)
|
||||||
|
|
||||||
|
|
||||||
|
glColor4f(0, 1, 0, .6) # z is green
|
||||||
|
glVertex3f(0, 0, 0)
|
||||||
|
glVertex3f(0, 0, 5)
|
||||||
|
|
||||||
|
glColor4f(1, 1, 0, .6) # y is yellow
|
||||||
|
glVertex3f(0, 0, 0)
|
||||||
|
glVertex3f(0, 5, 0)
|
||||||
|
|
||||||
|
glColor4f(0, 0, 1, .6) # x is blue
|
||||||
|
glVertex3f(0, 0, 0)
|
||||||
|
glVertex3f(5, 0, 0)
|
||||||
|
glEnd()
|
||||||
|
glEndList()
|
||||||
|
|
||||||
|
def generatePoints(self):
|
||||||
|
self.pointList = glGenLists(1)
|
||||||
|
glNewList(self.pointList, GL_COMPILE)
|
||||||
|
width = 7
|
||||||
|
alpha = 0.02
|
||||||
|
n = 40
|
||||||
|
glPointSize( width )
|
||||||
|
glBegin(GL_POINTS)
|
||||||
|
for x in range(-n, n+1):
|
||||||
|
r = (n-x)/(2.*n)
|
||||||
|
glColor4f(r, r, r, alpha)
|
||||||
|
for y in range(-n, n+1):
|
||||||
|
for z in range(-n, n+1):
|
||||||
|
glVertex3f(x, y, z)
|
||||||
|
glEnd()
|
||||||
|
glEndList()
|
||||||
|
|
||||||
|
|
||||||
|
def mousePressEvent(self, ev):
|
||||||
|
self.mousePos = ev.pos()
|
||||||
|
|
||||||
|
def mouseMoveEvent(self, ev):
|
||||||
|
diff = ev.pos() - self.mousePos
|
||||||
|
self.mousePos = ev.pos()
|
||||||
|
self.opts['azimuth'] -= diff.x()
|
||||||
|
self.opts['elevation'] = np.clip(self.opts['elevation'] + diff.y(), -90, 90)
|
||||||
|
#print self.opts['azimuth'], self.opts['elevation']
|
||||||
|
self.updateGL()
|
||||||
|
|
||||||
|
def mouseReleaseEvent(self, ev):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def wheelEvent(self, ev):
|
||||||
|
self.opts['distance'] *= 0.999**ev.delta()
|
||||||
|
self.updateGL()
|
||||||
|
|
||||||
|
|
||||||
|
|
23
opengl/__init__.py
Normal file
23
opengl/__init__.py
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
from GLViewWidget import GLViewWidget
|
||||||
|
|
||||||
|
import os
|
||||||
|
def importAll(path):
|
||||||
|
d = os.path.join(os.path.split(__file__)[0], path)
|
||||||
|
files = []
|
||||||
|
for f in os.listdir(d):
|
||||||
|
if os.path.isdir(os.path.join(d, f)):
|
||||||
|
files.append(f)
|
||||||
|
elif f[-3:] == '.py' and f != '__init__.py':
|
||||||
|
files.append(f[:-3])
|
||||||
|
|
||||||
|
for modName in files:
|
||||||
|
mod = __import__(path+"."+modName, globals(), locals(), fromlist=['*'])
|
||||||
|
if hasattr(mod, '__all__'):
|
||||||
|
names = mod.__all__
|
||||||
|
else:
|
||||||
|
names = [n for n in dir(mod) if n[0] != '_']
|
||||||
|
for k in names:
|
||||||
|
if hasattr(mod, k):
|
||||||
|
globals()[k] = getattr(mod, k)
|
||||||
|
|
||||||
|
importAll('items')
|
47
opengl/items/GLBoxItem.py
Normal file
47
opengl/items/GLBoxItem.py
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
from OpenGL.GL import *
|
||||||
|
from .. GLGraphicsItem import GLGraphicsItem
|
||||||
|
|
||||||
|
__all__ = ['GLBoxItem']
|
||||||
|
|
||||||
|
class GLBoxItem(GLGraphicsItem):
|
||||||
|
def paint(self):
|
||||||
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
|
||||||
|
glEnable( GL_BLEND )
|
||||||
|
glEnable( GL_ALPHA_TEST )
|
||||||
|
#glAlphaFunc( GL_ALWAYS,0.5 )
|
||||||
|
glEnable( GL_POINT_SMOOTH )
|
||||||
|
glDisable( GL_DEPTH_TEST )
|
||||||
|
glBegin( GL_LINES )
|
||||||
|
|
||||||
|
glColor4f(1, 1, 1, .3)
|
||||||
|
w = 10
|
||||||
|
glVertex3f(-w, -w, -w)
|
||||||
|
glVertex3f(-w, -w, w)
|
||||||
|
glVertex3f( w, -w, -w)
|
||||||
|
glVertex3f( w, -w, w)
|
||||||
|
glVertex3f(-w, w, -w)
|
||||||
|
glVertex3f(-w, w, w)
|
||||||
|
glVertex3f( w, w, -w)
|
||||||
|
glVertex3f( w, w, w)
|
||||||
|
|
||||||
|
glVertex3f(-w, -w, -w)
|
||||||
|
glVertex3f(-w, w, -w)
|
||||||
|
glVertex3f( w, -w, -w)
|
||||||
|
glVertex3f( w, w, -w)
|
||||||
|
glVertex3f(-w, -w, w)
|
||||||
|
glVertex3f(-w, w, w)
|
||||||
|
glVertex3f( w, -w, w)
|
||||||
|
glVertex3f( w, w, w)
|
||||||
|
|
||||||
|
glVertex3f(-w, -w, -w)
|
||||||
|
glVertex3f( w, -w, -w)
|
||||||
|
glVertex3f(-w, w, -w)
|
||||||
|
glVertex3f( w, w, -w)
|
||||||
|
glVertex3f(-w, -w, w)
|
||||||
|
glVertex3f( w, -w, w)
|
||||||
|
glVertex3f(-w, w, w)
|
||||||
|
glVertex3f( w, w, w)
|
||||||
|
|
||||||
|
glEnd()
|
||||||
|
|
||||||
|
|
179
opengl/items/GLVolumeItem.py
Normal file
179
opengl/items/GLVolumeItem.py
Normal file
@ -0,0 +1,179 @@
|
|||||||
|
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()
|
||||||
|
|
||||||
|
|
||||||
|
|
0
opengl/items/__init__.py
Normal file
0
opengl/items/__init__.py
Normal file
Loading…
Reference in New Issue
Block a user