class Viewer(object): def __init__(self): """ Initialize the viewer. """ self.init_interface() self.init_opengl() self.init_scene() self.init_interaction() init_primitives() init_primitives() def init_interface(self): glutInit() glutInitWindowSize(640, 480) glutCreateWindow(b"3D Modeller") glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB) #register render function glutDisplayFunc(self.render) 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_scene(self): self.scene = Scene() #to init objects in the scene self.create_sample_scene() def init_interaction(self): pass def main_loop(self): glutMainLoop() def render(self): #init shadow matrix self.init_view() #open light glEnable(GL_LIGHTING) #clear color and depth caches glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) #set model view matrix(danwei matrix is ok) glMatirxMode(GL_MODELVIEW) glPushMatrix() #replace now-matrix with hengdeng matrix glLoadIdentity() #rend the scene self.scene.render() #after each shadow , huifu light state glDisable(GL_LIGHTING) glPopmatrix() glFlush() def init_view(self): """init shadow matrix""" xSize, ySize = glutGet(GLUT_WINDOW_WIDTH), gluGet(GLUT_WINDOW_HEIGHT) #get screen's kuangaobi aspect_ratio = float(xSize) / float(ySize) #set shadow matrix glMatrixMode(GL_PROJECTION) glLoadIdentity() #set viewport, should be chonghe with window glViewport(0, 0, xSize, ySize) #set toushi, eyesight width 70 degree, 1000 distance fron camare gluPerspective(70, aspect_ratio, 0.1, 1000.0) #jinftou back 15 distances from o glTranslated(0, 0, -15) def init_scene(self): self.scene = Scene() self.create_sample_scene() def create_sample_scene(self): # to create a ball sphere_node = Sphere() # to set the ball's color sphere_node.color_index = 2 sphere_node.translate(2, 2, 0) sphere_node.scale(4) #to put the ball in the scene.Default middle of view self.scene.add_node(sphere_node) #to add a snowman hierarchical_node = SnowFigure() hierarchical_node.translate(-2, 0, 2) hierarchical_node.scale(2) self.scene.add_node(hierarchical_node)
class Viewer(object): def __init__(self): """ Initialize the viewer. """ self.init_interface() self.init_opengl() self.init_scene() self.init_interaction() init_primitives() def init_interface(self): """ initialize the window and register the render function """ glutInit() glutInitWindowSize(640, 480) glutCreateWindow("3D Modeller") glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB) glutDisplayFunc(self.render) def init_interaction(self): """ init user interaction and callbacks """ self.interaction = Interaction() self.interaction.register_callback('pick', self.pick) self.interaction.register_callback('move', self.move) self.interaction.register_callback('place', self.place) self.interaction.register_callback('rotate_color', self.rotate_color) self.interaction.register_callback('scale', self.scale) def init_scene(self): """ initialize the scene object and initial scene """ self.scene = Scene() self.initial_scene() 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 main_loop(self): glutMainLoop() def render(self): """ The render pass for the scene """ self.init_view() # Enable lighting and color glEnable(GL_LIGHTING) glClearColor(0.4, 0.4, 0.4, 0.0) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) # Load the modelview matrix from the current state of the trackball glMatrixMode(GL_MODELVIEW) glPushMatrix() glLoadIdentity() loc = self.interaction.translation glTranslated(-loc[0], -loc[1], -loc[2]) glMultMatrixf(self.interaction.trackball.matrix) # store the inverse of the current modelview. currentModelView = numpy.array(glGetFloatv(GL_MODELVIEW_MATRIX)) self.modelView = numpy.transpose(currentModelView) self.inverseModelView = inv(numpy.transpose(currentModelView)) # render the scene. This will call the render function for each object in the scene self.scene.render() # draw the grid glDisable(GL_LIGHTING) glCallList(G_OBJ_PLANE) glPopMatrix() # flush the buffers so that the scene can be drawn glFlush() def init_view(self): """ initialize the projection matrix """ xSize, ySize = glutGet(GLUT_WINDOW_WIDTH), glutGet(GLUT_WINDOW_HEIGHT) aspect_ratio = float(xSize) / float(ySize) # load the projection matrix. Always the same glMatrixMode(GL_PROJECTION) glLoadIdentity() glViewport(0, 0, xSize, ySize) gluPerspective(70, aspect_ratio, 0.1, 1000.0) glTranslated(0, 0, -15) def initial_scene(self): cube_node = Cube() cube_node.translate(2, 0, 2) cube_node.color_index = 2 self.scene.add_node(cube_node) sphere_node = Sphere() sphere_node.translate(-2, 0, 2) sphere_node.color_index = 3 self.scene.add_node(sphere_node) sphere_node_2 = Sphere() sphere_node_2.translate(-2, 0, -2) sphere_node_2.color_index = 1 self.scene.add_node(sphere_node_2) def get_ray(self, x, y): """ Generate a ray beginning at the near plane, in the direction that the x, y coordinates are facing Consumes: x, y coordinates of mouse on screen Return: start, direction of the ray """ self.init_view() glMatrixMode(GL_MODELVIEW) glLoadIdentity() # get two points on the line. start = numpy.array(gluUnProject(x, y, 0.001)) end = numpy.array(gluUnProject(x, y, 0.999)) # convert those points into a ray direction = end - start direction = direction / norm(direction) return (start, direction) def pick(self, x, y): """ Execute pick of an object. Selects an object in the scene. """ start, direction = self.get_ray(x, y) self.scene.pick(start, direction, self.modelView) def move(self, x, y): """ Execute a move command on the scene. """ start, direction = self.get_ray(x, y) self.scene.move(start, direction, self.inverseModelView) def place(self, shape, x, y): """ Execute a placement of a new primitive into the scene. """ start, direction = self.get_ray(x, y) self.scene.place(shape, start, direction, self.inverseModelView) def rotate_color(self, forward): """ Rotate the color of the selected Node. Boolean 'forward' indicates direction of rotation. """ self.scene.rotate_color(forward) def scale(self, up): """ Scale the selected Node. Boolean up indicates scaling larger.""" self.scene.scale(up)
class Viewer(object): def __init__(self): """ Initialize the viewer. """ #初始化接口,创建窗口并注册渲染函数 self.init_interface() #初始化opengl的配置 self.init_opengl() #初始化3d场景 self.init_scene() #初始化交互操作相关的代码 self.init_interaction() init_primitives() def init_interface(self): """ 初始化窗口并注册渲染函数 """ glutInit() glutInitWindowSize(640, 480) glutCreateWindow(b"3D Modeller") glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB) #注册窗口渲染函数 glutDisplayFunc(self.render) 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_scene(self): #创建一个场景实例 self.scene = Scene() #初始化场景内的对象 self.create_sample_scene() def create_sample_scene(self): cube_node = Cube() cube_node.translate(2, 0, 2) cube_node.color_index = 1 self.scene.add_node(cube_node) sphere_node = Sphere() sphere_node.translate(-2, 0, 2) sphere_node.color_index = 3 self.scene.add_node(sphere_node) hierarchical_node = SnowFigure() hierarchical_node.translate(-2, 0, -2) self.scene.add_node(hierarchical_node) def init_interaction(self): #初始化交互操作相关的代码,之后实现 pass def main_loop(self): #程序主循环开始 glutMainLoop() def render(self): #初始化投影矩阵 self.init_view() #启动光照 glEnable(GL_LIGHTING) #清空颜色缓存与深度缓存 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) #设置模型视图矩阵,这节课先用单位矩阵就行了。 glMatrixMode(GL_MODELVIEW) glPushMatrix() glLoadIdentity() #渲染场景 self.scene.render() #每次渲染后复位光照状态 glDisable(GL_LIGHTING) glCallList(G_OBJ_PLANE) glPopMatrix() #把数据刷新到显存上 glFlush() def init_view(self): """ 初始化投影矩阵 """ xSize, ySize = glutGet(GLUT_WINDOW_WIDTH), glutGet(GLUT_WINDOW_HEIGHT) #得到屏幕宽高比 aspect_ratio = float(xSize) / float(ySize) #设置投影矩阵 glMatrixMode(GL_PROJECTION) glLoadIdentity() #设置视口,应与窗口重合 glViewport(0, 0, xSize, ySize) #设置透视,摄像机上下视野幅度70度 #视野范围到距离摄像机1000个单位为止。 gluPerspective(70, aspect_ratio, 0.1, 1000.0) #摄像机镜头从原点后退15个单位 glTranslated(0, 0, -15)
class Viewer(object): def __init__(self): """ Initialize the viewer. """ #初始化接口,创建窗口并注册渲染函数 self.init_interface() #初始化opengl的配置 self.init_opengl() #初始化3d场景 self.init_scene() #初始化交互操作相关的代码 self.init_interaction() init_primitives() def init_interface(self): """ 初始化窗口并注册渲染函数 """ glutInit() glutInitWindowSize(640, 480) glutCreateWindow(b"3D Modeller") glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB) #注册窗口渲染函数 glutDisplayFunc(self.render) 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_scene(self): #创建一个场景实例 self.scene = Scene() #初始化场景内的对象 self.create_sample_scene() def create_sample_scene(self): ''' cube_node = Cube() cube_node.translate(2, 2, 2) cube_node.color_index = 1 self.scene.add_node(cube_node) sphere_node = Sphere() sphere_node.translate(2, 0, 2) sphere_node.color_index = 3 self.scene.add_node(sphere_node) hierarchical_node = SnowFigure() hierarchical_node.translate(-2, 0, -2) self.scene.add_node(hierarchical_node) three_pyramid = ThreePyramid() three_pyramid.translate(0,10,0) three_pyramid.scale(4) three_pyramid.color_index=5 self.scene.add_node(three_pyramid) ''' man = Man() man.translate(0, 0, 0) man.scale(8) man.color_index = 1 self.scene.add_node(man) def init_interaction(self): self.interaction = Interaction() self.interaction.register_callback('pick', self.pick) self.interaction.register_callback('move', self.move) self.interaction.register_callback('place', self.place) self.interaction.register_callback('rotate_color', self.rotate_color) self.interaction.register_callback('scale', self.scale) def pick(self, x, y): """ 是否被选中以及哪一个被选中交由Scene下的pick处理 """ start, direction = self.get_ray(x, y) self.scene.pick(start, direction, self.modelView) def move(self, x, y): start, direction = self.get_ray(x, y) self.scene.move_selected(start, direction, self.inverseModelView) def place(self, shape, x, y): start, direction = self.get_ray(x, y) self.scene.place(shape, start, direction, self.inverseModelView) def rotate_color(self, forward): """ 更改选中节点的颜色 """ pass def scale(self, up): """ 改变选中节点的大小 """ pass def main_loop(self): #程序主循环开始 glutMainLoop() def render(self): #初始化投影矩阵 self.init_view() #启动光照 glEnable(GL_LIGHTING) #清空颜色缓存与深度缓存 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) #设置模型视图矩阵,这节课先用单位矩阵就行了。 glMatrixMode(GL_MODELVIEW) glPushMatrix() glLoadIdentity() glMultMatrixf(self.interaction.trackball.matrix) # 存储ModelView矩阵与其逆矩阵之后做坐标系转换用 currentModelView = numpy.array(glGetFloatv(GL_MODELVIEW_MATRIX)) self.modelView = numpy.transpose(currentModelView) self.inverseModelView = inv(numpy.transpose(currentModelView)) #渲染场景 self.scene.render() #每次渲染后复位光照状态 glDisable(GL_LIGHTING) glCallList(G_OBJ_PLANE) glPopMatrix() #把数据刷新到显存上 glFlush() def init_view(self): """ 初始化投影矩阵 """ xSize, ySize = glutGet(GLUT_WINDOW_WIDTH), glutGet(GLUT_WINDOW_HEIGHT) #得到屏幕宽高比 aspect_ratio = float(xSize) / float(ySize) #设置投影矩阵 glMatrixMode(GL_PROJECTION) glLoadIdentity() #设置视口,应与窗口重合 glViewport(0, 0, xSize, ySize) #设置透视,摄像机上下视野幅度70度 #视野范围到距离摄像机1000个单位为止。 gluPerspective(70, aspect_ratio, 0.1, 1000.0) #摄像机镜头从原点后退15个单位 glTranslated(0, 0, -15) def get_ray(self, x, y): """ 返回光源和激光方向 """ self.init_view() glMatrixMode(GL_MODELVIEW) glLoadIdentity() # 得到激光的起始点 start = numpy.array(gluUnProject(x, y, 0.001)) end = numpy.array(gluUnProject(x, y, 0.999)) # 得到激光的方向 direction = end - start direction = direction / norm(direction) return (start, direction)
class Viewer(object): def __init__(self): self.init_interface() # 初始化接口,创建窗口并注册渲染函数 self.init_opengl() # 初始化opengl配置 self.init_scene() # 初始化3D场景 self.init_interaction() # 初始化交互操作代码 def init_interface(self): """初始化窗口并注册渲染函数""" glutInit() glutInitWindowSize(640, 480) glutCreateWindow(b'3D Modeller') glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB) '''注册窗口渲染函数''' glutDisplayFunc(self.render) 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) def init_scene(self): # 初始化场景 self.scene = Scene() # 初始化场景类对象 self.create_sample_scene() def create_sample_seene(self): sphere_node = Sphere() sphere_node.color_index = 2 self.scene.add_node(sphere_node) def init_interaction(self): # 初始化交互操作 pass def main_loop(self): # 程序主循环开始 glutMainLoop() def render(self): # 每次循环调用的渲染函数 self.init_view() # 初始化投影矩阵 glEnable(GL_LIGHTING) # 启动光照 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) # 清空颜色缓存和深度缓存 # 设置模型视图矩阵,此处使用单位矩阵 glMatrixMode(GL_MODELVIEW) glPushMatrix() glLoadIdentity() # 渲染场景 self.scene.render() # 每次渲染后恢复光照状态 glDisable(GL_LIGHTING) glPopMatrix() # 把数据刷新到显存上 glFlush() def init_view(self): """初始化投影矩阵""" xSize, ySize = glutGet(GLUT_WINDOW_WIDTH), glutGet(GLUT_WINDOW_HEIGHT) # 得到屏幕宽高比 aspect_ratio = float(xSize) / float(ySize) # 设置投影矩阵 glMatrixMode(GL_PROJECTION) glLoadIdentity() # 设置视口,应与窗口重合 glViewport(0, 0, xSize, ySize) # 设置透视,摄像机上下视野幅度70度 # 视野范围到距离摄像机1000个单位为止。 gluPerspective(70, aspect_ratio, 0.1, 1000.0) # 摄像机镜头从原点后退15个单位 glTranslated(0, 0, -15)
class Viewer(object): def __init__(self): """ Initialize the viewer. """ self.init_interface() self.init_opengl() self.init_scene() self.init_interaction() init_primitives() make_plane() def init_interface(self): glutInit() glutInitWindowSize(640, 480) glutCreateWindow("3D Modeller") glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB) #register render function glutDisplayFunc(self.render) 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_interaction(self): self.interaction = Interaction() self.interaction.register_callback('pick', self.pick) self.interaction.register_callback('move', self.move) self.interaction.register_callback('place', self.place) self.interaction.register_callback('rotate_color', self.rotate_color) self.interaction.register_callback('scale', self.scale) def move(self, x, y): #move the chosen point start, direction = self.get_ray(x, y) self.scene.move_selected(start, direction, self.inverseModelView) def place(self, shape, x, y): """ put a new node at the mouse's location""" start, direction = self.get_ray(x, y) self.scene.place(shape, start, direction, self.inverseModelView) def rotate_color(self, forward): """change the color of chosen node""" pass def scale(self, up): """change the size of the chosen node""" pass def main_loop(self): glutMainLoop() def render(self): #init shadow matrix self.init_view() #open light glEnable(GL_LIGHTING) #clear color and depth caches glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) #set model view matrix(danwei matrix is ok) #set trackball's rotate matrix as Modelview glMatrixMode(GL_MODELVIEW) glPushMatrix() #replace now-matrix with hengdeng matrix glLoadIdentity() glMultMatrixf(self.interaction.trackball.matrix) #save Modelview matrix, later change system with anti-matrix currentModelView = numpy.array(glGetFloatv(GL_MODELVIEW_MATRIX)) self.modelView = numpy.transpose(currentModelView) self.inverseModelView = inv(numpy.transpose(currentModelView)) #rend the scene self.scene.render() #after each shadow , huifu light state glDisable(GL_LIGHTING) glPopMatrix() glFlush() def init_view(self): """init shadow matrix""" xSize, ySize = glutGet(GLUT_WINDOW_WIDTH), glutGet(GLUT_WINDOW_HEIGHT) #get screen's kuangaobi aspect_ratio = float(xSize) / float(ySize) #set shadow matrix glMatrixMode(GL_PROJECTION) glLoadIdentity() #set viewport, should be chonghe with window glViewport(0, 0, xSize, ySize) #set toushi, eyesight width 70 degree, 1000 distance fron camare gluPerspective(70, aspect_ratio, 0.1, 1000.0) #jinftou back 15 distances from o glTranslated(0, 0, -15) def init_scene(self): self.scene = Scene() self.create_sample_scene() def create_sample_scene(self): cube_node = Cube() cube_node.translate(2, 0, 2) cube_node.color_index = 1 self.scene.add_node(cube_node) # to create a ball sphere_node = Sphere() # to set the ball's color sphere_node.color_index = 3 sphere_node.translate(-2, 0, 2) #to put the ball in the scene.Default middle of view self.scene.add_node(sphere_node) #to add a snowman hierarchical_node = SnowFigure() hierarchical_node.translate(-2, 0, -2) self.scene.add_node(hierarchical_node) init_primitives() def get_ray(self, x, y): self.init_view() glMatrixMode(GL_MODELVIEW) glLoadIdentity() start = numpy.array(gluUnProject(x, y, 0.001)) end = numpy.array(gluUnProject(x, y, 0.999)) direction = end - start direction = direction / norm(direction) return (start, direction) def pick(self, x, y): start, direction = self.get_ray(x, y) self.scene.pick(start, direction, self.modelView)
class Viewer: """Manages window creation and rendering. Contains main loop of program""" def __init__(self): # Initialize our interface self.init_interface() # initialize openGL # ModelView and inverse are set to identity matrix to start with self.inverseModelView = numpy.identity(4) self.ModelView = numpy.identity(4) self.init_opengl() # initialize our scene self.scene = Scene() self.create_sample_scene() # Initialize our interactions self.interaction = Interaction() self.init_interaction() init_primitives() def init_interface(self): """Initialize the window and register the render function""" glutInit() # initialize GLUT library glutInitWindowSize(640, 480) # set window size glutCreateWindow("3D Modeller") # creates window and sets title glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB) # Default: GLUT_SINGLE, GLUT_RGB glutDisplayFunc(self.render) # set display callback for current window @staticmethod def init_opengl(): """initialize opengl settings to render the scene""" # Note: Cull basically == get rid of glEnable(GL_CULL_FACE ) # Allow getting rid of objects not in view for efficiency glCullFace( GL_BACK) # We get rid of the back face of polygons not in view glEnable( GL_DEPTH_TEST ) # do depth comparisons and update the depth buffer. Note: depth = pixel depth glDepthFunc( GL_LESS ) # Specifies function used to compare incoming pixel with the depth value present # in the depth buffer. I.e. whether or not incoming objects at same pixel location replaces old objects. # In this case, it passes if incoming depth value < stored depth value. glEnable( GL_LIGHT0 ) # Set source of light. this is a single light. Can enable GL_LIGHT (1-7) for more lights. glLightfv(GL_LIGHT0, GL_POSITION, GLfloat_4( 0, 0, 1, 0)) # specifies a \light\, a light source for \light\, # and a pointer to the value(s) that the light source of \light\ will be set to. glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, GLfloat_3(0, 0, -1)) # same as above. # Note: GL_POSITION = position of light, and GL_SPOT_DIRECTION = direction of light. glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE ) # Specifies which faces should track current colour, # and specifies details on light quality. glEnable( GL_COLOR_MATERIAL) # Enables the settings we previously just set glClearColor(0.4, 0.4, 0.4, 0.0) # sets default RGBA values that glClear sets to. def create_sample_scene(self): """ Create a sample scene.""" cube_node = Cube() # cube_node.translate(2, 0, 2) cube_node.color_index = 2 self.scene.add_node(cube_node) sphere_node = Sphere() # sphere_node.translate(-2, 0, 2) sphere_node.color_index = 3 self.scene.add_node(sphere_node) def init_interaction(self): """ init user interaction and callbacks """ pass # self.interaction.register_callback('pick', self.pick) # self.interaction.register_callback('move', self.move) # self.interaction.register_callback('place', self.place) # self.interaction.register_callback('rotate_color', self.rotate_color) # self.interaction.register_callback('scale', self.scale) @staticmethod def main_loop(): glutMainLoop() @staticmethod def init_view(): """ Initialize the projection matrix""" width, height = glutGet(GLUT_WINDOW_WIDTH), glutGet( GLUT_WINDOW_HEIGHT) # self explanatory aspect_ratio = width / height # ratio of width to height # load the projection matrix. Always the same. glMatrixMode( GL_PROJECTION ) # specifies projection matrix as matrix to do subsequent operations on. glLoadIdentity() # make projection matrix into identity matrix glViewport( 0, 0, width, height) # Sets the viewport to have proper width and height, and # specifies lower left corner be have coordinate (0,0) gluPerspective(70, aspect_ratio, 0.1, 1000.0) # Set up perspective projection matrix. # field of view angle in y dir. = 70, 0.1 and 1000 specify distance from viewer to near and far clipping plane # respectively. Objects nearer than near clipping plane or farther than far clipping plane are not rendered glTranslated(0, 0, -15) # multiply curr. matrix by this def render(self): """ The render pass for the scene""" self.init_view() # Initialize projection matrix glEnable(GL_LIGHTING ) # Use curr. lighting parameters to compute vertex colour glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) # Set these stuff back to default value # Load the modelview matrix from the current state of the trackball glMatrixMode(GL_MODELVIEW) # Set modelview matrix as curr. matrix glPushMatrix( ) # duplicate and push down the stack the curr. matrix. add duplicate to top. glLoadIdentity() # replace curr. matrix with identity matrix loc = self.interaction.translation # current location of camera glTranslated( loc[0], loc[1], loc[2]) # multiply current matrix with a translation matrix glMultMatrixf(self.interaction.trackball.matrix ) # multiply current matrix with given matrix # store the inverse of the current modelview. current_modelview = numpy.array(glGetFloatv(GL_MODELVIEW_MATRIX)) self.ModelView = numpy.transpose(current_modelview) self.inverseModelView = numpy.linalg.inv( numpy.transpose(current_modelview)) # render the scene. This calls the render function for each object in the scene self.scene.render() # draw the grid glDisable(GL_LIGHTING) glCallList(G_OBJ_PLANE) glPopMatrix() # flush the buffers so that the scene can be drawn glFlush() def generate_ray(self, x: int, y: int) -> tuple: """ Generates a ray beginning at the near plane in the direction the x,y coordinates are facing :param x: x coordinate of mouse :param y: y coordinate of mouse :return: a tuple containing ? start ? and the direction of the ray """ self.init_view() glMatrixMode(GL_MODELVIEW) glLoadIdentity() # get two points on the line. start = numpy.array(gluUnProject(x, y, 0.001)) # z coordinate = 0.001 end = numpy.array(gluUnProject(x, y, 0.999)) # z coordinate = 0.999 # convert those points into a direction direction = end - start # the difference between the two points gives a vector direction = direction / norm( direction) # we divide by the norm of the vector to normalize it return start, direction def pick(self, x, y): """ Execute pick of an object. Selects an object in the scene. """ start, direction = self.generate_ray(x, y) self.scene.pick(start, direction, self.ModelView)
class Viewer(object): def __init__(self): """ Initialize the viewer. """ self.init_interface() self.init_opengl() self.init_scene() self.init_camera() self.init_interaction() init_primitives() # makes lists of primitive objects defined # self.rosnode = rospy.init_node('viewer', anonymous=False) # self.rossub = rospy.Subscriber('/viewer/posetopic', PoseStamped, self.roscallback) # self.rate = rospy.Rate(100.); # def roscallback(self,data): # node = self.scene.get_node(data.header.frame_id) # # embed() # if not node == None: # node.set_pose(data.pose.position.x,data.pose.position.y,data.pose.position.z, # data.pose.orientation.w,data.pose.orientation.x,data.pose.orientation.y,data.pose.orientation.z) # px,py,pz = GroundtoGraphics((data.pose.position.x,data.pose.position.y,data.pose.position.z)) # self.interaction.LookAttarget = [px,py,pz]; # glutPostRedisplay() def init_interface(self): """ initialize the window and register the render function """ glutInit() glutInitWindowSize(640, 480) glutCreateWindow("3D Modeller") glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB) glutDisplayFunc(self.render) # top level render call glutIdleFunc(self.ROSsleep) # def ROSsleep(self): # self.rate.sleep() 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) # put some initial lighting 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_camera(self): self.Camera = Camera(); self.Camera.CameraMode = 'Trackball'; def init_scene(self): """ initialize the scene object and initial scene """ self.scene = Scene() # self.create_sample_scene() def create_sample_scene(self): cube_node = Cube() cube_node.translate(2, 0, 2) cube_node.color_index = 1 self.scene.add_node(cube_node) sphere_node = Sphere() sphere_node.translate(-2, 0, 2) sphere_node.color_index = 3 self.scene.add_node(sphere_node) hierarchical_node = SnowFigure() hierarchical_node.translate(-2, 0, -2) self.scene.add_node(hierarchical_node) def create_scene(self): self.create_sample_scene(); def init_interaction(self): """ init user interaction and callbacks """ self.interaction = Interaction() self.interaction.register_callback('pick', self.pick) self.interaction.register_callback('move', self.move) self.interaction.register_callback('place', self.place) self.interaction.register_callback('rotate_color', self.rotate_color) self.interaction.register_callback('scale', self.scale) self.interaction.register_callback('close',self.close) self.interaction.register_callback('setCameraMode',self.setCameraMode) def main_loop(self): glutMainLoop() def render(self): """ The render pass for the scene """ self.init_view() glEnable(GL_LIGHTING) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) # Load the modelview matrix from the current state of the trackball glMatrixMode(GL_MODELVIEW) glPushMatrix() glLoadIdentity() tar = self.interaction.LookAttarget; self.Camera.target = (tar[0],tar[1],tar[2]) if self.Camera.CameraMode == 'Trackball': loc = self.Camera.position; #Camera.position glTranslated(-loc[0], -loc[1], -loc[2]) glMultMatrixf(self.interaction.trackball.matrix) elif self.Camera.CameraMode == 'LookAt': # embed() self.Camera.point() elif self.Camera.CameraMode == 'LookAtFollow': self.Camera.follow() self.Camera.point() else: glMultMatrixf(self.interaction.trackball.matrix) # by default revert to trackball if mode is set incorrectly # store the inverse of the current modelview. currentModelView = numpy.array(glGetFloatv(GL_MODELVIEW_MATRIX)) self.modelView = numpy.transpose(currentModelView) self.inverseModelView = inv(numpy.transpose(currentModelView)) # render the scene. This will call the render function for each object in the scene self.scene.render() # draw the grid glDisable(GL_LIGHTING) glCallList(G_OBJ_PLANE) glPopMatrix() # flush the buffers so that the scene can be drawn glFlush() def init_view(self): """ initialize the projection matrix """ # xSize, ySize = glutGet(GLUT_WINDOW_WIDTH), glutGet(GLUT_WINDOW_HEIGHT) # aspect_ratio = float(xSize) / float(ySize) self.Camera.ViewportSetup() # load the projection matrix. Always the same # glMatrixMode(GL_PROJECTION) # glLoadIdentity() # glViewport(0, 0, xSize, ySize) # gluPerspective(70, aspect_ratio, 0.1, 1000.0) # glTranslated(0, 0, -15) def get_ray(self, x, y): """ Generate a ray beginning at the near plane, in the direction that the x, y coordinates are facing Consumes: x, y coordinates of mouse on screen Return: start, direction of the ray """ self.init_view() glMatrixMode(GL_MODELVIEW) glLoadIdentity() # get two points on the line. start = numpy.array(gluUnProject(x, y, 0.001)) end = numpy.array(gluUnProject(x, y, 0.999)) # convert those points into a ray direction = end - start direction = direction / norm(direction) return (start, direction) def pick(self, x, y): """ Execute pick of an object. Selects an object in the scene. """ start, direction = self.get_ray(x, y) self.interaction.node_selected = self.scene.pick(start, direction, self.modelView) def place(self, shape, x, y): """ Execute a placement of a new primitive into the scene. """ start, direction = self.get_ray(x, y) self.scene.place(shape, start, direction, self.inverseModelView) def move(self, x, y): """ Execute a move command on the scene. """ start, direction = self.get_ray(x, y) self.scene.move_selected(start, direction, self.inverseModelView) # def ROSHandler(self,ind,pose): # self.scene.set_pose(ind,pose) def rotate_color(self, forward): """ Rotate the color of the selected Node. Boolean 'forward' indicates direction of rotation. """ self.scene.rotate_selected_color(forward) def scale(self, up): """ Scale the selected Node. Boolean up indicates scaling larger.""" self.scene.scale_selected(up) def setCameraMode(self,mode): self.Camera.CameraMode = mode; def close(self): # embed() glutDestroyWindow(glutGetWindow()) # embed() sys.exit() # How do I clean up memory resources before exiting? Is it needed, or handled by destroywindow