78 lines
2.6 KiB
Python
78 lines
2.6 KiB
Python
|
'''
|
||
|
3D Rotating Monkey Head
|
||
|
========================
|
||
|
|
||
|
This example demonstrates using OpenGL to display a rotating monkey head. This
|
||
|
includes loading a Blender OBJ file, shaders written in OpenGL's Shading
|
||
|
Language (GLSL), and using scheduled callbacks.
|
||
|
|
||
|
The monkey.obj file is an OBJ file output from the Blender free 3D creation
|
||
|
software. The file is text, listing vertices and faces and is loaded
|
||
|
using a class in the file objloader.py. The file simple.glsl is
|
||
|
a simple vertex and fragment shader written in GLSL.
|
||
|
'''
|
||
|
|
||
|
from kivy.app import App
|
||
|
from kivy.clock import Clock
|
||
|
from kivy.core.window import Window
|
||
|
from kivy.uix.widget import Widget
|
||
|
from kivy.resources import resource_find
|
||
|
from kivy.graphics.transformation import Matrix
|
||
|
from kivy.graphics.opengl import glEnable, glDisable, GL_DEPTH_TEST
|
||
|
from kivy.graphics import RenderContext, Callback, PushMatrix, PopMatrix, \
|
||
|
Color, Translate, Rotate, Mesh, UpdateNormalMatrix
|
||
|
from objloader import ObjFile
|
||
|
|
||
|
|
||
|
class Renderer(Widget):
|
||
|
def __init__(self, **kwargs):
|
||
|
self.canvas = RenderContext(compute_normal_mat=True)
|
||
|
self.canvas.shader.source = resource_find('simple.glsl')
|
||
|
self.scene = ObjFile(resource_find("monkey.obj"))
|
||
|
super(Renderer, self).__init__(**kwargs)
|
||
|
with self.canvas:
|
||
|
self.cb = Callback(self.setup_gl_context)
|
||
|
PushMatrix()
|
||
|
self.setup_scene()
|
||
|
PopMatrix()
|
||
|
self.cb = Callback(self.reset_gl_context)
|
||
|
Clock.schedule_interval(self.update_glsl, 1 / 60.)
|
||
|
|
||
|
def setup_gl_context(self, *args):
|
||
|
glEnable(GL_DEPTH_TEST)
|
||
|
|
||
|
def reset_gl_context(self, *args):
|
||
|
glDisable(GL_DEPTH_TEST)
|
||
|
|
||
|
def update_glsl(self, delta):
|
||
|
asp = self.width / float(self.height)
|
||
|
proj = Matrix().view_clip(-asp, asp, -1, 1, 1, 100, 1)
|
||
|
self.canvas['projection_mat'] = proj
|
||
|
self.canvas['diffuse_light'] = (1.0, 1.0, 0.8)
|
||
|
self.canvas['ambient_light'] = (0.1, 0.1, 0.1)
|
||
|
self.rot.angle += delta * 100
|
||
|
|
||
|
def setup_scene(self):
|
||
|
Color(1, 1, 1, 1)
|
||
|
PushMatrix()
|
||
|
Translate(0, 0, -3)
|
||
|
self.rot = Rotate(1, 0, 1, 0)
|
||
|
m = list(self.scene.objects.values())[0]
|
||
|
UpdateNormalMatrix()
|
||
|
self.mesh = Mesh(
|
||
|
vertices=m.vertices,
|
||
|
indices=m.indices,
|
||
|
fmt=m.vertex_format,
|
||
|
mode='triangles',
|
||
|
)
|
||
|
PopMatrix()
|
||
|
|
||
|
|
||
|
class RendererApp(App):
|
||
|
def build(self):
|
||
|
return Renderer()
|
||
|
|
||
|
|
||
|
if __name__ == "__main__":
|
||
|
RendererApp().run()
|