def init_opengl(self): """ initialize the opengl settings to render the scene """ self.inverseModelView = numpy.identity(4) self.modelView = numpy.identity(4) glEnable(GL_CULL_FACE) glCullFace(GL_BACK) glEnable(GL_DEPTH_TEST) glDepthFunc(GL_LESS) glEnable(GL_LIGHT0) glLightfv(GL_LIGHT0, GL_POSITION, GLfloat_4(0, 0, 1, 0)) glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, GLfloat_3(0, 0, -1)) glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE) glEnable(GL_COLOR_MATERIAL) glClearColor(0.4, 0.4, 0.4, 0.0)
def init_opengl(self): #model view matrix self.inverseModelView = numpy.identity(4) #its anti-matrix self.modelView = numpy.identity(4) #open tichu effect glEnable(GL_CULL_FACE) #to not rend invisible part glCullFace(GL_BACK) #open depth test glEnable(GL_DEPTH_TEST) #objects being covered ot to rend glDepthFunc(GL_LESS) #open light 0 glEnable(GL_LIGHT0) #to set the position of light glLightfv(GL_LIGHT0, GL_POSITION, GLfloat_4(0, 0, 1, 0)) #to set the direction that light sheds at glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, GLfloat_3(0, 0, -1)) #to set material color glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE) glEnable(GL_COLOR_MATERIAL) #set the color of a clear-screen glClearColor(0.4, 0.4, 0.4, 0.0)
def init_opengl(self): """ 初始化opengl的配置 """ #模型视图矩阵 self.inverseModelView = numpy.identity(4) #模型视图矩阵的逆矩阵 self.modelView = numpy.identity(4) #开启剔除操作效果 glEnable(GL_CULL_FACE) #取消对多边形背面进行渲染的计算(看不到的部分不渲染) glCullFace(GL_BACK) #开启深度测试 glEnable(GL_DEPTH_TEST) #测试是否被遮挡,被遮挡的物体不予渲染 glDepthFunc(GL_LESS) #启用0号光源 glEnable(GL_LIGHT0) #设置光源的位置 glLightfv(GL_LIGHT0, GL_POSITION, GLfloat_4(0, 0, 1, 0)) #设置光源的照射方向 glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, GLfloat_3(0, 0, -1)) #设置材质颜色 glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE) glEnable(GL_COLOR_MATERIAL) #设置清屏的颜色 glClearColor(0.4, 0.4, 0.4, 0.0)
def init(): glShadeModel(GL_SMOOTH) glClearColor(0.0, 0.0, 0.0, 0.0) glClearDepth(1.0) glEnable(GL_DEPTH_TEST) glDepthFunc(GL_LEQUAL) glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)
def _render(self) -> None: """ Render the whole scene here. Note that, this is a private function and should not be overriden unless you really know what you are dealing with. """ # Disable Depth Test to draw background at the very back of the scene glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) # type: ignore self.background.render() glEnable(GL_DEPTH_TEST) glDepthFunc(GL_LESS) proj, view = self.active_observer.render() self.grid.render(proj, view, self.lights) self._render_lock = True for object in self.objects: self.objects[object].render(proj, view, self.lights) for object in self.huds: self.huds[object].render(proj, view, self.lights) self._render_lock = False for test in self._collision_detectors: test.check() self.__fps_counter += 1 if self.__timer == -1: self.__timer = time.time() diff = time.time() - self.__timer if diff > 1: self.__timer = time.time() self.fps = self.__fps_counter self.__fps_counter = 0
def prepare(self) -> None: """ Clears the screen before rendering the next frame. """ glClearColor(0.0, 0.0, 0.0, 1.0) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) glDisable(GL_BLEND) # glEnable(GL_DEPTH_TEST) glDepthFunc(GL_NEVER)
def __enable_depth_test(self): """Enable depth test and faces culling. Needed to not render invisible vertices and triangles. """ glDepthMask(GL_TRUE) glDepthFunc(GL_LESS) glEnable(GL_DEPTH_TEST) glEnable(GL_STENCIL_TEST)
def initializeGL(self): glClearColor(*self.color_background) glClearDepth(1.0) glDepthFunc(GL_LESS) glEnable(GL_DEPTH_TEST) glShadeModel(GL_SMOOTH) glMatrixMode(GL_PROJECTION) glLoadIdentity() glMatrixMode(GL_MODELVIEW)
def __enable_depth_test(self): """Enable depth test and faces culling. Needed to not render invisible vertices and triangles. """ glDepthMask(GL_TRUE) glDepthFunc(GL_LESS) glCullFace(GL_FRONT) glEnable(GL_DEPTH_TEST) glEnable(GL_STENCIL_TEST)
def initializeGL(self): self.resizeGL(self.width(), self.height()) glEnable(GL_DEPTH_TEST) glDepthFunc(GL_LEQUAL) # lighting light_position = [1.0, 1.0, 2.0, 0.0] glLight(GL_LIGHT0, GL_POSITION, light_position) glMaterialfv(GL_FRONT, GL_SPECULAR, [1.0, 1.0, 1.0, 1.0]) glMaterialf(GL_FRONT, GL_SHININESS, 100.0)
def initializeGL(self): # TODO: correct background color glClearColor(*self.color_background) glClearDepth(1.0) glDepthFunc(GL_LESS) glEnable(GL_DEPTH_TEST) glShadeModel(GL_SMOOTH) glMatrixMode(GL_PROJECTION) glLoadIdentity() glMatrixMode(GL_MODELVIEW)
def __update(self, widget): gldrawable = widget.get_gl_drawable() glcontext = widget.get_gl_context() # OpenGL begin. if not gldrawable.gl_begin(glcontext): return glClearColor(0.0, 0.0, 0.0, 1.0) glClearDepth(1.0) glDepthFunc(GL_LESS) # The type of depth test to do glEnable(GL_DEPTH_TEST | GL_LINE_SMOOTH) # Turn on depth testing. gldrawable.gl_end() # OpenGL end return
def main(): window = initWindow() classicProgram, normalMapProgram, skyboxProgram, asteroidProgram = initShaders() glEnable(GL_DEPTH_TEST) glDepthFunc(GL_LESS) # Initialize objects planets, spaceship, skybox, belt = initObjects(classicProgram, normalMapProgram, skyboxProgram, asteroidProgram) projMatrix = mat4.perspective_projection(60, float(WIDTH/HEIGHT), 0.1, 10000.0, dtype='f') eye, viewMatrix = initCamera() dt, oldTime = 0.0, glfw.GetTime() animation_speed = 800 while not glfw.WindowShouldClose(window): glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) currentTime = glfw.GetTime() dt = currentTime - oldTime oldTime = currentTime hAngle, vAngle, eye, direction, right, up, viewMatrix, animation_speed = getNewViewMatrixAndEye(window, animation_speed, dt, eye, WIDTH, HEIGHT) for planet in planets: planet.update(animation_speed) planet.draw(eye, viewMatrix, projMatrix) spaceship.update(eye, direction, right, up, hAngle, vAngle) spaceship.draw(eye, viewMatrix, projMatrix) belt.update(0.1) belt.draw(eye, viewMatrix, projMatrix) skybox.draw(viewMatrix, projMatrix) # Swap front and back buffers glfw.SwapBuffers(window) # Poll for and process events glfw.PollEvents() glfw.Terminate()
def initialize_draw(self): self.quadric = gluNewQuadric() gluQuadricNormals(self.quadric, GLU_SMOOTH) self.set_specular(True) self.set_bright(False) glLight(GL_LIGHT0, GL_SPECULAR, [0.7, 0.7, 0.7, 1.0]) glLight(GL_LIGHT0, GL_AMBIENT, [0.1, 0.1, 0.1, 1.0]) glLight(GL_LIGHT0, GL_POSITION, [1.0, 1.0, 3.0, 0.0]) glEnable(GL_LIGHT0) glEnable(GL_LIGHTING) glDepthFunc(GL_LESS) glEnable(GL_DEPTH_TEST) glCullFace(GL_BACK) VisBackend.initialize_draw(self) self.tool.initialize_gl()
def initializeGL(self): glEnable(GL_DEPTH_TEST) glDepthFunc(GL_LEQUAL) # glDepthMask(GL_TRUE) IMAGE_EXTENSIONS = '.png', '.bmp', '.tga' textureFolder = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'Textures') if os.path.exists(textureFolder): for texture in os.listdir(textureFolder): fname, ext = os.path.splitext(texture) if ext.lower() in IMAGE_EXTENSIONS: self._textures[fname] = loadImage(os.path.join(textureFolder, texture)) self._prevTime = time.time() self._timer.kick()
def init_opengl(self): """ initialize the opengl settings to render the scene """ self.inverseModelView = numpy.identity(4) self.modelView = numpy.identity(4) glEnable(GL_CULL_FACE) glCullFace(GL_BACK) glEnable(GL_DEPTH_TEST) glDepthFunc(GL_LESS) glEnable(GL_LIGHT0) glLightfv(GL_LIGHT0, GL_POSITION, GLfloat_4(0, 0, 1, 0)) glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, GLfloat_3(0, 0, -1)) glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE) glEnable(GL_COLOR_MATERIAL) glClearColor(1.0, 1.0, 1.0, 0.0)
def init_opengl(self) -> bool: """Initialize and set OpenGL capabilities. Returns: True if initialized without error, False otherwise. """ if self._gl_initialized: return True if self._context is None: return False glClearColor(*self.background_color) glClearDepth(1.0) glDepthFunc(GL_LESS) glEnable(GL_DEPTH_TEST) glEnable(GL_CULL_FACE) glEnable(GL_BLEND) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) # set antialiasing glEnable(GL_LINE_SMOOTH) glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE) glEnable(GL_COLOR_MATERIAL) glEnable(GL_MULTISAMPLE) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL) self.create_vaos() # compile shader programs self._shaders['default'] = shaderlib.compile_shader(*shaderlib.default) self._shaders['single_color'] = shaderlib.compile_shader( *shaderlib.single_color) self._shaders['instanced_model_color'] = shaderlib.compile_shader( *shaderlib.instanced_model_color) self._shaders['instanced_picking'] = shaderlib.compile_shader( *shaderlib.instanced_picking) self._shaders['diffuse'] = shaderlib.compile_shader(*shaderlib.diffuse) self._shaders['solid'] = shaderlib.compile_shader(*shaderlib.solid) self._gl_initialized = True return True
def initializeGL(self): # We call this right after our OpenGL window is created. glClearColor(1.0, 1.0, 1.0, 1.0) glClearDepth(1.0) glDepthFunc(GL_LESS) glEnable(GL_DEPTH_TEST) glShadeModel(GL_SMOOTH) glEnable(GL_NORMALIZE) light_position = (0., 0., 1., 0.) white_light = (1., 1., 1., 0.501) d_light = (1., 1., 1., 0.01) spec = (1., 1., 1., 0.08) glLightfv(GL_LIGHT0, GL_POSITION, light_position) glLightfv(GL_LIGHT0, GL_AMBIENT, white_light) #glLightfv(GL_LIGHT0, GL_DIFFUSE, d_light) glLightfv(GL_LIGHT0, GL_SPECULAR, spec) glEnable(GL_LIGHTING) glEnable(GL_LIGHT0) glEnable(GL_BLEND) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) #glBlendFunc(GL_SRC_ALPHA,GL_ONE) glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE) glEnable(GL_COLOR_MATERIAL) glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST) glMatrixMode(GL_PROJECTION) glLoadIdentity() gluPerspective( 45.0, float(self.size().height()) / float(self.size().width()), 0.1, 1000000.0) glMatrixMode(GL_MODELVIEW) glLoadIdentity() self.rotation = [0.0, 0.0] self.mesh.prepDraw()
def initializeGL(self): # We call this right after our OpenGL window is created. glClearColor(1.0, 1.0, 1.0, 1.0) glClearDepth(1.0) glDepthFunc(GL_LESS) glEnable(GL_DEPTH_TEST) glShadeModel(GL_SMOOTH) glEnable(GL_NORMALIZE) light_position = (0., 0., 1., 0.) white_light = (1., 1., 1., 0.501) d_light = (1., 1., 1., 0.01) spec = (1., 1., 1., 0.08) glLightfv(GL_LIGHT0, GL_POSITION, light_position) glLightfv(GL_LIGHT0, GL_AMBIENT, white_light) #glLightfv(GL_LIGHT0, GL_DIFFUSE, d_light) glLightfv(GL_LIGHT0, GL_SPECULAR, spec) glEnable(GL_LIGHTING) glEnable(GL_LIGHT0) glEnable(GL_BLEND) glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA) #glBlendFunc(GL_SRC_ALPHA,GL_ONE) glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE) glEnable(GL_COLOR_MATERIAL) glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST) glMatrixMode(GL_PROJECTION) glLoadIdentity() gluPerspective(45.0, float(self.size().height())/ float(self.size().width()), 0.1, 1000000.0) glMatrixMode(GL_MODELVIEW) glLoadIdentity() self.rotation = [0.0, 0.0] self.mesh.prepDraw()
def init_opengl(self): """A general OpenGL initialization function. Sets all of the initial parameters. We call this right after our OpenGL window is created. """ glClearColor(0.0, 0.0, 0.0, 1.0) # This Will Clear The Background Color To Black glClearDepth(1.0) # Enables Clearing Of The Depth Buffer glDepthFunc(GL_LEQUAL) # The Type Of Depth Test To Do glEnable(GL_DEPTH_TEST) # Enables Depth Testing glShadeModel(GL_SMOOTH) glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST) # Really Nice Perspective Calculations glEnable(GL_LIGHT0) glEnable(GL_LIGHTING) glEnable(GL_COLOR_MATERIAL) glEnable( GL_NORMALIZE) # important since we rescale the modelview matrix return True
def paintGL(self): """ Called by QtGL when redrawing is needed. For every redraw, color & depth butter are cleared, view projection are reset, view location & orientation are also reset. """ if not self.initialised: return self._call_whatever_waits_for_gl_context_current() #bruce 071103 glDepthFunc(GL_LEQUAL) self.setDepthRange_setup_from_debug_pref() self.setDepthRange_Normal() from utilities.debug_prefs import debug_pref, Choice_boolean_False if debug_pref("always setup_lighting?", Choice_boolean_False): #bruce 060415 added debug_pref("always setup_lighting?"), in GLPane and ThumbView [KEEP DFLTS THE SAME!!]; # see comments in GLPane_lighting_methods self._setup_lighting() #bruce 060415 added this call self.backgroundColor = env.prefs[backgroundColor_prefs_key] c = self.backgroundColor glClearColor(c[0], c[1], c[2], 0.0) del c glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) self.backgroundGradient = env.prefs[backgroundGradient_prefs_key] if self.backgroundGradient: glMatrixMode(GL_PROJECTION) glLoadIdentity() glMatrixMode(GL_MODELVIEW) glLoadIdentity() # Setting to blue sky (default), but might change to something else _bgGradient = bluesky if self.backgroundGradient == bgEVENING_SKY: _bgGradient = eveningsky if self.backgroundGradient == bgSEAGREEN: _bgGradient = bg_seagreen drawFullWindow(_bgGradient) # gradient color self._setup_projection() self._setup_modelview() ## glMatrixMode(GL_MODELVIEW) ## glLoadIdentity() ## glTranslatef(0.0, 0.0, - self.vdist) ## q = self.quat ## glRotatef(q.angle * 180.0 / math.pi, q.x, q.y, q.z) ## glTranslatef(self.pov[0], self.pov[1], self.pov[2]) if self.model_is_valid(): #bruce 080117 [testing this at start of paintGL to skip most of it]: # precaution (perhaps a bugfix); see similar code in GLPane. # # update, bruce 080220: this may have caused a bug by making this # not draw a blank-background graphics area when it has no model. # E.g. the partlib has no model when first entered. # Fixing this by only not drawing the model itself in that case [UNTESTED]. # (The GLPane always has a model, so has no similar issue.) # # I'm not moving the coordinate transforms into this if statement, # since I don't know if they might be depended on by non-paintGL # drawing (e.g. for highlighting, which btw is called "selection" # in some method names and comments in this file). [bruce 080220] self._drawModel_using_DrawingSets()
def do_glselect_if_wanted(self): # bruce 070919 split this out """ Do the glRenderMode(GL_SELECT) drawing, and/or the glname-color drawing for shader primitives, used to guess which object might be under the mouse, for one drawing frame, if desired for this frame. Report results by storing candidate mouseover objects in self.glselect_dict. The depth buffer is initially clear, and must be clear when we're done as well. @note: does not do related individual object depth/stencil buffer drawing -- caller must do that on some or all of the objects we store into self.glselect_dict. """ if self.glselect_wanted: # note: this will be reset below. ###@@@ WARNING: The original code for this, here in GLPane, has been duplicated and slightly modified # in at least three other places (search for glRenderMode to find them). This is bad; common code # should be used. Furthermore, I suspect it's sometimes needlessly called more than once per frame; # that should be fixed too. [bruce 060721 comment] wX, wY, self.targetdepth = self.glselect_wanted # wX, wY is the point to do the hit-test at # targetdepth is the depth buffer value to look for at that point, during ordinary drawing phase # (could also be used to set up clipping planes to further restrict hit-test, but this isn't yet done) # (Warning: targetdepth could in theory be out of date, if more events come between bareMotion # and the one caused by its gl_update, whose paintGL is what's running now, and if those events # move what's drawn. Maybe that could happen with mousewheel events or (someday) with keypresses # having a graphical effect. Ideally we'd count intentional redraws, and disable this picking in that case.) self.wX, self.wY = wX, wY self.glselect_wanted = 0 pwSize = 1 # Pick window size. Russ 081128: Was 3. # Bruce: Replace 3, 3 with 1, 1? 5, 5? not sure whether this will # matter... in principle should have no effect except speed. # Russ: For glname rendering, 1x1 is better because it doesn't # have window boundary issues. We get the coords of a single # pixel in the window for the mouse position. # bruce 050615 for use by nodes which want to set up their own projection matrix. self.current_glselect = (wX, wY, pwSize, pwSize) self._setup_projection(glselect=self.current_glselect) # option makes it use gluPickMatrix # Russ 081209: Added. debugPicking = debug_pref("GLPane: debug mouseover picking?", Choice_boolean_False, prefs_key=True) if self.enabled_shaders(): # TODO: optimization: find an appropriate place to call # _compute_frustum_planes. [bruce 090105 comment] # Russ 081122: There seems to be no way to access the GL name # stack in shaders. Instead, for mouseover, draw shader # primitives with glnames as colors in glRenderMode(GL_RENDER), # then read back the pixel color (glname) and depth value. # Temporarily replace the full-size viewport with a little one # at the mouse location, matching the pick matrix location. # Otherwise, we will draw a closeup of that area into the whole # window, rather than a few pixels. (This wasn't needed when we # only used GL_SELECT rendering mode here, because that doesn't # modify the frame buffer -- it just returns hits by graphics # primitives when they are inside the clipping boundaries.) # # (Don't set the viewport *before* _setup_projection(), since # that method needs to read the current whole-window viewport # to set up glselect. See explanation in its docstring.) savedViewport = glGetIntegerv(GL_VIEWPORT) glViewport(wX, wY, pwSize, pwSize) # Same as current_glselect. # First, clear the pixel RGBA to zeros and a depth of 1.0 (far), # so we won't confuse a color with a glname if there are # no shader primitives drawn over this pixel. saveDepthFunc = glGetInteger(GL_DEPTH_FUNC) glDepthFunc(GL_ALWAYS) glWindowPos3i(wX, wY, 1) # Note the Z coord. gl_format, gl_type = GL_RGBA, GL_UNSIGNED_BYTE glDrawPixels(pwSize, pwSize, gl_format, gl_type, (0, 0, 0, 0)) glDepthFunc(saveDepthFunc) # needed, though we'll change it again # We must be in glRenderMode(GL_RENDER) (as usual) when this is called. # Note: _setup_projection leaves the matrix mode as GL_PROJECTION. glMatrixMode(GL_MODELVIEW) shaders = self.enabled_shaders() try: # Set flags so that we will use glnames-as-color mode # in shaders, and draw only shader primitives. # (Ideally we would also draw all non-shader primitives # as some other color, unequal to all glname colors # (or derived from a fake glname for that purpose), # in order to obscure shader primitives where appropriate. # This is intended to be done but is not yet implemented. # [bruce 090105 addendum]) for shader in shaders: shader.setPicking(True) self.set_drawing_phase("glselect_glname_color") for stereo_image in self.stereo_images_to_draw: self._enable_stereo(stereo_image) try: self._do_graphicsMode_Draw(for_mouseover_highlighting=True) # note: we can't disable depth writing here, # since we need it to make sure the correct # shader object comes out on top, or is # obscured by a DL object. Instead, we'll # clear the depth buffer again (at this pixel) # below. [bruce 090105] finally: self._disable_stereo() except: print_compact_traceback( "exception in or around _do_graphicsMode_Draw() during glname_color;" "drawing ignored; restoring modelview matrix: " ) # REVIEW: what does "drawing ignored" mean, in that message? [bruce 090105 question] glMatrixMode(GL_MODELVIEW) self._setup_modelview() ### REVIEW: correctness of this is unreviewed! # now it's important to continue, at least enough to restore other gl state pass for shader in shaders: shader.setPicking(False) self.set_drawing_phase("?") # Restore the viewport. glViewport(savedViewport[0], savedViewport[1], savedViewport[2], savedViewport[3]) # Read pixel value from the back buffer and re-assemble glname. glFinish() # Make sure the drawing has completed. # REVIEW: is this glFinish needed? [bruce 090105 comment] rgba = glReadPixels(wX, wY, 1, 1, gl_format, gl_type)[0][0] pixZ = glReadPixelsf(wX, wY, 1, 1, GL_DEPTH_COMPONENT)[0][0] # Clear our depth pixel to 1.0 (far), so we won't mess up the # subsequent call of preDraw_glselect_dict. # (The following is not the most direct way, but it ought to work. # Note that we also clear the color pixel, since (being a glname) # it has no purpose remaining in the color buffer -- either it's # changed later, or, if not, that's a bug, but we'd rather have # it black than a random color.) [bruce 090105 bugfix] glDepthFunc(GL_ALWAYS) glWindowPos3i(wX, wY, 1) # Note the Z coord. glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE) gl_format, gl_type = GL_RGBA, GL_UNSIGNED_BYTE glDrawPixels(pwSize, pwSize, gl_format, gl_type, (0, 0, 0, 0)) glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE) glDepthFunc(saveDepthFunc) # Comes back sign-wrapped, in spite of specifying UNSIGNED_BYTE. def us(b): if b < 0: return 256 + b return b bytes = tuple([us(b) for b in rgba]) ##glname = (bytes[0] << 24 | bytes[1] << 16 | bytes[2] << 8 | bytes[3]) ## Temp fix: Ignore the last byte, which always comes back 255 on Windows. glname = bytes[0] << 16 | bytes[1] << 8 | bytes[2] if debugPicking: print ( "shader mouseover xy %d %d, " % (wX, wY) + "rgba bytes (0x%x, 0x%x, 0x%x, 0x%x), " % bytes + "Z %f, glname 0x%x" % (pixZ, glname) ) pass ### XXX This ought to be better-merged with the DL selection below. if glname: obj = self.object_for_glselect_name(glname) if debugPicking: print "shader mouseover glname=%r, obj=%r." % (glname, obj) if obj is None: # REVIEW: does this happen for mouse over a non-shader primitive? # [bruce 090105 question] #### Note: this bug is common. Guess: we are still drawing # ordinary colors for some primitives and/or for the # background, and they are showing up here and confusing # us. To help debug this, print the color too. But testing # shows it's not so simple -- e.g. for rung bonds it happens # where shader sphere and cylinder overlap, but not on either # one alone; for strand bonds it also happens on the bonds alone # (tested in Build DNA, in or not in Insert DNA). # [bruce 090218] # # Update: Since it's so common, I need to turn it off by default. # Q: is the situation safe? # A: if a color looks like a real glname by accident, # we'll get some random candidate object -- perhaps a killed one # or from a different Part or even a closed assy -- # and try to draw it. That doesn't sound very safe. Unfortunately # there is no perfect way to filter selobjs for safety, in the # current still-informal Selobj_API. The best approximation is # selobj_still_ok, and it should always say yes for the usual kinds, # so I'll add it as a check in the 'else' clause below. # [bruce 090311] if debug_flags.atom_debug: print "bug: object_for_glselect_name returns None for glname %r (color %r)" % ( glname, bytes, ) else: if self.graphicsMode.selobj_still_ok(obj): # bruce 090311 added condition, explained above self.glselect_dict[id(obj)] = obj else: # This should be rare but possible. Leave it on briefly and see # if it's ever common. If possible, gate it by atom_debug before # the release. [bruce 090311] print "fyi: glname-color selobj %r rejected since not selobj_still_ok" % obj pass pass pass if self._use_frustum_culling: self._compute_frustum_planes() # piotr 080331 - the frustum planes have to be setup after the # projection matrix is setup. I'm not sure if there may # be any side effects - see the comment below about # possible optimization. glSelectBuffer(self.SIZE_FOR_glSelectBuffer) # Note: this allocates a new select buffer, # and glRenderMode(GL_RENDER) returns it and forgets it, # so it's required before *each* call of glRenderMode(GL_SELECT) + # glRenderMode(GL_RENDER), not just once to set the size. # Ref: http://pyopengl.sourceforge.net/documentation/opengl_diffs.html # [bruce 080923 comment] glInitNames() # REVIEW: should we also set up a clipping plane just behind the # hit point, as (I think) is done in ThumbView, to reduce the # number of candidate objects? This might be a significant # optimization, though I don't think it eliminates the chance # of having multiple candidates. [bruce 080917 comment] glRenderMode(GL_SELECT) glMatrixMode(GL_MODELVIEW) try: self.set_drawing_phase("glselect") # bruce 070124 for stereo_image in self.stereo_images_to_draw: self._enable_stereo(stereo_image) try: self._do_graphicsMode_Draw(for_mouseover_highlighting=True) finally: self._disable_stereo() except: print_compact_traceback( "exception in or around _do_graphicsMode_Draw() during GL_SELECT; " "ignored; restoring modelview matrix: " ) glMatrixMode(GL_MODELVIEW) self._setup_modelview() ### REVIEW: correctness of this is unreviewed! # now it's important to continue, at least enough to restore other gl state self._frustum_planes_available = False # piotr 080331 # just to be safe and not use the frustum planes computed for # the pick matrix self.set_drawing_phase("?") self.current_glselect = False # REVIEW: On systems with no stencil buffer, I think we'd also need # to draw selobj here in highlighted form (in case that form is # bigger than when it's not highlighted), or (easier & faster) # just always pretend it passes the hit test and add it to # glselect_dict -- and, make sure to give it "first dibs" for being # the next selobj. I'll implement some of this now (untested when # no stencil buffer) but not yet all. [bruce 050612] selobj = self.selobj if selobj is not None: self.glselect_dict[id(selobj)] = selobj # (review: is the following note correct?) # note: unneeded, if the func that looks at this dict always # tries selobj first (except for a kluge near # "if self.glselect_dict", commented on below) glFlush() hit_records = list(glRenderMode(GL_RENDER)) if debugPicking: print "DLs %d hits" % len(hit_records) for (near, far, names) in hit_records: # see example code, renderpass.py ## print "hit record: near, far, names:", near, far, names # e.g. hit record: near, far, names: 1439181696 1453030144 (1638426L,) # which proves that near/far are too far apart to give actual depth, # in spite of the 1- or 3-pixel drawing window (presumably they're vertices # taken from unclipped primitives, not clipped ones). del near, far if 1: # partial workaround for bug 1527. This can be removed once that bug (in drawer.py) # is properly fixed. This exists in two places -- GLPane.py and modes.py. [bruce 060217] if names and names[-1] == 0: print "%d(g) partial workaround for bug 1527: removing 0 from end of namestack:" % env.redraw_counter, names names = names[:-1] if names: # For now, we only use the last element of names, # though (as of long before 080917) it is often longer: # - some code pushes the same name twice (directly and # via ColorSorter) (see 060725 debug print below); # - chunks push a name even when they draw atoms/bonds # which push their own names (see 080411 comment below). # # Someday: if we ever support "name/subname paths" we'll # probably let first name interpret the remaining ones. # In fact, if nodes change projection or viewport for # their kids, and/or share their kids, they'd need to # push their own names on the stack, so we'd know how # to redraw the kids, or which ones are meant when they # are shared. if debug_flags.atom_debug and len(names) > 1: # bruce 060725 if len(names) == 2 and names[0] == names[1]: if not env.seen_before("dual-names bug"): # this happens for Atoms (colorsorter bug??) print "debug (once-per-session message): why are some glnames duplicated on the namestack?", names else: # Note: as of sometime before 080411, this became common -- # I guess that chunks (which recently acquired glselect names) # are pushing their names even while drawing their atoms and bonds. # I am not sure if this can cause any problems -- almost surely not # directly, but maybe the nestedness of highlighted appearances could # violate some assumptions made by the highlight code... anyway, # to reduce verbosity I need to not print this when the deeper name # is that of a chunk, and there are exactly two names. [bruce 080411] if len(names) == 2 and isinstance(self.object_for_glselect_name(names[0]), self.assy.Chunk): if not env.seen_before("nested names for Chunk"): print "debug (once-per-session message): nested glnames for a Chunk: ", names else: print "debug fyi: len(names) == %d (names = %r)" % (len(names), names) obj = self.object_for_glselect_name(names[-1]) # k should always return an obj if obj is None: print "bug: object_for_glselect_name returns None for name %r at end of namestack %r" % ( names[-1], names, ) else: self.glselect_dict[id(obj)] = obj # note: outside of this method, one of these will be # chosen to be saved as self.selobj and rerendered # in "highlighted" form ##if 0: ## # this debug print was useful for debugging bug 2945, ## # and when it happens it's usually a bug, ## # but not always: ## # - it's predicted to happen for ChunkDrawer._renderOverlayText ## # - and whenever we're using a whole-chunk display style ## # so we can't leave it in permanently. [bruce 081211] ## if isinstance( obj, self.assy.Chunk ): ## print "\n*** namestack topped with a chunk:", obj pass continue # next hit_record # e maybe we should now sort glselect_dict by "hit priority" # (for depth-tiebreaking), or at least put selobj first. # (or this could be done lower down, where it's used.) # [I think we do this now...] return # from do_glselect_if_wanted
def run(): #Start OpenGL and ask it for an OpenGL context pygame.init() clock = pygame.time.Clock() screen = pygame.display.set_mode(SCREEN_SIZE, pygame.HWSURFACE|pygame.OPENGL|pygame.DOUBLEBUF) #The first thing we do is print some OpenGL details and check that we have a good enough version print("OpenGL Implementation Details:") if glGetString(GL_VENDOR): print("\tGL_VENDOR: {}".format(glGetString(GL_VENDOR).decode())) if glGetString(GL_RENDERER): print("\tGL_RENDERER: {}".format(glGetString(GL_RENDERER).decode())) if glGetString(GL_VERSION): print("\tGL_VERSION: {}".format(glGetString(GL_VERSION).decode())) if glGetString(GL_SHADING_LANGUAGE_VERSION): print("\tGL_SHADING_LANGUAGE_VERSION: {}".format(glGetString(GL_SHADING_LANGUAGE_VERSION).decode())) major_version = int(glGetString(GL_VERSION).decode().split()[0].split('.')[0]) minor_version = int(glGetString(GL_VERSION).decode().split()[0].split('.')[1]) if major_version < 3 or (major_version < 3 and minor_version < 0): print("OpenGL version must be at least 3.0 (found {0})".format(glGetString(GL_VERSION).decode().split()[0])) #Now onto the OpenGL initialisation #Set up depth culling glEnable(GL_CULL_FACE) glEnable(GL_DEPTH_TEST) glDepthMask(GL_TRUE) glDepthFunc(GL_LEQUAL) glDepthRange(0.0, 1.0) #We create out shaders which do little more than set a flat colour for each face VERTEX_SHADER = shaders.compileShader(b""" #version 130 in vec4 position; in vec4 normal; uniform mat4 projectionMatrix; uniform mat4 viewMatrix; uniform mat4 modelMatrix; flat out float theColor; void main() { vec4 temp = modelMatrix * position; temp = viewMatrix * temp; gl_Position = projectionMatrix * temp; theColor = clamp(abs(dot(normalize(normal.xyz), normalize(vec3(0.9,0.1,0.5)))), 0, 1); } """, GL_VERTEX_SHADER) FRAGMENT_SHADER = shaders.compileShader(b""" #version 130 flat in float theColor; out vec4 outputColor; void main() { outputColor = vec4(1.0, 0.5, theColor, 1.0); } """, GL_FRAGMENT_SHADER) shader = shaders.compileProgram(VERTEX_SHADER, FRAGMENT_SHADER) #And then grab our attribute locations from it glBindAttribLocation(shader, 0, b"position") glBindAttribLocation(shader, 1, b"normal") #Create the Vertex Array Object to hold our volume mesh vertexArrayObject = GLuint(0) glGenVertexArrays(1, vertexArrayObject) glBindVertexArray(vertexArrayObject) #Create the index buffer object indexPositions = vbo.VBO(indices, target=GL_ELEMENT_ARRAY_BUFFER, usage=GL_STATIC_DRAW) #Create the VBO vertexPositions = vbo.VBO(vertices, usage=GL_STATIC_DRAW) #Bind our VBOs and set up our data layout specifications with indexPositions, vertexPositions: glEnableVertexAttribArray(0) glVertexAttribPointer(0, 3, GL_FLOAT, False, 6*vertices.dtype.itemsize, vertexPositions+(0*vertices.dtype.itemsize)) glEnableVertexAttribArray(1) glVertexAttribPointer(1, 3, GL_FLOAT, False, 6*vertices.dtype.itemsize, vertexPositions+(3*vertices.dtype.itemsize)) glBindVertexArray(0) glDisableVertexAttribArray(0) #Now grab out transformation martix locations modelMatrixUnif = glGetUniformLocation(shader, b"modelMatrix") viewMatrixUnif = glGetUniformLocation(shader, b"viewMatrix") projectionMatrixUnif = glGetUniformLocation(shader, b"projectionMatrix") modelMatrix = np.array([[1.0,0.0,0.0,-32.0],[0.0,1.0,0.0,-32.0],[0.0,0.0,1.0,-32.0],[0.0,0.0,0.0,1.0]], dtype='f') viewMatrix = np.array([[1.0,0.0,0.0,0.0],[0.0,1.0,0.0,0.0],[0.0,0.0,1.0,-50.0],[0.0,0.0,0.0,1.0]], dtype='f') projectionMatrix = np.array([[0.0,0.0,0.0,0.0],[0.0,0.0,0.0,0.0],[0.0,0.0,0.0,0.0],[0.0,0.0,0.0,0.0]], dtype='f') #These next few lines just set up our camera frustum fovDeg = 45.0 frustumScale = 1.0 / tan(radians(fovDeg) / 2.0) zNear = 1.0 zFar = 1000.0 projectionMatrix[0][0] = frustumScale projectionMatrix[1][1] = frustumScale projectionMatrix[2][2] = (zFar + zNear) / (zNear - zFar) projectionMatrix[2][3] = -1.0 projectionMatrix[3][2] = (2 * zFar * zNear) / (zNear - zFar) #viewMatrix and projectionMatrix don't change ever so just set them once here with shader: glUniformMatrix4fv(projectionMatrixUnif, 1, GL_TRUE, projectionMatrix) glUniformMatrix4fv(viewMatrixUnif, 1, GL_TRUE, viewMatrix) #These are used to track the rotation of the volume LastFrameMousePos = (0,0) CurrentMousePos = (0,0) xRotation = 0 yRotation = 0 while True: clock.tick() for event in pygame.event.get(): if event.type == pygame.QUIT: return if event.type == pygame.KEYUP and event.key == pygame.K_ESCAPE: return if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1: CurrentMousePos = event.pos LastFrameMousePos = CurrentMousePos if event.type == pygame.MOUSEMOTION and 1 in event.buttons: CurrentMousePos = event.pos diff = (CurrentMousePos[0] - LastFrameMousePos[0], CurrentMousePos[1] - LastFrameMousePos[1]) xRotation += event.rel[0] yRotation += event.rel[1] LastFrameMousePos = CurrentMousePos glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) #Perform the rotation of the mesh moveToOrigin = np.array([[1.0,0.0,0.0,-32.0],[0.0,1.0,0.0,-32.0],[0.0,0.0,1.0,-32.0],[0.0,0.0,0.0,1.0]], dtype='f') rotateAroundX = np.array([[1.0,0.0,0.0,0.0],[0.0,cos(radians(yRotation)),-sin(radians(yRotation)),0.0],[0.0,sin(radians(yRotation)),cos(radians(yRotation)),0.0],[0.0,0.0,0.0,1.0]], dtype='f') rotateAroundY = np.array([[cos(radians(xRotation)),0.0,sin(radians(xRotation)),0.0],[0.0,1.0,0.0,0.0],[-sin(radians(xRotation)),0.0,cos(radians(xRotation)),0.0],[0.0,0.0,0.0,1.0]], dtype='f') modelMatrix = rotateAroundY.dot(rotateAroundX.dot(moveToOrigin)) with shader: glUniformMatrix4fv(modelMatrixUnif, 1, GL_TRUE, modelMatrix) glBindVertexArray(vertexArrayObject) glDrawElements(GL_TRIANGLES, len(indices), GL_UNSIGNED_INT, None) glBindVertexArray(0) # Show the screen pygame.display.flip()
def initializeGL(self): glClearColor(0.85, 0.85, 0.85, 1.0) glClearDepth(1.0) glDepthFunc(GL_LESS) glEnable(GL_DEPTH_TEST) glEnable(GL_CULL_FACE) glShadeModel(GL_SMOOTH) glEnable(GL_NORMALIZE) glEnable(GL_COLOR_MATERIAL) glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE) glLightfv(GL_LIGHT0, GL_POSITION, (0.0, 0.0, 1.0, 0.0)) glEnable(GL_LIGHT0) glMatrixMode(GL_PROJECTION) glLoadIdentity() glMatrixMode(GL_MODELVIEW) glLoadIdentity() self.display_list = glGenLists(1) glNewList(self.display_list, GL_COMPILE) glScalef(0.5, 0.5, 0.5) glEnable(GL_LIGHTING) # board glColor3f(0.0, 0.0, 0.0) self.draw_cuboid(4.0, 4.0, 0.16) # USB connector glPushMatrix() glColor3f(0.5, 0.51, 0.58) glTranslatef(0.0, -1.6, 0.28) self.draw_cuboid(0.75, 0.9, 0.4) glPopMatrix() # right button glPushMatrix() glColor3f(0.5, 0.51, 0.58) glTranslatef(1.15, -1.85, 0.16) self.draw_cuboid(0.4, 0.3, 0.16) glColor3f(0.0, 0.0, 0.0) glTranslatef(0.0, -0.155, 0.025) self.draw_cuboid(0.18, 0.1, 0.08) glPopMatrix() # left button glPushMatrix() glColor3f(0.5, 0.51, 0.58) glTranslatef(-1.15, -1.85, 0.16) self.draw_cuboid(0.4, 0.3, 0.16) glColor3f(0.0, 0.0, 0.0) glTranslatef(0.0, -0.155, 0.025) self.draw_cuboid(0.18, 0.1, 0.08) glPopMatrix() # left btb top glPushMatrix() glColor3f(1.0, 1.0, 1.0) glTranslatef(-1.65, 0.0, 0.38) self.draw_cuboid(0.5, 1.4, 0.9) glPopMatrix() # right btb top glPushMatrix() glColor3f(1.0, 1.0, 1.0) glTranslatef(1.65, 0.0, 0.38) self.draw_cuboid(0.5, 1.4, 0.9) glPopMatrix() # left btb bottom glPushMatrix() glColor3f(1.0, 1.0, 1.0) glTranslatef(-1.65, 0.0, -0.33) self.draw_cuboid(0.5, 1.4, 0.5) glPopMatrix() # right btb bottom glPushMatrix() glColor3f(1.0, 1.0, 1.0) glTranslatef(1.65, 0.0, -0.33) self.draw_cuboid(0.5, 1.4, 0.5) glPopMatrix() # left bricklet port glPushMatrix() glColor3f(1.0, 1.0, 1.0) glTranslatef(-0.85, 1.8, -0.23) self.draw_cuboid(1.2, 0.4, 0.3) glPopMatrix() # right bricklet port glPushMatrix() glColor3f(1.0, 1.0, 1.0) glTranslatef(0.85, 1.8, -0.23) self.draw_cuboid(1.2, 0.4, 0.3) glPopMatrix() # left direction LED glPushMatrix() glColor3f(0.0, 0.5, 0.0) glTranslatef(-1.05, 1.425, 0.115) self.draw_cuboid(0.1, 0.2, 0.07) glPopMatrix() # top direction LED glPushMatrix() glColor3f(0.0, 0.5, 0.0) glTranslatef(-0.675, 1.8, 0.115) self.draw_cuboid(0.2, 0.1, 0.07) glPopMatrix() # right direction LED glPushMatrix() glColor3f(0.0, 0.5, 0.0) glTranslatef(-0.3, 1.425, 0.115) self.draw_cuboid(0.1, 0.2, 0.07) glPopMatrix() # bottom direction LED glPushMatrix() glColor3f(0.0, 0.5, 0.0) glTranslatef(-0.675, 1.05, 0.115) self.draw_cuboid(0.2, 0.1, 0.07) glPopMatrix() # left y orientation LED glPushMatrix() glColor3f(0.0, 0.0, 1.0) glTranslatef(0.275, 1.7, 0.115) self.draw_cuboid(0.1, 0.2, 0.07) glPopMatrix() # right y orientation LED glPushMatrix() glColor3f(1.0, 0.0, 0.0) glTranslatef(0.425, 1.7, 0.115) self.draw_cuboid(0.1, 0.2, 0.07) glPopMatrix() # top z orientation LED glPushMatrix() glColor3f(1.0, 0.0, 0.0) glTranslatef(0.35, 1.15, 0.115) self.draw_cuboid(0.2, 0.1, 0.07) glPopMatrix() # bottom z orientation LED glPushMatrix() glColor3f(0.0, 0.0, 1.0) glTranslatef(0.35, 1.0, 0.115) self.draw_cuboid(0.2, 0.1, 0.07) glPopMatrix() # top x orientation LED glPushMatrix() glColor3f(1.0, 0.0, 0.0) glTranslatef(1.0, 1.15, 0.115) self.draw_cuboid(0.2, 0.1, 0.07) glPopMatrix() # bottom x orientation LED glPushMatrix() glColor3f(0.0, 0.0, 1.0) glTranslatef(1.0, 1.0, 0.115) self.draw_cuboid(0.2, 0.1, 0.07) glPopMatrix() # top alignment corner glPushMatrix() glColor3f(1.0, 1.0, 1.0) glBegin(GL_TRIANGLES) glNormal3f(0.0, 0.0, 1.0) glVertex3f(-2.0, -2.0, 0.09) glVertex3f(-1.1, -2.0, 0.09) glVertex3f(-2.0, -1.1, 0.09) glEnd() glPopMatrix() # bottom alignment corner glPushMatrix() glColor3f(1.0, 1.0, 1.0) glBegin(GL_TRIANGLES) glNormal3f(0.0, 0.0, -1.0) glVertex3f(-2.0, -2.0, -0.09) glVertex3f(-2.0, -1.1, -0.09) glVertex3f(-1.1, -2.0, -0.09) glEnd() glPopMatrix() glDisable(GL_LIGHTING) # axis glPushMatrix() glTranslatef(-2.3, -2.3, -0.38) glLineWidth(3.0) glBegin(GL_LINES) glColor3f(1,0,0) # x axis is red glVertex3f(0,0,0) glVertex3f(3,0,0) glColor3f(0,0.5,0) # y axis is green glVertex3f(0,0,0) glVertex3f(0,3,0) glColor3f(0,0,1) # z axis is blue glVertex3f(0,0,0) glVertex3f(0,0,3) glEnd() glLineWidth(1.0) glPopMatrix() glEndList()
def initializeGL(self): glClearColor(0.85, 0.85, 0.85, 1.0) glClearDepth(1.0) glDepthFunc(GL_LESS) glEnable(GL_DEPTH_TEST) glShadeModel(GL_SMOOTH) glMatrixMode(GL_PROJECTION) glLoadIdentity() glMatrixMode(GL_MODELVIEW) glLoadIdentity() self.display_list = glGenLists(1) glNewList(self.display_list, GL_COMPILE) # Draw board glColor3f(0.0, 0.0, 0.0) self.draw_cuboid(1.0, 1.0, 0.1) # Draw USB connector glPushMatrix() glColor3f(0.5, 0.51, 0.58) glTranslatef(0.0, -0.8, 0.2) self.draw_cuboid(0.2, 0.25, 0.1) glPopMatrix() # Draw button right glPushMatrix() glColor3f(0.5, 0.51, 0.58) glTranslatef(0.65, -0.95, 0.125) self.draw_cuboid(0.1, 0.075, 0.05) glColor3f(0.0, 0.0, 0.0) glTranslatef(0.0, -0.075, 0.0) self.draw_cuboid(0.05, 0.025, 0.045) glPopMatrix() # Draw button left glPushMatrix() glColor3f(0.5, 0.51, 0.58) glTranslatef(-0.65, -0.95, 0.125) self.draw_cuboid(0.1, 0.075, 0.05) glColor3f(0.0, 0.0, 0.0) glTranslatef(0.0, -0.075, 0.0) self.draw_cuboid(0.05, 0.025, 0.045) glPopMatrix() # Draw btb left top glPushMatrix() glColor3f(1.0, 1.0, 1.0) glTranslatef(-0.75, 0.0, 0.25) self.draw_cuboid(0.13, 0.5, 0.15) glPopMatrix() # Draw btb right top glPushMatrix() glColor3f(1.0, 1.0, 1.0) glTranslatef(0.75, 0.0, 0.25) self.draw_cuboid(0.13, 0.5, 0.15) glPopMatrix() # Draw btb left bottom glPushMatrix() glColor3f(1.0, 1.0, 1.0) glTranslatef(-0.75, 0.0, -0.2) self.draw_cuboid(0.13, 0.5, 0.1) glPopMatrix() # Draw btb right bottom glPushMatrix() glColor3f(1.0, 1.0, 1.0) glTranslatef(0.75, 0.0, -0.2) self.draw_cuboid(0.13, 0.5, 0.1) glPopMatrix() # Draw bricklet port left glPushMatrix() glColor3f(1.0, 1.0, 1.0) glTranslatef(-0.425, 0.9, -0.125) self.draw_cuboid(0.325, 0.1, 0.05) glPopMatrix() # Draw bricklet port right glPushMatrix() glColor3f(1.0, 1.0, 1.0) glTranslatef(0.425, 0.9, -0.125) self.draw_cuboid(0.325, 0.1, 0.05) glPopMatrix() # Draw Axis glPushMatrix() glTranslatef(-1.2, -1.2, -0.3) glLineWidth(5.0) glBegin(GL_LINES) glColor3f(1,0,0) # x axis is red glVertex3fv((0,0,0)) glVertex3fv((2,0,0)) glColor3f(0,0.5,0) # y axis is green glVertex3fv((0,0,0)) glVertex3fv((0,2,0)) glColor3f(0,0,1) # z axis is blue glVertex3fv((0,0,0)) glVertex3fv((0,0,2)) glEnd() glPopMatrix() glEndList()
def initializeGL(self): glClearColor(0.85, 0.85, 0.85, 1.0) glClearDepth(1.0) glDepthFunc(GL_LESS) glEnable(GL_DEPTH_TEST) glEnable(GL_CULL_FACE) glShadeModel(GL_SMOOTH) glEnable(GL_NORMALIZE) glEnable(GL_COLOR_MATERIAL) glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE) glLightfv(GL_LIGHT0, GL_POSITION, (0.0, 0.0, 1.0, 0.0)) glEnable(GL_LIGHT0) glMatrixMode(GL_PROJECTION) glLoadIdentity() glMatrixMode(GL_MODELVIEW) glLoadIdentity() self.display_list = glGenLists(1) glNewList(self.display_list, GL_COMPILE) glScalef(0.5, 0.5, 0.5) glEnable(GL_LIGHTING) # board glColor3f(0.0, 0.0, 0.0) self.draw_cuboid(4.0, 4.0, 0.16) # USB connector glPushMatrix() glColor3f(0.5, 0.51, 0.58) glTranslatef(0.0, -1.6, 0.28) self.draw_cuboid(0.75, 0.9, 0.4) glPopMatrix() # right button glPushMatrix() glColor3f(0.5, 0.51, 0.58) glTranslatef(1.15, -1.85, 0.16) self.draw_cuboid(0.4, 0.3, 0.16) glColor3f(0.0, 0.0, 0.0) glTranslatef(0.0, -0.155, 0.025) self.draw_cuboid(0.18, 0.1, 0.08) glPopMatrix() # left button glPushMatrix() glColor3f(0.5, 0.51, 0.58) glTranslatef(-1.15, -1.85, 0.16) self.draw_cuboid(0.4, 0.3, 0.16) glColor3f(0.0, 0.0, 0.0) glTranslatef(0.0, -0.155, 0.025) self.draw_cuboid(0.18, 0.1, 0.08) glPopMatrix() # left btb top glPushMatrix() glColor3f(1.0, 1.0, 1.0) glTranslatef(-1.65, 0.0, 0.38) self.draw_cuboid(0.5, 1.4, 0.6) glPopMatrix() # right btb top glPushMatrix() glColor3f(1.0, 1.0, 1.0) glTranslatef(1.65, 0.0, 0.38) self.draw_cuboid(0.5, 1.4, 0.6) glPopMatrix() # left btb bottom glPushMatrix() glColor3f(1.0, 1.0, 1.0) glTranslatef(-1.65, 0.0, -0.33) self.draw_cuboid(0.5, 1.4, 0.5) glPopMatrix() # right btb bottom glPushMatrix() glColor3f(1.0, 1.0, 1.0) glTranslatef(1.65, 0.0, -0.33) self.draw_cuboid(0.5, 1.4, 0.5) glPopMatrix() # left bricklet port glPushMatrix() glColor3f(1.0, 1.0, 1.0) glTranslatef(-0.85, 1.8, -0.23) self.draw_cuboid(1.2, 0.4, 0.3) glPopMatrix() # right bricklet port glPushMatrix() glColor3f(1.0, 1.0, 1.0) glTranslatef(0.85, 1.8, -0.23) self.draw_cuboid(1.2, 0.4, 0.3) glPopMatrix() # left direction LED glPushMatrix() glColor3f(0.0, 0.5, 0.0) glTranslatef(-1.05, 1.425, 0.115) self.draw_cuboid(0.1, 0.2, 0.07) glPopMatrix() # top direction LED glPushMatrix() glColor3f(0.0, 0.5, 0.0) glTranslatef(-0.675, 1.8, 0.115) self.draw_cuboid(0.2, 0.1, 0.07) glPopMatrix() # right direction LED glPushMatrix() glColor3f(0.0, 0.5, 0.0) glTranslatef(-0.3, 1.425, 0.115) self.draw_cuboid(0.1, 0.2, 0.07) glPopMatrix() # bottom direction LED glPushMatrix() glColor3f(0.0, 0.5, 0.0) glTranslatef(-0.675, 1.05, 0.115) self.draw_cuboid(0.2, 0.1, 0.07) glPopMatrix() # left y orientation LED glPushMatrix() glColor3f(0.0, 0.0, 1.0) glTranslatef(0.275, 1.7, 0.115) self.draw_cuboid(0.1, 0.2, 0.07) glPopMatrix() # right y orientation LED glPushMatrix() glColor3f(1.0, 0.0, 0.0) glTranslatef(0.425, 1.7, 0.115) self.draw_cuboid(0.1, 0.2, 0.07) glPopMatrix() # top z orientation LED glPushMatrix() glColor3f(1.0, 0.0, 0.0) glTranslatef(0.35, 1.15, 0.115) self.draw_cuboid(0.2, 0.1, 0.07) glPopMatrix() # bottom z orientation LED glPushMatrix() glColor3f(0.0, 0.0, 1.0) glTranslatef(0.35, 1.0, 0.115) self.draw_cuboid(0.2, 0.1, 0.07) glPopMatrix() # top x orientation LED glPushMatrix() glColor3f(1.0, 0.0, 0.0) glTranslatef(1.0, 1.15, 0.115) self.draw_cuboid(0.2, 0.1, 0.07) glPopMatrix() # bottom x orientation LED glPushMatrix() glColor3f(0.0, 0.0, 1.0) glTranslatef(1.0, 1.0, 0.115) self.draw_cuboid(0.2, 0.1, 0.07) glPopMatrix() # top alignment corner glPushMatrix() glColor3f(1.0, 1.0, 1.0) glBegin(GL_TRIANGLES) glNormal3f(0.0, 0.0, 1.0) glVertex3f(-2.0, -2.0, 0.081) glVertex3f(-1.1, -2.0, 0.081) glVertex3f(-2.0, -1.1, 0.081) glEnd() glPopMatrix() # bottom alignment corner glPushMatrix() glColor3f(1.0, 1.0, 1.0) glBegin(GL_TRIANGLES) glNormal3f(0.0, 0.0, -1.0) glVertex3f(-2.0, -2.0, -0.081) glVertex3f(-2.0, -1.1, -0.081) glVertex3f(-1.1, -2.0, -0.081) glEnd() glPopMatrix() glDisable(GL_LIGHTING) # axis glPushMatrix() glTranslatef(-2.3, -2.3, -0.38) glLineWidth(3.0) glBegin(GL_LINES) glColor3f(1, 0, 0) # x axis is red glVertex3f(0, 0, 0) glVertex3f(3, 0, 0) glColor3f(0, 0.5, 0) # y axis is green glVertex3f(0, 0, 0) glVertex3f(0, 3, 0) glColor3f(0, 0, 1) # z axis is blue glVertex3f(0, 0, 0) glVertex3f(0, 0, 3) glEnd() glLineWidth(1.0) glPopMatrix() glEndList()
def paintGL(self): """ Called by QtGL when redrawing is needed. For every redraw, color & depth butter are cleared, view projection are reset, view location & orientation are also reset. """ if not self.initialised: return self._call_whatever_waits_for_gl_context_current() #bruce 071103 glDepthFunc( GL_LEQUAL) self.setDepthRange_setup_from_debug_pref() self.setDepthRange_Normal() from utilities.debug_prefs import debug_pref, Choice_boolean_False if debug_pref("always setup_lighting?", Choice_boolean_False): #bruce 060415 added debug_pref("always setup_lighting?"), in GLPane and ThumbView [KEEP DFLTS THE SAME!!]; # see comments in GLPane_lighting_methods self._setup_lighting() #bruce 060415 added this call self.backgroundColor = env.prefs[backgroundColor_prefs_key] c = self.backgroundColor glClearColor(c[0], c[1], c[2], 0.0) del c glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) self.backgroundGradient = env.prefs[ backgroundGradient_prefs_key ] if self.backgroundGradient: glMatrixMode(GL_PROJECTION) glLoadIdentity() glMatrixMode(GL_MODELVIEW) glLoadIdentity() # Setting to blue sky (default), but might change to something else _bgGradient = bluesky if self.backgroundGradient == bgEVENING_SKY: _bgGradient = eveningsky if self.backgroundGradient == bgSEAGREEN: _bgGradient = bg_seagreen drawFullWindow(_bgGradient)# gradient color self._setup_projection() self._setup_modelview() ## glMatrixMode(GL_MODELVIEW) ## glLoadIdentity() ## glTranslatef(0.0, 0.0, - self.vdist) ## q = self.quat ## glRotatef(q.angle * 180.0 / math.pi, q.x, q.y, q.z) ## glTranslatef(self.pov[0], self.pov[1], self.pov[2]) if self.model_is_valid(): #bruce 080117 [testing this at start of paintGL to skip most of it]: # precaution (perhaps a bugfix); see similar code in GLPane. # # update, bruce 080220: this may have caused a bug by making this # not draw a blank-background graphics area when it has no model. # E.g. the partlib has no model when first entered. # Fixing this by only not drawing the model itself in that case [UNTESTED]. # (The GLPane always has a model, so has no similar issue.) # # I'm not moving the coordinate transforms into this if statement, # since I don't know if they might be depended on by non-paintGL # drawing (e.g. for highlighting, which btw is called "selection" # in some method names and comments in this file). [bruce 080220] self._drawModel_using_DrawingSets()
def _setup_opengl(self): glEnable(GL_DEPTH_TEST) glEnable(GL_CULL_FACE) glDepthFunc(GL_LEQUAL) glEnable(GL_BLEND) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
def InitGL(): # We call this right after our OpenGL window is created. glClearColor(0.0, 0.0, 0.0, 0.0) # This Will Clear The Background Color To Black glClearDepth(1.0) # Enables Clearing Of The Depth Buffer glDepthFunc(GL_LESS) # The Type Of Depth Test To Do glEnable(GL_DEPTH_TEST) # Enables Depth Testing
def do_glselect_if_wanted(self): #bruce 070919 split this out """ Do the glRenderMode(GL_SELECT) drawing, and/or the glname-color drawing for shader primitives, used to guess which object might be under the mouse, for one drawing frame, if desired for this frame. Report results by storing candidate mouseover objects in self.glselect_dict. The depth buffer is initially clear, and must be clear when we're done as well. @note: does not do related individual object depth/stencil buffer drawing -- caller must do that on some or all of the objects we store into self.glselect_dict. """ if self.glselect_wanted: # note: this will be reset below. ###@@@ WARNING: The original code for this, here in GLPane, has been duplicated and slightly modified # in at least three other places (search for glRenderMode to find them). This is bad; common code # should be used. Furthermore, I suspect it's sometimes needlessly called more than once per frame; # that should be fixed too. [bruce 060721 comment] wX, wY, self.targetdepth = self.glselect_wanted # wX, wY is the point to do the hit-test at # targetdepth is the depth buffer value to look for at that point, during ordinary drawing phase # (could also be used to set up clipping planes to further restrict hit-test, but this isn't yet done) # (Warning: targetdepth could in theory be out of date, if more events come between bareMotion # and the one caused by its gl_update, whose paintGL is what's running now, and if those events # move what's drawn. Maybe that could happen with mousewheel events or (someday) with keypresses # having a graphical effect. Ideally we'd count intentional redraws, and disable this picking in that case.) self.wX, self.wY = wX, wY self.glselect_wanted = 0 pwSize = 1 # Pick window size. Russ 081128: Was 3. # Bruce: Replace 3, 3 with 1, 1? 5, 5? not sure whether this will # matter... in principle should have no effect except speed. # Russ: For glname rendering, 1x1 is better because it doesn't # have window boundary issues. We get the coords of a single # pixel in the window for the mouse position. #bruce 050615 for use by nodes which want to set up their own projection matrix. self.current_glselect = (wX, wY, pwSize, pwSize) self._setup_projection(glselect=self.current_glselect ) # option makes it use gluPickMatrix # Russ 081209: Added. debugPicking = debug_pref("GLPane: debug mouseover picking?", Choice_boolean_False, prefs_key=True) if self.enabled_shaders(): # TODO: optimization: find an appropriate place to call # _compute_frustum_planes. [bruce 090105 comment] # Russ 081122: There seems to be no way to access the GL name # stack in shaders. Instead, for mouseover, draw shader # primitives with glnames as colors in glRenderMode(GL_RENDER), # then read back the pixel color (glname) and depth value. # Temporarily replace the full-size viewport with a little one # at the mouse location, matching the pick matrix location. # Otherwise, we will draw a closeup of that area into the whole # window, rather than a few pixels. (This wasn't needed when we # only used GL_SELECT rendering mode here, because that doesn't # modify the frame buffer -- it just returns hits by graphics # primitives when they are inside the clipping boundaries.) # # (Don't set the viewport *before* _setup_projection(), since # that method needs to read the current whole-window viewport # to set up glselect. See explanation in its docstring.) savedViewport = glGetIntegerv(GL_VIEWPORT) glViewport(wX, wY, pwSize, pwSize) # Same as current_glselect. # First, clear the pixel RGBA to zeros and a depth of 1.0 (far), # so we won't confuse a color with a glname if there are # no shader primitives drawn over this pixel. saveDepthFunc = glGetInteger(GL_DEPTH_FUNC) glDepthFunc(GL_ALWAYS) glWindowPos3i(wX, wY, 1) # Note the Z coord. gl_format, gl_type = GL_RGBA, GL_UNSIGNED_BYTE glDrawPixels(pwSize, pwSize, gl_format, gl_type, (0, 0, 0, 0)) glDepthFunc( saveDepthFunc) # needed, though we'll change it again # We must be in glRenderMode(GL_RENDER) (as usual) when this is called. # Note: _setup_projection leaves the matrix mode as GL_PROJECTION. glMatrixMode(GL_MODELVIEW) shaders = self.enabled_shaders() try: # Set flags so that we will use glnames-as-color mode # in shaders, and draw only shader primitives. # (Ideally we would also draw all non-shader primitives # as some other color, unequal to all glname colors # (or derived from a fake glname for that purpose), # in order to obscure shader primitives where appropriate. # This is intended to be done but is not yet implemented. # [bruce 090105 addendum]) for shader in shaders: shader.setPicking(True) self.set_drawing_phase("glselect_glname_color") for stereo_image in self.stereo_images_to_draw: self._enable_stereo(stereo_image) try: self._do_graphicsMode_Draw( for_mouseover_highlighting=True) # note: we can't disable depth writing here, # since we need it to make sure the correct # shader object comes out on top, or is # obscured by a DL object. Instead, we'll # clear the depth buffer again (at this pixel) # below. [bruce 090105] finally: self._disable_stereo() except: print_compact_traceback( "exception in or around _do_graphicsMode_Draw() during glname_color;" "drawing ignored; restoring modelview matrix: ") # REVIEW: what does "drawing ignored" mean, in that message? [bruce 090105 question] glMatrixMode(GL_MODELVIEW) self._setup_modelview( ) ### REVIEW: correctness of this is unreviewed! # now it's important to continue, at least enough to restore other gl state pass for shader in shaders: shader.setPicking(False) self.set_drawing_phase('?') # Restore the viewport. glViewport(savedViewport[0], savedViewport[1], savedViewport[2], savedViewport[3]) # Read pixel value from the back buffer and re-assemble glname. glFinish() # Make sure the drawing has completed. # REVIEW: is this glFinish needed? [bruce 090105 comment] rgba = glReadPixels(wX, wY, 1, 1, gl_format, gl_type)[0][0] pixZ = glReadPixelsf(wX, wY, 1, 1, GL_DEPTH_COMPONENT)[0][0] # Clear our depth pixel to 1.0 (far), so we won't mess up the # subsequent call of preDraw_glselect_dict. # (The following is not the most direct way, but it ought to work. # Note that we also clear the color pixel, since (being a glname) # it has no purpose remaining in the color buffer -- either it's # changed later, or, if not, that's a bug, but we'd rather have # it black than a random color.) [bruce 090105 bugfix] glDepthFunc(GL_ALWAYS) glWindowPos3i(wX, wY, 1) # Note the Z coord. glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE) gl_format, gl_type = GL_RGBA, GL_UNSIGNED_BYTE glDrawPixels(pwSize, pwSize, gl_format, gl_type, (0, 0, 0, 0)) glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE) glDepthFunc(saveDepthFunc) # Comes back sign-wrapped, in spite of specifying UNSIGNED_BYTE. def us(b): if b < 0: return 256 + b return b bytes = tuple([us(b) for b in rgba]) ##glname = (bytes[0] << 24 | bytes[1] << 16 | bytes[2] << 8 | bytes[3]) ## Temp fix: Ignore the last byte, which always comes back 255 on Windows. glname = (bytes[0] << 16 | bytes[1] << 8 | bytes[2]) if debugPicking: print("shader mouseover xy %d %d, " % (wX, wY) + "rgba bytes (0x%x, 0x%x, 0x%x, 0x%x), " % bytes + "Z %f, glname 0x%x" % (pixZ, glname)) pass ### XXX This ought to be better-merged with the DL selection below. if glname: obj = self.object_for_glselect_name(glname) if debugPicking: print "shader mouseover glname=%r, obj=%r." % (glname, obj) if obj is None: # REVIEW: does this happen for mouse over a non-shader primitive? # [bruce 090105 question] #### Note: this bug is common. Guess: we are still drawing # ordinary colors for some primitives and/or for the # background, and they are showing up here and confusing # us. To help debug this, print the color too. But testing # shows it's not so simple -- e.g. for rung bonds it happens # where shader sphere and cylinder overlap, but not on either # one alone; for strand bonds it also happens on the bonds alone # (tested in Build DNA, in or not in Insert DNA). # [bruce 090218] # # Update: Since it's so common, I need to turn it off by default. # Q: is the situation safe? # A: if a color looks like a real glname by accident, # we'll get some random candidate object -- perhaps a killed one # or from a different Part or even a closed assy -- # and try to draw it. That doesn't sound very safe. Unfortunately # there is no perfect way to filter selobjs for safety, in the # current still-informal Selobj_API. The best approximation is # selobj_still_ok, and it should always say yes for the usual kinds, # so I'll add it as a check in the 'else' clause below. # [bruce 090311] if debug_flags.atom_debug: print "bug: object_for_glselect_name returns None for glname %r (color %r)" % ( glname, bytes) else: if self.graphicsMode.selobj_still_ok(obj): #bruce 090311 added condition, explained above self.glselect_dict[id(obj)] = obj else: # This should be rare but possible. Leave it on briefly and see # if it's ever common. If possible, gate it by atom_debug before # the release. [bruce 090311] print "fyi: glname-color selobj %r rejected since not selobj_still_ok" % obj pass pass pass if self._use_frustum_culling: self._compute_frustum_planes() # piotr 080331 - the frustum planes have to be setup after the # projection matrix is setup. I'm not sure if there may # be any side effects - see the comment below about # possible optimization. glSelectBuffer(self.SIZE_FOR_glSelectBuffer) # Note: this allocates a new select buffer, # and glRenderMode(GL_RENDER) returns it and forgets it, # so it's required before *each* call of glRenderMode(GL_SELECT) + # glRenderMode(GL_RENDER), not just once to set the size. # Ref: http://pyopengl.sourceforge.net/documentation/opengl_diffs.html # [bruce 080923 comment] glInitNames() # REVIEW: should we also set up a clipping plane just behind the # hit point, as (I think) is done in ThumbView, to reduce the # number of candidate objects? This might be a significant # optimization, though I don't think it eliminates the chance # of having multiple candidates. [bruce 080917 comment] glRenderMode(GL_SELECT) glMatrixMode(GL_MODELVIEW) try: self.set_drawing_phase('glselect') #bruce 070124 for stereo_image in self.stereo_images_to_draw: self._enable_stereo(stereo_image) try: self._do_graphicsMode_Draw( for_mouseover_highlighting=True) finally: self._disable_stereo() except: print_compact_traceback( "exception in or around _do_graphicsMode_Draw() during GL_SELECT; " "ignored; restoring modelview matrix: ") glMatrixMode(GL_MODELVIEW) self._setup_modelview( ) ### REVIEW: correctness of this is unreviewed! # now it's important to continue, at least enough to restore other gl state self._frustum_planes_available = False # piotr 080331 # just to be safe and not use the frustum planes computed for # the pick matrix self.set_drawing_phase('?') self.current_glselect = False # REVIEW: On systems with no stencil buffer, I think we'd also need # to draw selobj here in highlighted form (in case that form is # bigger than when it's not highlighted), or (easier & faster) # just always pretend it passes the hit test and add it to # glselect_dict -- and, make sure to give it "first dibs" for being # the next selobj. I'll implement some of this now (untested when # no stencil buffer) but not yet all. [bruce 050612] selobj = self.selobj if selobj is not None: self.glselect_dict[id(selobj)] = selobj # (review: is the following note correct?) # note: unneeded, if the func that looks at this dict always # tries selobj first (except for a kluge near # "if self.glselect_dict", commented on below) glFlush() hit_records = list(glRenderMode(GL_RENDER)) if debugPicking: print "DLs %d hits" % len(hit_records) for (near, far, names) in hit_records: # see example code, renderpass.py ## print "hit record: near, far, names:", near, far, names # e.g. hit record: near, far, names: 1439181696 1453030144 (1638426L,) # which proves that near/far are too far apart to give actual depth, # in spite of the 1- or 3-pixel drawing window (presumably they're vertices # taken from unclipped primitives, not clipped ones). del near, far if 1: # partial workaround for bug 1527. This can be removed once that bug (in drawer.py) # is properly fixed. This exists in two places -- GLPane.py and modes.py. [bruce 060217] if names and names[-1] == 0: print "%d(g) partial workaround for bug 1527: removing 0 from end of namestack:" % env.redraw_counter, names names = names[:-1] if names: # For now, we only use the last element of names, # though (as of long before 080917) it is often longer: # - some code pushes the same name twice (directly and # via ColorSorter) (see 060725 debug print below); # - chunks push a name even when they draw atoms/bonds # which push their own names (see 080411 comment below). # # Someday: if we ever support "name/subname paths" we'll # probably let first name interpret the remaining ones. # In fact, if nodes change projection or viewport for # their kids, and/or share their kids, they'd need to # push their own names on the stack, so we'd know how # to redraw the kids, or which ones are meant when they # are shared. if debug_flags.atom_debug and len( names) > 1: # bruce 060725 if len(names) == 2 and names[0] == names[1]: if not env.seen_before( "dual-names bug" ): # this happens for Atoms (colorsorter bug??) print "debug (once-per-session message): why are some glnames duplicated on the namestack?", names else: # Note: as of sometime before 080411, this became common -- # I guess that chunks (which recently acquired glselect names) # are pushing their names even while drawing their atoms and bonds. # I am not sure if this can cause any problems -- almost surely not # directly, but maybe the nestedness of highlighted appearances could # violate some assumptions made by the highlight code... anyway, # to reduce verbosity I need to not print this when the deeper name # is that of a chunk, and there are exactly two names. [bruce 080411] if len(names) == 2 and \ isinstance( self.object_for_glselect_name(names[0]), self.assy.Chunk ): if not env.seen_before( "nested names for Chunk"): print "debug (once-per-session message): nested glnames for a Chunk: ", names else: print "debug fyi: len(names) == %d (names = %r)" % ( len(names), names) obj = self.object_for_glselect_name( names[-1]) #k should always return an obj if obj is None: print "bug: object_for_glselect_name returns None for name %r at end of namestack %r" % ( names[-1], names) else: self.glselect_dict[id(obj)] = obj # note: outside of this method, one of these will be # chosen to be saved as self.selobj and rerendered # in "highlighted" form ##if 0: ## # this debug print was useful for debugging bug 2945, ## # and when it happens it's usually a bug, ## # but not always: ## # - it's predicted to happen for ChunkDrawer._renderOverlayText ## # - and whenever we're using a whole-chunk display style ## # so we can't leave it in permanently. [bruce 081211] ## if isinstance( obj, self.assy.Chunk ): ## print "\n*** namestack topped with a chunk:", obj pass continue # next hit_record #e maybe we should now sort glselect_dict by "hit priority" # (for depth-tiebreaking), or at least put selobj first. # (or this could be done lower down, where it's used.) # [I think we do this now...] return # from do_glselect_if_wanted
def run(): #Start OpenGL and ask it for an OpenGL context pygame.init() clock = pygame.time.Clock() screen = pygame.display.set_mode( SCREEN_SIZE, pygame.HWSURFACE | pygame.OPENGL | pygame.DOUBLEBUF) #The first thing we do is print some OpenGL details and check that we have a good enough version print("OpenGL Implementation Details:") if glGetString(GL_VENDOR): print("\tGL_VENDOR: {}".format(glGetString(GL_VENDOR).decode())) if glGetString(GL_RENDERER): print("\tGL_RENDERER: {}".format(glGetString(GL_RENDERER).decode())) if glGetString(GL_VERSION): print("\tGL_VERSION: {}".format(glGetString(GL_VERSION).decode())) if glGetString(GL_SHADING_LANGUAGE_VERSION): print("\tGL_SHADING_LANGUAGE_VERSION: {}".format( glGetString(GL_SHADING_LANGUAGE_VERSION).decode())) major_version = int( glGetString(GL_VERSION).decode().split()[0].split('.')[0]) minor_version = int( glGetString(GL_VERSION).decode().split()[0].split('.')[1]) if major_version < 3 or (major_version < 3 and minor_version < 0): print("OpenGL version must be at least 3.0 (found {0})".format( glGetString(GL_VERSION).decode().split()[0])) #Now onto the OpenGL initialisation #Set up depth culling glEnable(GL_CULL_FACE) glEnable(GL_DEPTH_TEST) glDepthMask(GL_TRUE) glDepthFunc(GL_LEQUAL) glDepthRange(0.0, 1.0) #We create out shaders which do little more than set a flat colour for each face VERTEX_SHADER = shaders.compileShader( b""" #version 130 in vec4 position; in vec4 normal; uniform mat4 projectionMatrix; uniform mat4 viewMatrix; uniform mat4 modelMatrix; flat out float theColor; void main() { vec4 temp = modelMatrix * position; temp = viewMatrix * temp; gl_Position = projectionMatrix * temp; theColor = clamp(abs(dot(normalize(normal.xyz), normalize(vec3(0.9,0.1,0.5)))), 0, 1); } """, GL_VERTEX_SHADER) FRAGMENT_SHADER = shaders.compileShader( b""" #version 130 flat in float theColor; out vec4 outputColor; void main() { outputColor = vec4(1.0, 0.5, theColor, 1.0); } """, GL_FRAGMENT_SHADER) shader = shaders.compileProgram(VERTEX_SHADER, FRAGMENT_SHADER) #And then grab our attribute locations from it glBindAttribLocation(shader, 0, b"position") glBindAttribLocation(shader, 1, b"normal") #Create the Vertex Array Object to hold our volume mesh vertexArrayObject = GLuint(0) glGenVertexArrays(1, vertexArrayObject) glBindVertexArray(vertexArrayObject) #Create the index buffer object indexPositions = vbo.VBO(indices, target=GL_ELEMENT_ARRAY_BUFFER, usage=GL_STATIC_DRAW) #Create the VBO vertexPositions = vbo.VBO(vertices, usage=GL_STATIC_DRAW) #Bind our VBOs and set up our data layout specifications with indexPositions, vertexPositions: glEnableVertexAttribArray(0) glVertexAttribPointer(0, 3, GL_FLOAT, False, 6 * vertices.dtype.itemsize, vertexPositions + (0 * vertices.dtype.itemsize)) glEnableVertexAttribArray(1) glVertexAttribPointer(1, 3, GL_FLOAT, False, 6 * vertices.dtype.itemsize, vertexPositions + (3 * vertices.dtype.itemsize)) glBindVertexArray(0) glDisableVertexAttribArray(0) #Now grab out transformation martix locations modelMatrixUnif = glGetUniformLocation(shader, b"modelMatrix") viewMatrixUnif = glGetUniformLocation(shader, b"viewMatrix") projectionMatrixUnif = glGetUniformLocation(shader, b"projectionMatrix") modelMatrix = np.array([[1.0, 0.0, 0.0, -32.0], [0.0, 1.0, 0.0, -32.0], [0.0, 0.0, 1.0, -32.0], [0.0, 0.0, 0.0, 1.0]], dtype='f') viewMatrix = np.array([[1.0, 0.0, 0.0, 0.0], [0.0, 1.0, 0.0, 0.0], [0.0, 0.0, 1.0, -50.0], [0.0, 0.0, 0.0, 1.0]], dtype='f') projectionMatrix = np.array([[0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0]], dtype='f') #These next few lines just set up our camera frustum fovDeg = 45.0 frustumScale = 1.0 / tan(radians(fovDeg) / 2.0) zNear = 1.0 zFar = 1000.0 projectionMatrix[0][0] = frustumScale projectionMatrix[1][1] = frustumScale projectionMatrix[2][2] = (zFar + zNear) / (zNear - zFar) projectionMatrix[2][3] = -1.0 projectionMatrix[3][2] = (2 * zFar * zNear) / (zNear - zFar) #viewMatrix and projectionMatrix don't change ever so just set them once here with shader: glUniformMatrix4fv(projectionMatrixUnif, 1, GL_TRUE, projectionMatrix) glUniformMatrix4fv(viewMatrixUnif, 1, GL_TRUE, viewMatrix) #These are used to track the rotation of the volume LastFrameMousePos = (0, 0) CurrentMousePos = (0, 0) xRotation = 0 yRotation = 0 while True: clock.tick() for event in pygame.event.get(): if event.type == pygame.QUIT: return if event.type == pygame.KEYUP and event.key == pygame.K_ESCAPE: return if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1: CurrentMousePos = event.pos LastFrameMousePos = CurrentMousePos if event.type == pygame.MOUSEMOTION and 1 in event.buttons: CurrentMousePos = event.pos diff = (CurrentMousePos[0] - LastFrameMousePos[0], CurrentMousePos[1] - LastFrameMousePos[1]) xRotation += event.rel[0] yRotation += event.rel[1] LastFrameMousePos = CurrentMousePos glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) #Perform the rotation of the mesh moveToOrigin = np.array( [[1.0, 0.0, 0.0, -32.0], [0.0, 1.0, 0.0, -32.0], [0.0, 0.0, 1.0, -32.0], [0.0, 0.0, 0.0, 1.0]], dtype='f') rotateAroundX = np.array( [[1.0, 0.0, 0.0, 0.0], [0.0, cos(radians(yRotation)), -sin(radians(yRotation)), 0.0], [0.0, sin(radians(yRotation)), cos(radians(yRotation)), 0.0], [0.0, 0.0, 0.0, 1.0]], dtype='f') rotateAroundY = np.array( [[cos(radians(xRotation)), 0.0, sin(radians(xRotation)), 0.0], [0.0, 1.0, 0.0, 0.0], [-sin(radians(xRotation)), 0.0, cos(radians(xRotation)), 0.0], [0.0, 0.0, 0.0, 1.0]], dtype='f') modelMatrix = rotateAroundY.dot(rotateAroundX.dot(moveToOrigin)) with shader: glUniformMatrix4fv(modelMatrixUnif, 1, GL_TRUE, modelMatrix) glBindVertexArray(vertexArrayObject) glDrawElements(GL_TRIANGLES, len(indices), GL_UNSIGNED_INT, None) glBindVertexArray(0) # Show the screen pygame.display.flip()