Skip to content

Commit

Permalink
Moving more OpenGL stuff into separate pyx files.
Browse files Browse the repository at this point in the history
  • Loading branch information
unhyperbolic committed Jan 29, 2024
1 parent 50a84eb commit 44bfccf
Show file tree
Hide file tree
Showing 5 changed files with 145 additions and 143 deletions.
147 changes: 4 additions & 143 deletions opengl/CyOpenGL.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -30,53 +30,8 @@ import tkinter as Tk_
##############################################################################
# Classes and utilties that work with any OpenGL


def get_gl_string(string):
cdef const char* str
gl_string_enums = {
'GL_VENDOR': GL_VENDOR,
'GL_RENDERER': GL_RENDERER,
'GL_VERSION': GL_VERSION,
'GL_EXTENSIONS': GL_EXTENSIONS,
'GL_SHADING_LANGUAGE_VERSION': GL_SHADING_LANGUAGE_VERSION}
if not glGetString(GL_VERSION):
raise RuntimeError(
'GL strings not available - is there a current OpenGL context?')
if string not in gl_string_enums:
raise ValueError(
"Invalid GL string. Must be one of %s." % ', '.join(
[ "'%s'" % k for k in sorted(gl_string_enums.keys()) ]))
str = <const char*>glGetString(gl_string_enums[string])
return str.decode('ascii') if str else 'undefined'

def clear_gl_errors():
"""
Clears any previous OpenGL errors.
"""

while glGetError() != GL_NO_ERROR:
pass

def print_gl_errors(msg):
"""
Prints all OpenGL errors using given message.
"""

while True:
err = glGetError()
if err == GL_NO_ERROR:
return
if err == GL_INVALID_ENUM:
k = "GL_INVALID_ENUM"
elif err == GL_INVALID_VALUE:
k = "GL_INVALID_VALUE"
elif err == GL_INVALID_OPERATION:
k = "GL_INVALID_OPERATION"
elif err == GL_INVALID_FRAMEBUFFER_OPERATION:
k = "GL_INVALID_FRAMEBUFFER_OPERATION"
else:
k = "GL_ENUM 0x%x" % err
print("Error %s in %s" % (k, msg))
include "common/string.pyx"
include "common/error.pyx"

class RawOpenGLWidget(Tk_.Widget, Tk_.Misc):
"""
Expand Down Expand Up @@ -249,106 +204,12 @@ class RawOpenGLWidget(Tk_.Widget, Tk_.Misc):
##############################################################################
# Non-OpenGL classes

cdef class vector3:
"""
A simple real 3-dimensional vector which supports addition,
subtraction and right multiplication or division by scalars.
Attributes include its norm and the square of its norm.
"""
cdef readonly double x, y, z, norm_squared, norm

def __cinit__(self, triple):
self.x, self.y, self.z = triple
self.norm_squared = self.x*self.x + self.y*self.y + self.z*self.z
self.norm = sqrt(self.norm_squared)

def __repr__(self):
"""
>>> vector3( (0, 1, 2) )
< 0.0, 1.0, 2.0 >
"""
return '< %s, %s, %s >'%(self.x, self.y, self.z)

def __add__(self, vector):
return vector3([self.x+vector.x, self.y+vector.y, self.z+vector.z])

def __sub__(self, vector):
return vector3([self.x-vector.x, self.y-vector.y, self.z-vector.z])

def __mul__(self, scalar):
return vector3([self.x*scalar, self.y*scalar, self.z*scalar])

def __div__(self, scalar):
return vector3([self.x/scalar, self.y/scalar, self.z/scalar])

def __truediv__(self, scalar):
return vector3([self.x/scalar, self.y/scalar, self.z/scalar])
include "vector3.pyx"

##############################################################################
# OpenGL utilities for legacy OpenGL (OpenGL 2.1)

def cyglSetStandardLighting():
"""
Sets up our default OpenGL environment.
"""

# Lighting intensities and location
cdef GLfloat* ambient = [0.75, 0.75, 0.75, 1.0]
cdef GLfloat* lightdiffuse = [0.8, 0.8, 0.8, 1.0]
cdef GLfloat* lightspecular = [0.3, 0.3, 0.3, 1.0]
# 2 units from the center, up and to the right
# we should be able to control the light
cdef GLfloat* lightposition0 = [0.3, 0.5, 3.0, 1.0]
cdef GLfloat* lightposition1 = [0.3, -0.5, -3.0, 1.0]

## Set parameters that apply to all objects:
# Remove hidden stuff
glEnable(GL_DEPTH_TEST)
# Allow transparency
# glEnable(GL_ALPHA_TEST)
glEnable(GL_BLEND)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
# Enable anti-aliasing of points lines and polygons
glEnable(GL_POINT_SMOOTH)
glEnable(GL_LINE_SMOOTH)
#Below call is deprecated and causes odd behavior on some systems.
#glEnable(GL_POLYGON_SMOOTH)
# Use lights and materials to determine colors
glEnable(GL_LIGHTING)
# Make the Color command control ambient and diffuse material colors
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE)
glEnable(GL_COLOR_MATERIAL)
# Use interpolated shading (although colors are constant on faces)
glShadeModel(GL_SMOOTH)
# Define the counter-clockwise (outer) face to be the front.
glFrontFace(GL_CCW)
# Rasterize front and back Faces
glDisable(GL_CULL_FACE)
## Set up lighting
# Allow different properties on fronts and backs
glLightModelf(GL_LIGHT_MODEL_TWO_SIDE, 1.0)
# Compute specular reflections from the eye
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, True)
# Ambient light intensity for the entire scene
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient)
# Enable two lights, with attenuation
glEnable(GL_LIGHT0)
glLightfv(GL_LIGHT0, GL_POSITION, lightposition0)
glLightfv(GL_LIGHT0, GL_DIFFUSE, lightdiffuse)
glLightfv(GL_LIGHT0, GL_SPECULAR, lightspecular)
glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 1.0)
glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 0.1)
glLightf(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, 0.08)
glDisable(GL_LIGHT1)
glLightfv(GL_LIGHT1, GL_POSITION, lightposition1)
glLightfv(GL_LIGHT1, GL_DIFFUSE, lightdiffuse)
glLightfv(GL_LIGHT1, GL_SPECULAR, lightspecular)
glLightf(GL_LIGHT1, GL_CONSTANT_ATTENUATION, 1.0)
glLightf(GL_LIGHT1, GL_LINEAR_ATTENUATION, 0.1)
glLightf(GL_LIGHT1, GL_QUADRATIC_ATTENUATION, 0.08)
# Use the Model View Matrix
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
include "legacy/lighting.pyx"

##############################################################################
# OpenGL objects for legacy OpenGL (OpenGL 2.1)
Expand Down
28 changes: 28 additions & 0 deletions opengl/common/error.pyx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
def clear_gl_errors():
"""
Clears any previous OpenGL errors.
"""

while glGetError() != GL_NO_ERROR:
pass

def print_gl_errors(msg):
"""
Prints all OpenGL errors using given message.
"""

while True:
err = glGetError()
if err == GL_NO_ERROR:
return
if err == GL_INVALID_ENUM:
k = "GL_INVALID_ENUM"
elif err == GL_INVALID_VALUE:
k = "GL_INVALID_VALUE"
elif err == GL_INVALID_OPERATION:
k = "GL_INVALID_OPERATION"
elif err == GL_INVALID_FRAMEBUFFER_OPERATION:
k = "GL_INVALID_FRAMEBUFFER_OPERATION"
else:
k = "GL_ENUM 0x%x" % err
print("Error %s in %s" % (k, msg))
17 changes: 17 additions & 0 deletions opengl/common/string.pyx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
def get_gl_string(string):
cdef const char* str
gl_string_enums = {
'GL_VENDOR': GL_VENDOR,
'GL_RENDERER': GL_RENDERER,
'GL_VERSION': GL_VERSION,
'GL_EXTENSIONS': GL_EXTENSIONS,
'GL_SHADING_LANGUAGE_VERSION': GL_SHADING_LANGUAGE_VERSION}
if not glGetString(GL_VERSION):
raise RuntimeError(
'GL strings not available - is there a current OpenGL context?')
if string not in gl_string_enums:
raise ValueError(
"Invalid GL string. Must be one of %s." % ', '.join(
[ "'%s'" % k for k in sorted(gl_string_enums.keys()) ]))
str = <const char*>glGetString(gl_string_enums[string])
return str.decode('ascii') if str else 'undefined'
62 changes: 62 additions & 0 deletions opengl/legacy/lighting.pyx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
def cyglSetStandardLighting():
"""
Sets up our default OpenGL environment.
"""

# Lighting intensities and location
cdef GLfloat* ambient = [0.75, 0.75, 0.75, 1.0]
cdef GLfloat* lightdiffuse = [0.8, 0.8, 0.8, 1.0]
cdef GLfloat* lightspecular = [0.3, 0.3, 0.3, 1.0]
# 2 units from the center, up and to the right
# we should be able to control the light
cdef GLfloat* lightposition0 = [0.3, 0.5, 3.0, 1.0]
cdef GLfloat* lightposition1 = [0.3, -0.5, -3.0, 1.0]

## Set parameters that apply to all objects:
# Remove hidden stuff
glEnable(GL_DEPTH_TEST)
# Allow transparency
# glEnable(GL_ALPHA_TEST)
glEnable(GL_BLEND)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
# Enable anti-aliasing of points lines and polygons
glEnable(GL_POINT_SMOOTH)
glEnable(GL_LINE_SMOOTH)
#Below call is deprecated and causes odd behavior on some systems.
#glEnable(GL_POLYGON_SMOOTH)
# Use lights and materials to determine colors
glEnable(GL_LIGHTING)
# Make the Color command control ambient and diffuse material colors
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE)
glEnable(GL_COLOR_MATERIAL)
# Use interpolated shading (although colors are constant on faces)
glShadeModel(GL_SMOOTH)
# Define the counter-clockwise (outer) face to be the front.
glFrontFace(GL_CCW)
# Rasterize front and back Faces
glDisable(GL_CULL_FACE)
## Set up lighting
# Allow different properties on fronts and backs
glLightModelf(GL_LIGHT_MODEL_TWO_SIDE, 1.0)
# Compute specular reflections from the eye
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, True)
# Ambient light intensity for the entire scene
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient)
# Enable two lights, with attenuation
glEnable(GL_LIGHT0)
glLightfv(GL_LIGHT0, GL_POSITION, lightposition0)
glLightfv(GL_LIGHT0, GL_DIFFUSE, lightdiffuse)
glLightfv(GL_LIGHT0, GL_SPECULAR, lightspecular)
glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 1.0)
glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 0.1)
glLightf(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, 0.08)
glDisable(GL_LIGHT1)
glLightfv(GL_LIGHT1, GL_POSITION, lightposition1)
glLightfv(GL_LIGHT1, GL_DIFFUSE, lightdiffuse)
glLightfv(GL_LIGHT1, GL_SPECULAR, lightspecular)
glLightf(GL_LIGHT1, GL_CONSTANT_ATTENUATION, 1.0)
glLightf(GL_LIGHT1, GL_LINEAR_ATTENUATION, 0.1)
glLightf(GL_LIGHT1, GL_QUADRATIC_ATTENUATION, 0.08)
# Use the Model View Matrix
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
34 changes: 34 additions & 0 deletions opengl/vector3.pyx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
cdef class vector3:
"""
A simple real 3-dimensional vector which supports addition,
subtraction and right multiplication or division by scalars.
Attributes include its norm and the square of its norm.
"""
cdef readonly double x, y, z, norm_squared, norm

def __cinit__(self, triple):
self.x, self.y, self.z = triple
self.norm_squared = self.x*self.x + self.y*self.y + self.z*self.z
self.norm = sqrt(self.norm_squared)

def __repr__(self):
"""
>>> vector3( (0, 1, 2) )
< 0.0, 1.0, 2.0 >
"""
return '< %s, %s, %s >'%(self.x, self.y, self.z)

def __add__(self, vector):
return vector3([self.x+vector.x, self.y+vector.y, self.z+vector.z])

def __sub__(self, vector):
return vector3([self.x-vector.x, self.y-vector.y, self.z-vector.z])

def __mul__(self, scalar):
return vector3([self.x*scalar, self.y*scalar, self.z*scalar])

def __div__(self, scalar):
return vector3([self.x/scalar, self.y/scalar, self.z/scalar])

def __truediv__(self, scalar):
return vector3([self.x/scalar, self.y/scalar, self.z/scalar])

0 comments on commit 44bfccf

Please sign in to comment.