mirror of
https://github.com/wxWidgets/Phoenix.git
synced 2026-01-10 13:57:08 +01:00
Merge pull request #1807 from Metallicow/Fix-GLCanvas-Demo
Fix GLCanvas Demo
This commit is contained in:
190
demo/GLCanvas.py
190
demo/GLCanvas.py
@@ -1,7 +1,10 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import wx
|
||||
import os
|
||||
import sys
|
||||
from math import pi, sin, cos
|
||||
|
||||
import wx
|
||||
|
||||
try:
|
||||
from wx import glcanvas
|
||||
@@ -13,11 +16,12 @@ try:
|
||||
# The Python OpenGL package can be found at
|
||||
# http://PyOpenGL.sourceforge.net/
|
||||
from OpenGL.GL import *
|
||||
from OpenGL.GLUT import *
|
||||
from OpenGL.GLU import *
|
||||
haveOpenGL = True
|
||||
except ImportError:
|
||||
haveOpenGL = False
|
||||
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -28,7 +32,7 @@ buttonDefs = {
|
||||
|
||||
class ButtonPanel(wx.Panel):
|
||||
def __init__(self, parent, log):
|
||||
wx.Panel.__init__(self, parent, -1)
|
||||
wx.Panel.__init__(self, parent, wx.ID_ANY)
|
||||
self.log = log
|
||||
|
||||
box = wx.BoxSizer(wx.VERTICAL)
|
||||
@@ -37,14 +41,14 @@ class ButtonPanel(wx.Panel):
|
||||
for k in keys:
|
||||
text = buttonDefs[k][1]
|
||||
btn = wx.Button(self, k, text)
|
||||
box.Add(btn, 0, wx.ALIGN_CENTER|wx.ALL, 15)
|
||||
box.Add(btn, 0, wx.ALIGN_CENTER | wx.ALL, 15)
|
||||
self.Bind(wx.EVT_BUTTON, self.OnButton, btn)
|
||||
|
||||
#** Enable this to show putting a GLCanvas on the wx.Panel
|
||||
#** Enable this to show putting a GLCanvas on the wx.Panel .
|
||||
if 0:
|
||||
c = CubeCanvas(self)
|
||||
c.SetSize((200, 200))
|
||||
box.Add(c, 0, wx.ALIGN_CENTER|wx.ALL, 15)
|
||||
box.Add(c, 0, wx.ALIGN_CENTER | wx.ALL, 15)
|
||||
|
||||
self.SetAutoLayout(True)
|
||||
self.SetSizer(box)
|
||||
@@ -61,7 +65,8 @@ class ButtonPanel(wx.Panel):
|
||||
elif not haveOpenGL:
|
||||
dlg = wx.MessageDialog(self,
|
||||
'The OpenGL package was not found. You can get it at\n'
|
||||
'http://PyOpenGL.sourceforge.net/',
|
||||
'http://PyOpenGL.sourceforge.net/ \n'
|
||||
'or $ pip install PyOpenGL PyOpenGL_accelerate',
|
||||
'Sorry', wx.OK | wx.ICON_WARNING)
|
||||
dlg.ShowModal()
|
||||
dlg.Destroy()
|
||||
@@ -69,7 +74,7 @@ class ButtonPanel(wx.Panel):
|
||||
else:
|
||||
canvasClassName = buttonDefs[evt.GetId()][0]
|
||||
canvasClass = eval(canvasClassName)
|
||||
frame = wx.Frame(None, -1, canvasClassName, size=(400,400))
|
||||
frame = wx.Frame(None, wx.ID_ANY, canvasClassName, size=(400, 400))
|
||||
canvas = canvasClass(frame)
|
||||
frame.Show(True)
|
||||
|
||||
@@ -80,7 +85,7 @@ class MyCanvasBase(glcanvas.GLCanvas):
|
||||
self.init = False
|
||||
self.context = glcanvas.GLContext(self)
|
||||
|
||||
# initial mouse position
|
||||
# Initial mouse position.
|
||||
self.lastx = self.x = 30
|
||||
self.lasty = self.y = 30
|
||||
self.size = None
|
||||
@@ -93,20 +98,17 @@ class MyCanvasBase(glcanvas.GLCanvas):
|
||||
|
||||
|
||||
def OnEraseBackground(self, event):
|
||||
pass # Do nothing, to avoid flashing on MSW.
|
||||
|
||||
pass # Do nothing, to avoid flashing on MSW.
|
||||
|
||||
def OnSize(self, event):
|
||||
wx.CallAfter(self.DoSetViewport)
|
||||
event.Skip()
|
||||
|
||||
|
||||
def DoSetViewport(self):
|
||||
size = self.size = self.GetClientSize() * self.GetContentScaleFactor()
|
||||
self.SetCurrent(self.context)
|
||||
glViewport(0, 0, size.width, size.height)
|
||||
|
||||
|
||||
def OnPaint(self, event):
|
||||
dc = wx.PaintDC(self)
|
||||
self.SetCurrent(self.context)
|
||||
@@ -115,34 +117,79 @@ class MyCanvasBase(glcanvas.GLCanvas):
|
||||
self.init = True
|
||||
self.OnDraw()
|
||||
|
||||
|
||||
def OnMouseDown(self, evt):
|
||||
def OnMouseDown(self, event):
|
||||
if self.HasCapture():
|
||||
self.ReleaseMouse()
|
||||
self.CaptureMouse()
|
||||
self.x, self.y = self.lastx, self.lasty = evt.GetPosition()
|
||||
self.x, self.y = self.lastx, self.lasty = event.GetPosition()
|
||||
|
||||
def OnMouseUp(self, event):
|
||||
if self.HasCapture():
|
||||
self.ReleaseMouse()
|
||||
|
||||
def OnMouseUp(self, evt):
|
||||
self.ReleaseMouse()
|
||||
|
||||
|
||||
def OnMouseMotion(self, evt):
|
||||
if evt.Dragging() and evt.LeftIsDown():
|
||||
def OnMouseMotion(self, event):
|
||||
if event.Dragging() and event.LeftIsDown():
|
||||
self.lastx, self.lasty = self.x, self.y
|
||||
self.x, self.y = evt.GetPosition()
|
||||
self.x, self.y = event.GetPosition()
|
||||
self.Refresh(False)
|
||||
|
||||
|
||||
def ReadTexture(filename):
|
||||
# Load texture with PIL/PILLOW. RGBA png seems to load fine with pillow.
|
||||
## with Image.open(filename) as img:
|
||||
## imgWidth, imgHeight = img.size
|
||||
## img_data = img.tobytes("raw", "RGB", 0, -1)
|
||||
|
||||
# Load texture with wxPython.
|
||||
# Hmmm this seems to be wrong channel order or something for wx.Image
|
||||
# with png alpha when using RGBA. Oh well. We will send jpg Robin instead.
|
||||
img = wx.Image(filename)
|
||||
## if not img.HasAlpha():
|
||||
## img.InitAlpha()
|
||||
imgWidth, imgHeight = img.GetSize()
|
||||
img_data = bytes(img.GetData())
|
||||
return (imgWidth, imgHeight, img_data)
|
||||
|
||||
def GenerateTexture(imgWidth, imgHeight, img_data):
|
||||
textureID = glGenTextures(1)
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1)
|
||||
glBindTexture(GL_TEXTURE_2D, textureID)
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE)
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
|
||||
|
||||
# https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glTexImage2D.xhtml
|
||||
target = GL_TEXTURE_2D
|
||||
level = 0
|
||||
internalformat = GL_RGB # GL_RGBA
|
||||
width = imgWidth
|
||||
height = imgHeight
|
||||
border = 0
|
||||
format = GL_RGB # GL_RGBA
|
||||
type = GL_UNSIGNED_BYTE
|
||||
data = img_data
|
||||
glTexImage2D(target, level, internalformat, width, height, border, format, type, data)
|
||||
# https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glTexEnv.xml
|
||||
target = GL_TEXTURE_ENV
|
||||
pname = GL_TEXTURE_ENV_MODE
|
||||
params = GL_MODULATE
|
||||
glTexEnvf(target, pname, params)
|
||||
return textureID
|
||||
|
||||
|
||||
class CubeCanvas(MyCanvasBase):
|
||||
def InitGL(self):
|
||||
# set viewing projection
|
||||
# Set viewing projection.
|
||||
glMatrixMode(GL_PROJECTION)
|
||||
glFrustum(-0.5, 0.5, -0.5, 0.5, 1.0, 3.0)
|
||||
|
||||
# position viewer
|
||||
# Position viewer.
|
||||
glMatrixMode(GL_MODELVIEW)
|
||||
glTranslatef(0.0, 0.0, -2.0)
|
||||
|
||||
# position object
|
||||
# Position object.
|
||||
glRotatef(self.y, 1.0, 0.0, 0.0)
|
||||
glRotatef(self.x, 0.0, 1.0, 0.0)
|
||||
|
||||
@@ -150,18 +197,24 @@ class CubeCanvas(MyCanvasBase):
|
||||
glEnable(GL_LIGHTING)
|
||||
glEnable(GL_LIGHT0)
|
||||
|
||||
self.textureID = None
|
||||
path = os.path.abspath(os.path.join(os.path.dirname(__file__), 'bmp_source'))
|
||||
rd = 'robin.jpg'
|
||||
if os.path.exists(os.path.join(path, rd)):
|
||||
self.textureID = GenerateTexture(*ReadTexture(os.path.join(path, rd)))
|
||||
|
||||
|
||||
def OnDraw(self):
|
||||
# clear color and depth buffers
|
||||
# Clear color and depth buffers.
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
|
||||
|
||||
# draw six faces of a cube
|
||||
# Draw six faces of a cube.
|
||||
glBegin(GL_QUADS)
|
||||
glNormal3f( 0.0, 0.0, 1.0)
|
||||
glVertex3f( 0.5, 0.5, 0.5)
|
||||
glVertex3f(-0.5, 0.5, 0.5)
|
||||
glVertex3f(-0.5,-0.5, 0.5)
|
||||
glVertex3f( 0.5,-0.5, 0.5)
|
||||
## glNormal3f( 0.0, 0.0, 1.0)
|
||||
## glVertex3f( 0.5, 0.5, 0.5)
|
||||
## glVertex3f(-0.5, 0.5, 0.5)
|
||||
## glVertex3f(-0.5,-0.5, 0.5)
|
||||
## glVertex3f( 0.5,-0.5, 0.5)
|
||||
|
||||
glNormal3f( 0.0, 0.0,-1.0)
|
||||
glVertex3f(-0.5,-0.5,-0.5)
|
||||
@@ -194,6 +247,21 @@ class CubeCanvas(MyCanvasBase):
|
||||
glVertex3f(-0.5, 0.5,-0.5)
|
||||
glEnd()
|
||||
|
||||
if self.textureID:
|
||||
glEnable(GL_TEXTURE_2D)
|
||||
## glBindTexture(GL_TEXTURE_2D, self.textureID)
|
||||
glBegin(GL_QUADS)
|
||||
glNormal3f( 0.0, 0.0, 1.0)
|
||||
glTexCoord2f(0.0, 0.0)
|
||||
glVertex3fv((0.5, 0.5, 0.5))
|
||||
glTexCoord2f(1.0, 0.0)
|
||||
glVertex3fv((-0.5, 0.5, 0.5))
|
||||
glTexCoord2f(1.0, 1.0)
|
||||
glVertex3fv((-0.5,-0.5, 0.5))
|
||||
glTexCoord2f(0.0, 1.0)
|
||||
glVertex3fv((0.5,-0.5, 0.5))
|
||||
glEnd()
|
||||
|
||||
if self.size is None:
|
||||
self.size = self.GetClientSize()
|
||||
w, h = self.size
|
||||
@@ -210,7 +278,7 @@ class CubeCanvas(MyCanvasBase):
|
||||
class ConeCanvas(MyCanvasBase):
|
||||
def InitGL( self ):
|
||||
glMatrixMode(GL_PROJECTION)
|
||||
# camera frustrum setup
|
||||
# Camera frustrum setup.
|
||||
glFrustum(-0.5, 0.5, -0.5, 0.5, 1.0, 3.0)
|
||||
glMaterial(GL_FRONT, GL_AMBIENT, [0.2, 0.2, 0.2, 1.0])
|
||||
glMaterial(GL_FRONT, GL_DIFFUSE, [0.8, 0.8, 0.8, 1.0])
|
||||
@@ -226,35 +294,64 @@ class ConeCanvas(MyCanvasBase):
|
||||
glDepthFunc(GL_LESS)
|
||||
glEnable(GL_DEPTH_TEST)
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
|
||||
# position viewer
|
||||
# Position viewer.
|
||||
glMatrixMode(GL_MODELVIEW)
|
||||
# position viewer
|
||||
# Position viewer.
|
||||
glTranslatef(0.0, 0.0, -2.0);
|
||||
#
|
||||
glutInit(sys.argv)
|
||||
|
||||
|
||||
def OnDraw(self):
|
||||
# clear color and depth buffers
|
||||
# Clear color and depth buffers.
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
|
||||
# use a fresh transformation matrix
|
||||
# Use a fresh transformation matrix.
|
||||
glPushMatrix()
|
||||
# position object
|
||||
#glTranslate(0.0, 0.0, -2.0)
|
||||
# Position object.
|
||||
## glTranslate(0.0, 0.0, -2.0)
|
||||
glRotate(30.0, 1.0, 0.0, 0.0)
|
||||
glRotate(30.0, 0.0, 1.0, 0.0)
|
||||
|
||||
glTranslate(0, -1, 0)
|
||||
glRotate(250, 1, 0, 0)
|
||||
glutSolidCone(0.5, 1, 30, 5)
|
||||
|
||||
glEnable(GL_BLEND)
|
||||
glEnable(GL_POLYGON_SMOOTH)
|
||||
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, (0.5, 0.5, 1.0, 0.5))
|
||||
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 1.0)
|
||||
glShadeModel(GL_FLAT)
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)
|
||||
# glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)
|
||||
|
||||
quad = gluNewQuadric()
|
||||
base = .5
|
||||
top = 0.0
|
||||
height = 1.0
|
||||
slices = 16
|
||||
stacks = 16
|
||||
# stacks = 0
|
||||
if stacks:
|
||||
# This is the premade way to make a cone.
|
||||
gluCylinder(quad, base, top, height, slices, stacks)
|
||||
else:
|
||||
# Draw cone open ended without glu.
|
||||
tau = pi * 2
|
||||
glBegin(GL_TRIANGLE_FAN)
|
||||
centerX, centerY, centerZ = 0.0, 0.0, height
|
||||
glVertex3f(centerX, centerY, centerZ) # Center of circle.
|
||||
centerX, centerY, centerZ = 0.0, 0.0, 0.0
|
||||
for i in range(slices + 1):
|
||||
theta = tau * float(i) / float(slices) # Get the current angle.
|
||||
x = base * cos(theta) # Calculate the x component.
|
||||
y = base * sin(theta) # Calculate the y component.
|
||||
glVertex3f(x + centerX, y + centerY, centerZ) # Output vertex.
|
||||
glEnd()
|
||||
|
||||
glPopMatrix()
|
||||
glRotatef((self.y - self.lasty), 0.0, 0.0, 1.0);
|
||||
glRotatef((self.x - self.lastx), 1.0, 0.0, 0.0);
|
||||
# push into visible buffer
|
||||
# Push into visible buffer.
|
||||
self.SwapBuffers()
|
||||
|
||||
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -263,13 +360,10 @@ def runTest(frame, nb, log):
|
||||
return win
|
||||
|
||||
|
||||
|
||||
|
||||
overview = """\
|
||||
"""
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import sys,os
|
||||
import run
|
||||
|
||||
Reference in New Issue
Block a user