diff --git a/opengl/CyOpenGL.pyx b/opengl/CyOpenGL.pyx index 6ff78ebe..f4f7da16 100644 --- a/opengl/CyOpenGL.pyx +++ b/opengl/CyOpenGL.pyx @@ -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 = 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): """ @@ -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) diff --git a/opengl/common/error.pyx b/opengl/common/error.pyx new file mode 100644 index 00000000..5b19c762 --- /dev/null +++ b/opengl/common/error.pyx @@ -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)) diff --git a/opengl/common/string.pyx b/opengl/common/string.pyx new file mode 100644 index 00000000..d6c84f85 --- /dev/null +++ b/opengl/common/string.pyx @@ -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 = glGetString(gl_string_enums[string]) + return str.decode('ascii') if str else 'undefined' diff --git a/opengl/legacy/lighting.pyx b/opengl/legacy/lighting.pyx new file mode 100644 index 00000000..2ca2f567 --- /dev/null +++ b/opengl/legacy/lighting.pyx @@ -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() diff --git a/opengl/vector3.pyx b/opengl/vector3.pyx new file mode 100644 index 00000000..e8de5551 --- /dev/null +++ b/opengl/vector3.pyx @@ -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])