├── .gitattributes ├── .gitignore ├── LICENSE ├── Manifest.in ├── README.md ├── examples ├── blinnphong.glsl ├── camera │ └── main.py ├── createscene.py ├── example1.py ├── example2.py ├── example3.py ├── extended.glsl ├── monkey.obj ├── monkey.py ├── simple.glsl ├── test.stl ├── testnurbs-2.mtl ├── testnurbs-2.obj ├── testnurbs.mtl ├── testnurbs.obj ├── textures │ ├── main.py │ ├── orion.mtl │ ├── orion.obj │ ├── orion.png │ └── simple.glsl └── trackball │ ├── Digital.tga │ ├── MQ-27-2.obj │ ├── MQ-27-2.obj.mtl │ ├── MQ-27.mtl │ ├── MQ-27.obj │ ├── Tan.tga │ ├── gun.tga │ ├── gun_normal.tga │ ├── gun_spec.tga │ ├── main.py │ ├── mq_normal.tga │ ├── mq_spec.tga │ └── rotor.tga ├── kivy3.dia ├── kivy3 ├── __init__.py ├── cameras │ ├── __init__.py │ ├── camera.py │ ├── orthographic_camera.py │ └── perspective_camera.py ├── core │ ├── __init__.py │ ├── face3.py │ ├── geometry.py │ └── object3d.py ├── default.glsl ├── extras │ ├── __init__.py │ └── geometries.py ├── light.py ├── loaders │ ├── __init__.py │ ├── empty.png │ ├── loader.py │ ├── objloader.py │ └── stlloader.py ├── materials.py ├── math │ ├── __init__.py │ └── vectors.py ├── objects │ ├── __init__.py │ └── mesh.py ├── renderer.py └── scenes │ ├── __init__.py │ └── scene.py ├── setup.py ├── test.py └── tests ├── __init__.py ├── core ├── __init__.py └── test_object3d.py ├── loaders ├── __init__.py ├── test_loader.py └── test_objloader.py ├── test_materials.py ├── test_vectors.py ├── testnurbs.obj └── utils.py /.gitattributes: -------------------------------------------------------------------------------- 1 | # Basic .gitattributes for a python repo. 2 | 3 | # Source files 4 | # ============ 5 | *.pxd text 6 | *.py text 7 | *.py3 text 8 | *.pyw text 9 | *.pyx text 10 | 11 | # Binary files 12 | # ============ 13 | *.db binary 14 | *.p binary 15 | *.pkl binary 16 | *.pyc binary 17 | *.pyd binary 18 | *.pyo binary 19 | *.obj binary 20 | *.mtl binary 21 | 22 | # Note: .db, .p, and .pkl files are associated 23 | # with the python modules ``pickle``, ``dbm.*``, 24 | # ``shelve``, ``marshal``, ``anydbm``, & ``bsddb`` 25 | # (among others). 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyo 2 | *.pyc 3 | *~ 4 | build 5 | MANIFEST 6 | dist 7 | *.egg-info 8 | venv/ 9 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014-2016 Niko Skrypnik and contributors 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /Manifest.in: -------------------------------------------------------------------------------- 1 | recursive-include kivy3 *.* -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Kivy3 - 3D graphics framework for Kivy 2 | 3 | Kivy3 is the framework which helps people work with 3D elements and rendering 4 | within Kivy application. Basically with Kivy and Kivy3 you may create a 3D 5 | application for any platform Kivy supports, such as: iOS, Android, Windows, 6 | OSX, Linux (including Raspberry Pi). 7 | 8 | Kivy3 provides a toolset and abstraction levels to work with 3D objects like 9 | Camera, Scene, Renderers, loaders you may use to load 3D objects. 10 | 11 | # Installation 12 | 13 | First make sure that you have `kivy` installed on your machine. Mostly 14 | a simple: 15 | 16 | $ pip install kivy 17 | 18 | should be sufficient, but stable version will not include the latest features. 19 | For further info visit 20 | [Kivy documentation](https://kivy.org/docs/installation/installation.html). 21 | After successful Kivy installation install Kivy3 with this: 22 | 23 | $ pip install https://github.com/kivy/kivy3/archive/master.zip 24 | 25 | # Packaging kivy3 26 | 27 | Kivy3 is a pure python package, currently available only at GitHub, which 28 | means that for packaging it e.g. for Android you need to clone the folder 29 | to your application folder (the one with `main.py`). If you can run the app 30 | on a desktop machine, it should work even on other platforms. 31 | 32 | Don't forget to add an include exception for additional files, such as shader 33 | (`*.glsl`) and other files you may find in the `kivy3` folder. 34 | -------------------------------------------------------------------------------- /examples/blinnphong.glsl: -------------------------------------------------------------------------------- 1 | ---VERTEX SHADER------------------------------------------------------- 2 | /** 3 | * Based on: https://learnopengl.com/Advanced-Lighting/Advanced-Lighting 4 | */ 5 | 6 | #ifdef GL_ES 7 | precision highp float; 8 | #endif 9 | 10 | attribute vec3 v_pos; 11 | attribute vec3 v_normal; 12 | attribute vec4 v_color; 13 | attribute vec2 v_tc0; 14 | 15 | uniform mat4 modelview_mat; 16 | uniform mat4 projection_mat; 17 | 18 | varying vec4 frag_color; 19 | varying vec2 uv_vec; 20 | varying vec4 normal_vec; 21 | varying vec4 vertex_pos; 22 | 23 | void main (void) { 24 | vec4 pos = modelview_mat * vec4(v_pos,1.0); 25 | vertex_pos = pos; 26 | gl_Position = projection_mat * pos; 27 | frag_color = v_color; 28 | uv_vec = v_tc0; 29 | normal_vec = modelview_mat * vec4(v_normal, 0.0); 30 | } 31 | 32 | 33 | ---FRAGMENT SHADER----------------------------------------------------- 34 | #ifdef GL_ES 35 | precision highp float; 36 | #endif 37 | 38 | varying vec4 frag_color; 39 | varying vec2 uv_vec; 40 | varying vec4 normal_vec; 41 | varying vec4 vertex_pos; 42 | 43 | uniform mat4 normal_mat; 44 | uniform sampler2D tex; 45 | 46 | uniform vec3 light_pos; 47 | uniform float light_intensity; 48 | uniform vec3 camera_pos; 49 | 50 | uniform vec3 Ka; // color (ambient) 51 | uniform vec3 Kd; // diffuse color 52 | uniform vec3 Ks; // specular color 53 | uniform float Tr; // transparency 54 | uniform float Ns; // shininess 55 | uniform float d; // dissolve 56 | uniform float ambient_ratio; 57 | 58 | void main (void){ 59 | vec4 color = texture2D(tex, uv_vec); 60 | color = vec4(Ka, Tr); 61 | if (Ns > 0.0) { 62 | // ambient 63 | vec3 ambient = ambient_ratio * vec3(color); 64 | // diffuse 65 | vec3 lightDir = normalize(light_pos - vec3(vertex_pos)); 66 | vec3 normal = normalize(vec3(normal_vec)); 67 | float diff = max(dot(lightDir, normal), 0.0); 68 | vec3 diffuse = diff * vec3(Kd); 69 | // specular 70 | vec3 viewDir = normalize(camera_pos - vec3(vertex_pos)); 71 | vec3 reflectDir = reflect(-lightDir, normal); 72 | 73 | // Blinn-Phong lighting 74 | vec3 halfwayDir = normalize(lightDir + viewDir); 75 | float spec = pow(max(dot(normal, halfwayDir), 0.0), Ns); 76 | 77 | // vec3 specular = vec3(0.3) * spec;// assuming bright white light color 78 | vec3 specular = Ks * spec;// assuming bright white light color 79 | gl_FragColor = vec4(ambient + diffuse + specular, color[3]); 80 | } else { 81 | gl_FragColor = color; 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /examples/camera/main.py: -------------------------------------------------------------------------------- 1 | 2 | import os 3 | import kivy3 4 | from kivy.app import App 5 | from kivy.clock import Clock 6 | from kivy.core.window import Window 7 | from kivy3 import Scene, Renderer, PerspectiveCamera, Vector3 8 | from kivy3.loaders import OBJMTLLoader 9 | from kivy.uix.floatlayout import FloatLayout 10 | 11 | # Resources pathes 12 | _this_path = os.path.dirname(os.path.realpath(__file__)) 13 | shader_file = os.path.join(_this_path, "../textures/simple.glsl") 14 | obj_file = os.path.join(_this_path, "../textures/orion.obj") 15 | mtl_file = os.path.join(_this_path, "../textures/orion.mtl") 16 | 17 | 18 | class MainApp(App): 19 | 20 | def build(self): 21 | self.look_at = Vector3(0, 0, -1) 22 | root = FloatLayout() 23 | self.renderer = Renderer(shader_file=shader_file) 24 | scene = Scene() 25 | self.camera = PerspectiveCamera(75, 1, 1, 1000) 26 | self.camera.pos.z = 5 27 | loader = OBJMTLLoader() 28 | obj = loader.load(obj_file, mtl_file) 29 | self._keyboard = Window.request_keyboard(self._keyboard_closed, self) 30 | self._keyboard.bind(on_key_down=self._on_keyboard_down) 31 | 32 | scene.add(*obj.children) 33 | 34 | self.renderer.render(scene, self.camera) 35 | self.orion = scene.children[0] 36 | 37 | root.add_widget(self.renderer) 38 | self.renderer.bind(size=self._adjust_aspect) 39 | Clock.schedule_interval(self._rotate_obj, 1 / 20) 40 | return root 41 | 42 | def _adjust_aspect(self, inst, val): 43 | rsize = self.renderer.size 44 | aspect = rsize[0] / float(rsize[1]) 45 | self.renderer.camera.aspect = aspect 46 | 47 | def _keyboard_closed(self): 48 | self._keyboard.unbind(on_key_down=self._on_keyboard_down) 49 | self._keyboard = None 50 | 51 | def _on_keyboard_down(self, keyboard, keycode, text, modifiers): 52 | if keycode[1] == 'w': 53 | self.camera.pos.z -= 0.2 54 | elif keycode[1] == 's': 55 | self.camera.pos.z += 0.2 56 | elif keycode[1] == 'a': 57 | self.camera.pos.y -= 0.2 58 | elif keycode[1] == 'd': 59 | self.camera.pos.y += 0.2 60 | 61 | elif keycode[1] == 'up': 62 | self.look_at.y += 0.2 63 | elif keycode[1] == 'down': 64 | self.look_at.y -= 0.2 65 | elif keycode[1] == 'right': 66 | self.look_at.x += 0.2 67 | elif keycode[1] == 'left': 68 | self.look_at.x -= 0.2 69 | 70 | self.camera.look_at(self.look_at) 71 | 72 | def _rotate_obj(self, dt): 73 | self.orion.rot.x += 2 74 | self.orion.rot.z += 2 75 | 76 | 77 | if __name__ == '__main__': 78 | MainApp().run() 79 | -------------------------------------------------------------------------------- /examples/createscene.py: -------------------------------------------------------------------------------- 1 | 2 | import os 3 | import kivy3 4 | from kivy.app import App 5 | from kivy.uix.floatlayout import FloatLayout 6 | from kivy.clock import Clock 7 | from kivy3 import Mesh, Material 8 | from kivy3 import Scene, Renderer, PerspectiveCamera, OrthographicCamera 9 | from kivy3.extras.geometries import BoxGeometry, CylinderGeometry, SphereGeometry 10 | from kivy3.loaders import OBJLoader, STLLoader 11 | 12 | from kivy.graphics import Color, Rectangle 13 | 14 | 15 | _this_path = os.path.dirname(os.path.realpath(__file__)) 16 | shader_file = os.path.join(_this_path, "./blinnphong.glsl") 17 | obj_file = os.path.join(_this_path, "./monkey.obj") 18 | stl_file = os.path.join(_this_path, "./test.stl") 19 | 20 | class SceneApp(App): 21 | 22 | def build(self): 23 | root = FloatLayout() 24 | 25 | self.renderer = Renderer(shader_file=shader_file) 26 | self.renderer.set_clear_color((.16, .30, .44, 1.)) 27 | 28 | 29 | scene = Scene() 30 | # geometry = CylinderGeometry(0.5, 2) 31 | geometry = SphereGeometry(1) 32 | # geometry = BoxGeometry(1, 1, 1) 33 | material = Material(color=(0.3, 0., 0.3), diffuse=(0.3, 0.3, 0.3), 34 | specular=(0., 0., 0.)) 35 | 36 | loader = STLLoader() 37 | obj = loader.load(stl_file,material) 38 | self.item = obj 39 | 40 | scene.add(self.item) 41 | 42 | self.cube = Mesh(geometry, material) 43 | self.item.pos.z = -1.5 44 | #self.cube.pos.z=-5 45 | camera = PerspectiveCamera(75, 0.3, 0.5, 1000) 46 | #camera = OrthographicCamera() 47 | 48 | #scene.add(self.cube) 49 | self.renderer.render(scene, camera) 50 | 51 | root.add_widget(self.renderer) 52 | Clock.schedule_interval(self._rotate_cube, 1 / 20) 53 | self.renderer.bind(size=self._adjust_aspect) 54 | 55 | return root 56 | 57 | def _adjust_aspect(self, inst, val): 58 | rsize = self.renderer.size 59 | aspect = rsize[0] / float(rsize[1]) 60 | self.renderer.camera.aspect = aspect 61 | 62 | def _rotate_cube(self, dt): 63 | self.cube.rotation.x += 1 64 | self.cube.rotation.y += 1 65 | self.cube.rotation.z += 1 66 | self.item.rotation.x += 1 67 | self.item.rotation.y += 1 68 | self.item.rotation.z += 1 69 | 70 | 71 | if __name__ == '__main__': 72 | SceneApp().run() 73 | -------------------------------------------------------------------------------- /examples/example1.py: -------------------------------------------------------------------------------- 1 | """ 2 | The MIT License (MIT) 3 | 4 | Copyright (c) 2014 Niko Skrypnik 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | """ 24 | 25 | """ 26 | This example loads simple objects from .obj file and shows how 27 | to use custom shader file 28 | """ 29 | 30 | import os 31 | import kivy3 32 | from kivy.app import App 33 | from kivy3 import Scene, Renderer, PerspectiveCamera 34 | from kivy3.loaders import OBJLoader 35 | from kivy.uix.floatlayout import FloatLayout 36 | 37 | 38 | # Resources pathes 39 | _this_path = os.path.dirname(os.path.realpath(__file__)) 40 | shader_file = os.path.join(_this_path, "./simple.glsl") 41 | obj_path = os.path.join(_this_path, "./testnurbs.obj") 42 | 43 | 44 | class MainApp(App): 45 | 46 | def build(self): 47 | root = FloatLayout() 48 | self.renderer = Renderer(shader_file=shader_file) 49 | scene = Scene() 50 | camera = PerspectiveCamera(15, 1, 1, 1000) 51 | # load obj file 52 | loader = OBJLoader() 53 | obj = loader.load(obj_path) 54 | 55 | scene.add(*obj.children) 56 | for obj in scene.children: 57 | obj.pos.z = -20 58 | 59 | self.renderer.render(scene, camera) 60 | root.add_widget(self.renderer) 61 | self.renderer.bind(size=self._adjust_aspect) 62 | return root 63 | 64 | def _adjust_aspect(self, inst, val): 65 | rsize = self.renderer.size 66 | aspect = rsize[0] / float(rsize[1]) 67 | self.renderer.camera.aspect = aspect 68 | 69 | 70 | if __name__ == '__main__': 71 | MainApp().run() 72 | -------------------------------------------------------------------------------- /examples/example2.py: -------------------------------------------------------------------------------- 1 | """ 2 | The MIT License (MIT) 3 | 4 | Copyright (c) 2014 Niko Skrypnik 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | """ 24 | 25 | """ 26 | Same as example1 but with using default shader file and colorizing 27 | of the objects 28 | """ 29 | 30 | import os 31 | import kivy3 32 | from kivy.app import App 33 | from kivy3 import Scene, Renderer, PerspectiveCamera 34 | from kivy3.loaders import OBJLoader 35 | from kivy.uix.floatlayout import FloatLayout 36 | 37 | 38 | class MainApp(App): 39 | 40 | def build(self): 41 | root = FloatLayout() 42 | self.renderer = Renderer() 43 | scene = Scene() 44 | camera = PerspectiveCamera(15, 1, 1, 1000) 45 | # load obj file 46 | loader = OBJLoader() 47 | obj_path = os.path.join(os.path.dirname(__file__), "./testnurbs-2.obj") 48 | obj = loader.load(obj_path) 49 | 50 | scene.add(*obj.children) 51 | for obj in scene.children: 52 | obj.pos.z = -20 53 | obj.material.specular = .35, .35, .35 54 | 55 | # set colors to 3d objects 56 | scene.children[0].material.color = 0., .7, 0. # green 57 | scene.children[1].material.color = .7, 0., 0. # red 58 | scene.children[2].material.color = 0., 0., .7 # blue 59 | scene.children[3].material.color = .7, .7, 0. # yellow 60 | 61 | scene.children[0].material.diffuse = 0., .7, 0. # green 62 | scene.children[1].material.diffuse = .7, 0., 0. # red 63 | scene.children[2].material.diffuse = 0., 0., .7 # blue 64 | scene.children[3].material.diffuse = .7, .7, 0. # yellow 65 | 66 | self.renderer.render(scene, camera) 67 | root.add_widget(self.renderer) 68 | self.renderer.bind(size=self._adjust_aspect) 69 | return root 70 | 71 | def _adjust_aspect(self, inst, val): 72 | rsize = self.renderer.size 73 | aspect = rsize[0] / float(rsize[1]) 74 | self.renderer.camera.aspect = aspect 75 | 76 | 77 | if __name__ == '__main__': 78 | MainApp().run() 79 | -------------------------------------------------------------------------------- /examples/example3.py: -------------------------------------------------------------------------------- 1 | """ 2 | The MIT License (MIT) 3 | 4 | Copyright (c) 2014 Niko Skrypnik 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | """ 24 | 25 | """ 26 | This example loads simple objects from .obj file and shows how 27 | to use custom shader file 28 | """ 29 | 30 | import os 31 | import kivy3 32 | from kivy.app import App 33 | from kivy3 import Scene, Renderer, PerspectiveCamera 34 | from kivy3.loaders import OBJMTLLoader 35 | from kivy.uix.floatlayout import FloatLayout 36 | 37 | 38 | class MainApp(App): 39 | 40 | def build(self): 41 | root = FloatLayout() 42 | self.renderer = Renderer() 43 | scene = Scene() 44 | camera = PerspectiveCamera(15, 1, 1, 1000) 45 | # load obj file 46 | loader = OBJMTLLoader() 47 | obj_path = os.path.join(os.path.dirname(__file__), "./testnurbs.obj") 48 | obj = loader.load(obj_path, "./testnurbs.mtl") 49 | 50 | scene.add(*obj.children) 51 | for obj in scene.children: 52 | obj.pos.z = -20 53 | 54 | self.renderer.render(scene, camera) 55 | root.add_widget(self.renderer) 56 | self.renderer.bind(size=self._adjust_aspect) 57 | return root 58 | 59 | def _adjust_aspect(self, inst, val): 60 | rsize = self.renderer.size 61 | aspect = rsize[0] / float(rsize[1]) 62 | self.renderer.camera.aspect = aspect 63 | 64 | 65 | if __name__ == '__main__': 66 | MainApp().run() 67 | -------------------------------------------------------------------------------- /examples/extended.glsl: -------------------------------------------------------------------------------- 1 | /* simple.glsl 2 | 3 | simple diffuse lighting based on laberts cosine law; see e.g.: 4 | http://en.wikipedia.org/wiki/Lambertian_reflectance 5 | http://en.wikipedia.org/wiki/Lambert%27s_cosine_law 6 | */ 7 | ---VERTEX SHADER------------------------------------------------------- 8 | #ifdef GL_ES 9 | precision highp float; 10 | #endif 11 | 12 | 13 | attribute vec3 v_pos; 14 | attribute vec3 v_normal; 15 | attribute vec4 v_color; 16 | attribute vec2 v_tc0; 17 | 18 | uniform mat4 modelview_mat; 19 | uniform mat4 projection_mat; 20 | uniform mat4 normal_mat; 21 | uniform mat4 model_mat; 22 | uniform mat4 view_mat; 23 | 24 | varying vec4 normal_vec; 25 | varying vec4 vertex_pos; 26 | varying vec4 frag_color; 27 | varying vec2 uv_vec; 28 | 29 | void main (void) { 30 | //compute vertex position in eye_sapce and normalize normal vector 31 | vec4 pos = modelview_mat * vec4(v_pos,1.0); 32 | vertex_pos = pos; 33 | normal_vec = vec4(v_normal,0.0); 34 | 35 | frag_color = v_color; 36 | uv_vec = v_tc0; 37 | 38 | gl_Position = projection_mat * pos; 39 | } 40 | 41 | 42 | ---FRAGMENT SHADER----------------------------------------------------- 43 | #ifdef GL_ES 44 | precision highp float; 45 | #endif 46 | 47 | varying vec4 normal_vec; 48 | varying vec4 vertex_pos; 49 | 50 | uniform mat4 normal_mat; 51 | uniform mat4 model_mat; 52 | uniform mat4 view_mat; 53 | 54 | uniform vec3 camera_pos; 55 | uniform vec3 Ka; // color (ambient) 56 | uniform vec3 Kd; // diffuse color 57 | uniform vec3 Ks; // specular color 58 | uniform float Tr; // transparency 59 | uniform float Ns; // shininess 60 | uniform float tex_ratio; 61 | 62 | uniform vec3 light_pos; 63 | uniform float light_intensity; 64 | 65 | 66 | void main (void){ 67 | //correct normal, and compute light vector (assume light at the eye) 68 | vec4 v_normal = normalize( normal_mat * normal_vec ) ; 69 | vec4 v_light = normalize( vec4(0,0,0,1) - vertex_pos ); 70 | 71 | // force lightPos to lower-left (like in Kivy) 72 | vec4 lightPos = model_mat * vec4(light_pos, 0.0) - gl_FragCoord; 73 | float lightPosLen = length(lightPos); 74 | 75 | // set ambient, diffuse, specular color 76 | vec3 Ia = Ka * light_intensity / lightPosLen; 77 | vec3 Id = Kd * max(dot(v_light, v_normal), 0.0); 78 | vec3 Is = Ks * pow(max(dot(v_light, v_normal), 0.0), Ns); 79 | 80 | //reflectance based on lamberts law of cosine 81 | float theta = clamp(dot(v_normal, v_light), 0.1, 1.0); 82 | vec3 thetaColor = theta * vec3(Ia + Id + Is); 83 | 84 | gl_FragColor = vec4(thetaColor, Tr); 85 | } 86 | -------------------------------------------------------------------------------- /examples/monkey.py: -------------------------------------------------------------------------------- 1 | """ 2 | The MIT License (MIT) 3 | 4 | Copyright (c) 2014 Niko Skrypnik 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | """ 24 | 25 | import os 26 | from kivy.app import App 27 | from kivy3 import Scene, Renderer, PerspectiveCamera 28 | from kivy3.loaders import OBJLoader 29 | from kivy.uix.floatlayout import FloatLayout 30 | from kivy.clock import Clock 31 | 32 | # Resources pathes 33 | _this_path = os.path.dirname(os.path.realpath(__file__)) 34 | shader_file = os.path.join(_this_path, "./simple.glsl") 35 | obj_file = os.path.join(_this_path, "./monkey.obj") 36 | 37 | 38 | class MainApp(App): 39 | 40 | def build(self): 41 | root = FloatLayout() 42 | self.renderer = Renderer(shader_file=shader_file) 43 | scene = Scene() 44 | # load obj file 45 | loader = OBJLoader() 46 | obj = loader.load(obj_file) 47 | self.monkey = obj.children[0] 48 | 49 | scene.add(*obj.children) 50 | camera = PerspectiveCamera(15, 1, 1, 1000) 51 | 52 | self.renderer.render(scene, camera) 53 | root.add_widget(self.renderer) 54 | Clock.schedule_interval(self._update_obj, 1. / 20) 55 | self.renderer.bind(size=self._adjust_aspect) 56 | return root 57 | 58 | def _update_obj(self, dt): 59 | obj = self.monkey 60 | if obj.pos.z > -30: 61 | obj.pos.z -= 0.5 62 | 63 | def _adjust_aspect(self, inst, val): 64 | rsize = self.renderer.size 65 | aspect = rsize[0] / float(rsize[1]) 66 | self.renderer.camera.aspect = aspect 67 | 68 | 69 | if __name__ == '__main__': 70 | MainApp().run() 71 | -------------------------------------------------------------------------------- /examples/simple.glsl: -------------------------------------------------------------------------------- 1 | /* simple.glsl 2 | 3 | simple diffuse lighting based on laberts cosine law; see e.g.: 4 | http://en.wikipedia.org/wiki/Lambertian_reflectance 5 | http://en.wikipedia.org/wiki/Lambert%27s_cosine_law 6 | */ 7 | ---VERTEX SHADER------------------------------------------------------- 8 | #ifdef GL_ES 9 | precision highp float; 10 | #endif 11 | 12 | attribute vec3 v_pos; 13 | attribute vec3 v_normal; 14 | 15 | uniform mat4 modelview_mat; 16 | uniform mat4 projection_mat; 17 | 18 | varying vec4 normal_vec; 19 | varying vec4 vertex_pos; 20 | 21 | void main (void) { 22 | //compute vertex position in eye_sapce and normalize normal vector 23 | vec4 pos = modelview_mat * vec4(v_pos,1.0); 24 | vertex_pos = pos; 25 | normal_vec = vec4(v_normal,0.0); 26 | gl_Position = projection_mat * pos; 27 | } 28 | 29 | 30 | ---FRAGMENT SHADER----------------------------------------------------- 31 | #ifdef GL_ES 32 | precision highp float; 33 | #endif 34 | 35 | varying vec4 normal_vec; 36 | varying vec4 vertex_pos; 37 | 38 | uniform mat4 normal_mat; 39 | 40 | void main (void){ 41 | //correct normal, and compute light vector (assume light at the eye) 42 | vec4 v_normal = normalize( normal_mat * normal_vec ) ; 43 | vec4 v_light = normalize( vec4(0,0,0,1) - vertex_pos ); 44 | //reflectance based on lamberts law of cosine 45 | float theta = clamp(dot(v_normal, v_light), 0.0, 1.0); 46 | gl_FragColor = vec4(theta, theta, theta, 1.0); 47 | } 48 | -------------------------------------------------------------------------------- /examples/test.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivy/kivy3/e3364b39ec61a69aa31bf88e77fadaa148359ec6/examples/test.stl -------------------------------------------------------------------------------- /examples/testnurbs-2.mtl: -------------------------------------------------------------------------------- 1 | # Blender MTL File: 'None' 2 | # Material Count: 4 3 | 4 | newmtl wire_087224143 5 | Ns 29.411765 6 | Ka 0.000000 0.000000 0.000000 7 | Kd 0.272960 0.702720 0.448640 8 | Ks 0.350000 0.350000 0.350000 9 | Ni 1.000000 10 | d 1.000000 11 | illum 2 12 | 13 | newmtl wire_108008136 14 | Ns 29.411765 15 | Ka 0.000000 0.000000 0.000000 16 | Kd 0.338800 0.025120 0.426640 17 | Ks 0.350000 0.350000 0.350000 18 | Ni 1.000000 19 | d 1.000000 20 | illum 2 21 | 22 | newmtl wire_148177026 23 | Ns 29.411765 24 | Ka 0.000000 0.000000 0.000000 25 | Kd 0.464320 0.555280 0.081600 26 | Ks 0.350000 0.350000 0.350000 27 | Ni 1.000000 28 | d 1.000000 29 | illum 2 30 | 31 | newmtl wire_154154229 32 | Ns 29.411765 33 | Ka 0.000000 0.000000 0.000000 34 | Kd 0.483120 0.483120 0.718400 35 | Ks 0.350000 0.350000 0.350000 36 | Ni 1.000000 37 | d 1.000000 38 | illum 2 39 | -------------------------------------------------------------------------------- /examples/testnurbs-2.obj: -------------------------------------------------------------------------------- 1 | # Blender v2.71 (sub 0) OBJ File: '' 2 | # www.blender.org 3 | mtllib testnurbs-2.mtl 4 | o Sphere 5 | v 0.000000 0.170200 -1.293300 6 | v 0.319600 0.000000 -1.265000 7 | v 0.000000 0.000000 -1.304700 8 | v 0.000000 0.499300 -1.204900 9 | v 0.000000 0.652300 -1.129900 10 | v 0.276800 0.652300 -1.095600 11 | v 0.308600 0.337600 -1.221400 12 | v 0.000000 0.337600 -1.259700 13 | v 0.000000 0.794100 -1.035700 14 | v 0.000000 0.922400 -0.923600 15 | v 0.226200 0.922400 -0.895600 16 | v 0.000000 1.035000 -0.795400 17 | v 0.000000 1.129900 -0.652300 18 | v 0.159800 1.129900 -0.632500 19 | v 0.060800 1.260000 -0.327200 20 | v 0.081500 1.260000 -0.322700 21 | v 0.040200 1.260000 -0.330300 22 | v 0.000000 1.260000 -0.332800 23 | v 0.000000 1.205200 -0.496700 24 | v 0.000000 1.304700 0.000000 25 | v 0.000000 1.293400 -0.165600 26 | v 0.000000 1.304700 0.000000 27 | v -0.078800 -1.129900 -0.647500 28 | v 0.000000 -1.129900 -0.652300 29 | v 0.000000 -1.205200 -0.496700 30 | v 0.000000 -1.260000 -0.332800 31 | v 0.000000 -1.293400 -0.165600 32 | v 0.000000 -1.304700 -0.000000 33 | v -0.159800 -1.129900 -0.632500 34 | v 0.000000 -1.035000 -0.795400 35 | v 0.000000 -0.922400 -0.923600 36 | v -0.226200 -0.922400 -0.895600 37 | v 0.000000 -0.794100 -1.035700 38 | v -0.276800 -0.652300 -1.095600 39 | v 0.000000 -0.652300 -1.129900 40 | v 0.000000 -0.499300 -1.204900 41 | v -0.308600 -0.337600 -1.221400 42 | v 0.000000 -0.337600 -1.259700 43 | v 0.000000 -0.170200 -1.293300 44 | v -0.319600 0.000000 -1.265000 45 | v -0.308600 0.337600 -1.221400 46 | v -0.276800 0.652300 -1.095600 47 | v -0.226200 0.922400 -0.895600 48 | v -0.159800 1.129900 -0.632500 49 | v -0.040200 1.260000 -0.330300 50 | v -0.060800 1.260000 -0.327200 51 | v -0.081500 1.260000 -0.322700 52 | v 0.000000 -1.304700 -0.000000 53 | v -0.319000 -1.129900 -0.569000 54 | v -0.451700 -0.922400 -0.805600 55 | v -0.552600 -0.652300 -0.985600 56 | v -0.616100 -0.337600 -1.098800 57 | v -0.638000 0.000000 -1.138000 58 | v -0.616100 0.337600 -1.098800 59 | v -0.552600 0.652300 -0.985600 60 | v -0.451700 0.922400 -0.805700 61 | v -0.319000 1.129900 -0.569000 62 | v -0.162700 1.260000 -0.290300 63 | v -0.459900 -1.129900 -0.459800 64 | v -0.569000 -1.129900 -0.319000 65 | v -0.651200 -0.922400 -0.651000 66 | v -0.805600 -0.922400 -0.451700 67 | v -0.796600 -0.652300 -0.796400 68 | v -0.985600 -0.652300 -0.552600 69 | v -0.888100 -0.337600 -0.887900 70 | v -1.098800 -0.337600 -0.616100 71 | v -0.919800 0.000000 -0.919600 72 | v -1.138000 0.000000 -0.638000 73 | v -0.888100 0.337600 -0.887900 74 | v -1.098800 0.337600 -0.616100 75 | v -0.796600 0.652300 -0.796400 76 | v -0.985600 0.652300 -0.552600 77 | v -0.651200 0.922400 -0.651000 78 | v -0.805700 0.922400 -0.451700 79 | v -0.459900 1.129900 -0.459800 80 | v -0.569000 1.129900 -0.319000 81 | v -0.200300 1.260000 -0.265000 82 | v -0.234600 1.260000 -0.234600 83 | v -0.290300 1.260000 -0.162700 84 | v -0.636000 -1.129900 -0.162900 85 | v -0.658500 -1.129900 -0.000000 86 | v -0.636300 -1.129900 0.162900 87 | v 0.000000 -1.304700 -0.000000 88 | v -0.569000 -1.129900 0.319000 89 | v -0.900500 -0.922400 -0.230600 90 | v -0.932400 -0.922400 -0.000000 91 | v -0.900900 -0.922400 0.230600 92 | v -0.805600 -0.922400 0.451700 93 | v -1.101600 -0.652300 -0.282100 94 | v -1.140600 -0.652300 -0.000000 95 | v -1.102100 -0.652300 0.282100 96 | v -0.985600 -0.652300 0.552600 97 | v -1.228100 -0.337600 -0.314500 98 | v -1.271600 -0.337600 -0.000000 99 | v -1.228700 -0.337600 0.314500 100 | v -1.098800 -0.337600 0.616100 101 | v -1.272000 0.000000 -0.325800 102 | v -1.317000 0.000000 0.000000 103 | v -1.272600 -0.000000 0.325800 104 | v -1.138000 -0.000000 0.638000 105 | v -1.228100 0.337600 -0.314500 106 | v -1.271600 0.337600 0.000000 107 | v -1.228700 0.337600 0.314500 108 | v -1.098800 0.337600 0.616100 109 | v -1.101600 0.652300 -0.282100 110 | v -1.140600 0.652300 0.000000 111 | v -1.102100 0.652300 0.282100 112 | v -0.985600 0.652300 0.552600 113 | v -0.900500 0.922400 -0.230600 114 | v -0.932400 0.922400 0.000000 115 | v -0.900900 0.922400 0.230600 116 | v -0.805700 0.922400 0.451700 117 | v -0.636000 1.129900 -0.162900 118 | v -0.658500 1.129900 0.000000 119 | v -0.636300 1.129900 0.162900 120 | v -0.569000 1.129900 0.319000 121 | v -0.324400 1.260000 -0.083100 122 | v -0.335900 1.260000 0.000000 123 | v -0.324600 1.260000 0.083100 124 | v -0.290300 1.260000 0.162700 125 | v 0.000000 1.304700 0.000000 126 | v -0.319000 -1.129900 0.569000 127 | v -0.451700 -0.922400 0.805600 128 | v -0.552600 -0.652300 0.985600 129 | v -0.616100 -0.337600 1.098800 130 | v -0.638000 -0.000000 1.138000 131 | v -0.616100 0.337600 1.098800 132 | v -0.552600 0.652300 0.985600 133 | v -0.451700 0.922400 0.805700 134 | v -0.319000 1.129900 0.569000 135 | v -0.162700 1.260000 0.290300 136 | v -0.163100 -1.129900 0.632500 137 | v 0.000000 -1.129900 0.652300 138 | v -0.231000 -0.922400 0.895600 139 | v 0.000000 -0.922400 0.923600 140 | v -0.282600 -0.652300 1.095600 141 | v 0.000000 -0.652300 1.129900 142 | v -0.315100 -0.337600 1.221400 143 | v 0.000000 -0.337600 1.259700 144 | v -0.326300 -0.000000 1.265000 145 | v 0.000000 -0.000000 1.304700 146 | v -0.315100 0.337600 1.221400 147 | v 0.000000 0.337600 1.259700 148 | v -0.282600 0.652300 1.095600 149 | v 0.000000 0.652300 1.129900 150 | v -0.231000 0.922400 0.895600 151 | v 0.000000 0.922400 0.923600 152 | v -0.163100 1.129900 0.632500 153 | v 0.000000 1.129900 0.652300 154 | v -0.083200 1.260000 0.322700 155 | v 0.000000 1.260000 0.332800 156 | v 0.163100 -1.129900 0.632500 157 | v 0.000000 -1.304700 -0.000000 158 | v 0.319000 -1.129900 0.569000 159 | v 0.231000 -0.922400 0.895600 160 | v 0.451700 -0.922400 0.805600 161 | v 0.282600 -0.652300 1.095600 162 | v 0.552600 -0.652300 0.985600 163 | v 0.315100 -0.337600 1.221400 164 | v 0.616100 -0.337600 1.098800 165 | v 0.326300 -0.000000 1.265000 166 | v 0.638000 -0.000000 1.138000 167 | v 0.315100 0.337600 1.221400 168 | v 0.616100 0.337600 1.098800 169 | v 0.282600 0.652300 1.095600 170 | v 0.552600 0.652300 0.985600 171 | v 0.231000 0.922400 0.895600 172 | v 0.451700 0.922400 0.805700 173 | v 0.163100 1.129900 0.632500 174 | v 0.319000 1.129900 0.569000 175 | v 0.083200 1.260000 0.322700 176 | v 0.162700 1.260000 0.290300 177 | v 0.000000 1.304700 0.000000 178 | v 0.569000 -1.129900 0.319000 179 | v 0.805600 -0.922400 0.451700 180 | v 0.985600 -0.652300 0.552600 181 | v 1.098800 -0.337600 0.616100 182 | v 1.138000 -0.000000 0.638000 183 | v 1.098800 0.337600 0.616100 184 | v 0.985600 0.652300 0.552600 185 | v 0.805700 0.922400 0.451700 186 | v 0.569000 1.129900 0.319000 187 | v 0.290300 1.260000 0.162700 188 | v 0.636300 -1.129900 0.162900 189 | v 0.658500 -1.129900 -0.000000 190 | v 0.636000 -1.129900 -0.162900 191 | v 0.569000 -1.129900 -0.319000 192 | v 0.900900 -0.922400 0.230600 193 | v 0.932400 -0.922400 -0.000000 194 | v 0.900500 -0.922400 -0.230600 195 | v 0.805600 -0.922400 -0.451700 196 | v 1.102100 -0.652300 0.282100 197 | v 1.140600 -0.652300 -0.000000 198 | v 1.101600 -0.652300 -0.282100 199 | v 0.985600 -0.652300 -0.552600 200 | v 1.228700 -0.337600 0.314500 201 | v 1.271600 -0.337600 -0.000000 202 | v 1.228100 -0.337600 -0.314500 203 | v 1.098800 -0.337600 -0.616100 204 | v 1.272600 -0.000000 0.325800 205 | v 1.317000 0.000000 0.000000 206 | v 1.272000 0.000000 -0.325800 207 | v 1.138000 0.000000 -0.638000 208 | v 1.228700 0.337600 0.314500 209 | v 1.271600 0.337600 0.000000 210 | v 1.228100 0.337600 -0.314500 211 | v 1.098800 0.337600 -0.616100 212 | v 1.102100 0.652300 0.282100 213 | v 1.140600 0.652300 0.000000 214 | v 1.101600 0.652300 -0.282100 215 | v 0.985600 0.652300 -0.552600 216 | v 0.900900 0.922400 0.230600 217 | v 0.932400 0.922400 0.000000 218 | v 0.900500 0.922400 -0.230600 219 | v 0.805700 0.922400 -0.451700 220 | v 0.636300 1.129900 0.162900 221 | v 0.658500 1.129900 0.000000 222 | v 0.636000 1.129900 -0.162900 223 | v 0.569000 1.129900 -0.319000 224 | v 0.324600 1.260000 0.083100 225 | v 0.335900 1.260000 0.000000 226 | v 0.324400 1.260000 -0.083100 227 | v 0.290300 1.260000 -0.162700 228 | v 0.459900 -1.129900 -0.459800 229 | v 0.319000 -1.129900 -0.569000 230 | v 0.651200 -0.922400 -0.651000 231 | v 0.451700 -0.922400 -0.805600 232 | v 0.796600 -0.652300 -0.796400 233 | v 0.552600 -0.652300 -0.985600 234 | v 0.888100 -0.337600 -0.887900 235 | v 0.616100 -0.337600 -1.098800 236 | v 0.919800 0.000000 -0.919600 237 | v 0.638000 0.000000 -1.138000 238 | v 0.888100 0.337600 -0.887900 239 | v 0.616100 0.337600 -1.098800 240 | v 0.796600 0.652300 -0.796400 241 | v 0.552600 0.652300 -0.985600 242 | v 0.651200 0.922400 -0.651000 243 | v 0.451700 0.922400 -0.805700 244 | v 0.459900 1.129900 -0.459800 245 | v 0.319000 1.129900 -0.569000 246 | v 0.234600 1.260000 -0.234600 247 | v 0.200300 1.260000 -0.265000 248 | v 0.162700 1.260000 -0.290300 249 | v 0.159800 -1.129900 -0.632500 250 | v 0.226200 -0.922400 -0.895600 251 | v 0.276800 -0.652300 -1.095600 252 | v 0.308600 -0.337600 -1.221400 253 | v 0.078800 -1.129900 -0.647500 254 | vt 1.000000 0.541800 255 | vt 0.962500 0.500000 256 | vt 1.000000 0.500000 257 | vt 1.000000 0.625500 258 | vt 1.000000 0.667200 259 | vt 0.962500 0.666500 260 | vt 0.962500 0.583300 261 | vt 1.000000 0.583700 262 | vt 1.000000 0.708900 263 | vt 1.000000 0.750600 264 | vt 0.962500 0.749800 265 | vt 1.000000 0.792500 266 | vt 1.000000 0.834700 267 | vt 0.962500 0.834000 268 | vt 0.972200 0.918900 269 | vt 0.962500 0.918800 270 | vt 0.981700 0.919000 271 | vt 1.000000 0.919200 272 | vt 1.000000 0.877100 273 | vt 0.972200 1.000000 274 | vt 0.981700 1.000000 275 | vt 1.000000 0.960400 276 | vt 1.000000 1.000000 277 | vt 0.018300 0.165700 278 | vt 0.000000 0.165300 279 | vt 0.000000 0.122900 280 | vt 0.000000 0.080800 281 | vt 0.000000 0.039600 282 | vt 0.000000 0.000000 283 | vt 0.018300 0.000000 284 | vt 0.037500 0.166000 285 | vt 0.000000 0.207500 286 | vt 0.000000 0.249400 287 | vt 0.037500 0.250200 288 | vt 0.000000 0.291100 289 | vt 0.037500 0.333500 290 | vt 0.000000 0.332800 291 | vt 0.000000 0.374500 292 | vt 0.037500 0.416700 293 | vt 0.000000 0.416300 294 | vt 0.000000 0.458200 295 | vt 0.037500 0.500000 296 | vt 0.000000 0.500000 297 | vt 0.000000 0.541800 298 | vt 0.037500 0.583300 299 | vt 0.000000 0.583700 300 | vt 0.000000 0.625500 301 | vt 0.037500 0.666500 302 | vt 0.000000 0.667200 303 | vt 0.000000 0.708900 304 | vt 0.037500 0.749800 305 | vt 0.000000 0.750600 306 | vt 0.000000 0.792500 307 | vt 0.037500 0.834000 308 | vt 0.000000 0.834700 309 | vt 0.018300 0.919000 310 | vt 0.000000 0.919200 311 | vt 0.000000 0.877100 312 | vt 0.027800 0.918900 313 | vt 0.037500 0.918800 314 | vt 0.000000 0.960400 315 | vt 0.018300 1.000000 316 | vt 0.027800 1.000000 317 | vt 0.037500 1.000000 318 | vt 0.037500 0.000000 319 | vt 0.077800 0.000000 320 | vt 0.077800 0.167000 321 | vt 0.077800 0.251300 322 | vt 0.077800 0.334500 323 | vt 0.077800 0.417300 324 | vt 0.077800 0.500000 325 | vt 0.077800 0.582700 326 | vt 0.077800 0.665500 327 | vt 0.077800 0.748700 328 | vt 0.077800 0.833000 329 | vt 0.077800 0.918200 330 | vt 0.077800 1.000000 331 | vt 0.120400 0.168600 332 | vt 0.120400 0.000000 333 | vt 0.163700 0.170200 334 | vt 0.120400 0.253100 335 | vt 0.163700 0.254900 336 | vt 0.120400 0.336000 337 | vt 0.163700 0.337600 338 | vt 0.120400 0.418200 339 | vt 0.163700 0.419100 340 | vt 0.120400 0.500000 341 | vt 0.163700 0.500000 342 | vt 0.120400 0.581800 343 | vt 0.163700 0.580900 344 | vt 0.120400 0.664000 345 | vt 0.163700 0.662400 346 | vt 0.120400 0.746900 347 | vt 0.163700 0.745100 348 | vt 0.120400 0.831400 349 | vt 0.163700 0.829800 350 | vt 0.098900 0.917800 351 | vt 0.120400 0.917300 352 | vt 0.163700 0.916400 353 | vt 0.098900 1.000000 354 | vt 0.120400 1.000000 355 | vt 0.163700 1.000000 356 | vt 0.163700 0.000000 357 | vt 0.206400 0.171300 358 | vt 0.206400 0.000000 359 | vt 0.248600 0.171700 360 | vt 0.248600 0.000000 361 | vt 0.290900 0.171600 362 | vt 0.290900 0.000000 363 | vt 0.333800 0.170900 364 | vt 0.206400 0.256200 365 | vt 0.248600 0.256700 366 | vt 0.290900 0.256500 367 | vt 0.333800 0.255800 368 | vt 0.206400 0.338700 369 | vt 0.248600 0.339100 370 | vt 0.290900 0.339000 371 | vt 0.333800 0.338400 372 | vt 0.206400 0.419700 373 | vt 0.248600 0.420000 374 | vt 0.290900 0.419900 375 | vt 0.333800 0.419500 376 | vt 0.206400 0.500000 377 | vt 0.248600 0.500000 378 | vt 0.290900 0.500000 379 | vt 0.333800 0.500000 380 | vt 0.206400 0.580300 381 | vt 0.248600 0.580000 382 | vt 0.290900 0.580100 383 | vt 0.333800 0.580500 384 | vt 0.206400 0.661300 385 | vt 0.248600 0.660900 386 | vt 0.290900 0.661000 387 | vt 0.333800 0.661600 388 | vt 0.206400 0.743800 389 | vt 0.248600 0.743300 390 | vt 0.290900 0.743500 391 | vt 0.333800 0.744200 392 | vt 0.206400 0.828700 393 | vt 0.248600 0.828300 394 | vt 0.290900 0.828400 395 | vt 0.333800 0.829100 396 | vt 0.206400 0.915800 397 | vt 0.248600 0.915500 398 | vt 0.290900 0.915600 399 | vt 0.333800 0.916000 400 | vt 0.206400 1.000000 401 | vt 0.248600 1.000000 402 | vt 0.290900 1.000000 403 | vt 0.333800 1.000000 404 | vt 0.333800 0.000000 405 | vt 0.420200 0.168800 406 | vt 0.420200 0.253300 407 | vt 0.420200 0.336200 408 | vt 0.420200 0.418300 409 | vt 0.420200 0.500000 410 | vt 0.420200 0.581700 411 | vt 0.420200 0.663800 412 | vt 0.420200 0.746700 413 | vt 0.420200 0.831200 414 | vt 0.420200 0.917200 415 | vt 0.420200 1.000000 416 | vt 0.420200 0.000000 417 | vt 0.460800 0.168200 418 | vt 0.460800 0.000000 419 | vt 0.500000 0.168000 420 | vt 0.460800 0.252600 421 | vt 0.500000 0.252400 422 | vt 0.460800 0.335600 423 | vt 0.500000 0.335400 424 | vt 0.460800 0.417900 425 | vt 0.500000 0.417800 426 | vt 0.460800 0.500000 427 | vt 0.500000 0.500000 428 | vt 0.460800 0.582100 429 | vt 0.500000 0.582200 430 | vt 0.460800 0.664400 431 | vt 0.500000 0.664600 432 | vt 0.460800 0.747400 433 | vt 0.500000 0.747600 434 | vt 0.460800 0.831800 435 | vt 0.500000 0.832000 436 | vt 0.460800 0.917600 437 | vt 0.500000 0.917700 438 | vt 0.460800 1.000000 439 | vt 0.500000 1.000000 440 | vt 0.500000 0.000000 441 | vt 0.539200 0.168200 442 | vt 0.539200 0.000000 443 | vt 0.579800 0.168800 444 | vt 0.539200 0.252600 445 | vt 0.579800 0.253300 446 | vt 0.539200 0.335600 447 | vt 0.579800 0.336200 448 | vt 0.539200 0.417900 449 | vt 0.579800 0.418300 450 | vt 0.539200 0.500000 451 | vt 0.579800 0.500000 452 | vt 0.539200 0.582100 453 | vt 0.579800 0.581700 454 | vt 0.539200 0.664400 455 | vt 0.579800 0.663800 456 | vt 0.539200 0.747400 457 | vt 0.579800 0.746700 458 | vt 0.539200 0.831800 459 | vt 0.579800 0.831200 460 | vt 0.539200 0.917600 461 | vt 0.579800 0.917200 462 | vt 0.539200 1.000000 463 | vt 0.579800 1.000000 464 | vt 0.579800 0.000000 465 | vt 0.666200 0.170900 466 | vt 0.666200 0.255800 467 | vt 0.666200 0.338400 468 | vt 0.666200 0.419500 469 | vt 0.666200 0.500000 470 | vt 0.666200 0.580500 471 | vt 0.666200 0.661600 472 | vt 0.666200 0.744200 473 | vt 0.666200 0.829100 474 | vt 0.666200 0.916000 475 | vt 0.666200 1.000000 476 | vt 0.666200 0.000000 477 | vt 0.709100 0.171600 478 | vt 0.709100 0.000000 479 | vt 0.751400 0.171700 480 | vt 0.751400 0.000000 481 | vt 0.793600 0.171300 482 | vt 0.793600 0.000000 483 | vt 0.836300 0.170200 484 | vt 0.709100 0.256500 485 | vt 0.751400 0.256700 486 | vt 0.793600 0.256200 487 | vt 0.836300 0.254900 488 | vt 0.709100 0.339000 489 | vt 0.751400 0.339100 490 | vt 0.793600 0.338700 491 | vt 0.836300 0.337600 492 | vt 0.709100 0.419900 493 | vt 0.751400 0.420000 494 | vt 0.793600 0.419700 495 | vt 0.836300 0.419100 496 | vt 0.709100 0.500000 497 | vt 0.751400 0.500000 498 | vt 0.793600 0.500000 499 | vt 0.836300 0.500000 500 | vt 0.709100 0.580100 501 | vt 0.751400 0.580000 502 | vt 0.793600 0.580300 503 | vt 0.836300 0.580900 504 | vt 0.709100 0.661000 505 | vt 0.751400 0.660900 506 | vt 0.793600 0.661300 507 | vt 0.836300 0.662400 508 | vt 0.709100 0.743500 509 | vt 0.751400 0.743300 510 | vt 0.793600 0.743800 511 | vt 0.836300 0.745100 512 | vt 0.709100 0.828400 513 | vt 0.751400 0.828300 514 | vt 0.793600 0.828700 515 | vt 0.836300 0.829800 516 | vt 0.709100 0.915600 517 | vt 0.751400 0.915500 518 | vt 0.793600 0.915800 519 | vt 0.836300 0.916400 520 | vt 0.709100 1.000000 521 | vt 0.751400 1.000000 522 | vt 0.793600 1.000000 523 | vt 0.836300 1.000000 524 | vt 0.836300 0.000000 525 | vt 0.879600 0.168600 526 | vt 0.879600 0.000000 527 | vt 0.922200 0.167000 528 | vt 0.879600 0.253100 529 | vt 0.922200 0.251300 530 | vt 0.879600 0.336000 531 | vt 0.922200 0.334500 532 | vt 0.879600 0.418200 533 | vt 0.922200 0.417300 534 | vt 0.879600 0.500000 535 | vt 0.922200 0.500000 536 | vt 0.879600 0.581800 537 | vt 0.922200 0.582700 538 | vt 0.879600 0.664000 539 | vt 0.922200 0.665500 540 | vt 0.879600 0.746900 541 | vt 0.922200 0.748700 542 | vt 0.879600 0.831400 543 | vt 0.922200 0.833000 544 | vt 0.879600 0.917300 545 | vt 0.901100 0.917800 546 | vt 0.922200 0.918200 547 | vt 0.879600 1.000000 548 | vt 0.901100 1.000000 549 | vt 0.922200 1.000000 550 | vt 0.922200 0.000000 551 | vt 0.962500 0.000000 552 | vt 0.962500 0.166000 553 | vt 0.962500 0.250200 554 | vt 0.962500 0.333500 555 | vt 0.962500 0.416700 556 | vt 0.962500 1.000000 557 | vt 0.981700 0.165700 558 | vt 1.000000 0.165300 559 | vt 0.981700 0.000000 560 | vt 1.000000 0.122900 561 | vt 1.000000 0.080800 562 | vt 1.000000 0.039600 563 | vt 1.000000 0.000000 564 | vt 1.000000 0.249400 565 | vt 1.000000 0.207500 566 | vt 1.000000 0.291100 567 | vt 1.000000 0.332800 568 | vt 1.000000 0.374500 569 | vt 1.000000 0.416300 570 | vt 1.000000 0.458200 571 | usemtl wire_148177026 572 | s 1 573 | f 1/1 2/2 3/3 574 | f 4/4 5/5 6/6 575 | f 4/4 6/6 7/7 576 | f 4/4 7/7 8/8 577 | f 9/9 10/10 11/11 578 | f 9/9 11/11 6/6 579 | f 9/9 6/6 5/5 580 | f 12/12 13/13 14/14 581 | f 12/12 14/14 11/11 582 | f 12/12 11/11 10/10 583 | f 15/15 16/16 14/14 584 | f 17/17 15/15 14/14 585 | f 18/18 17/17 14/14 586 | f 19/19 18/18 14/14 587 | f 13/13 19/19 14/14 588 | f 16/16 15/15 20/20 589 | f 15/15 17/17 20/21 590 | f 21/22 22/23 20/21 591 | f 21/22 20/21 17/17 592 | f 21/22 17/17 18/18 593 | f 23/24 24/25 25/26 594 | f 23/24 25/26 26/27 595 | f 23/24 26/27 27/28 596 | f 23/24 27/28 28/29 597 | f 28/30 29/31 23/24 598 | f 23/24 30/32 24/25 599 | f 23/24 31/33 30/32 600 | f 32/34 31/33 23/24 601 | f 29/31 32/34 23/24 602 | f 33/35 31/33 32/34 603 | f 33/35 32/34 34/36 604 | f 33/35 34/36 35/37 605 | f 36/38 35/37 34/36 606 | f 36/38 34/36 37/39 607 | f 36/38 37/39 38/40 608 | f 39/41 38/40 37/39 609 | f 39/41 37/39 40/42 610 | f 39/41 40/42 3/43 611 | f 1/44 3/43 40/42 612 | f 1/44 40/42 41/45 613 | f 1/44 41/45 8/46 614 | f 4/47 8/46 41/45 615 | f 4/47 41/45 42/48 616 | f 4/47 42/48 5/49 617 | f 9/50 5/49 42/48 618 | f 9/50 42/48 43/51 619 | f 9/50 43/51 10/52 620 | f 12/53 10/52 43/51 621 | f 12/53 43/51 44/54 622 | f 12/53 44/54 13/55 623 | f 45/56 18/57 19/58 624 | f 45/56 19/58 13/55 625 | f 46/59 45/56 13/55 626 | f 47/60 46/59 13/55 627 | f 44/54 47/60 13/55 628 | f 21/61 18/57 45/56 629 | f 21/61 45/56 22/62 630 | f 45/56 46/59 22/63 631 | f 46/59 47/60 22/64 632 | f 28/65 48/66 49/67 633 | f 28/65 49/67 29/31 634 | f 29/31 49/67 50/68 635 | f 29/31 50/68 32/34 636 | f 32/34 50/68 51/69 637 | f 32/34 51/69 34/36 638 | f 34/36 51/69 52/70 639 | f 34/36 52/70 37/39 640 | f 37/39 52/70 53/71 641 | f 37/39 53/71 40/42 642 | f 40/42 53/71 54/72 643 | f 40/42 54/72 41/45 644 | f 41/45 54/72 55/73 645 | f 41/45 55/73 42/48 646 | f 42/48 55/73 56/74 647 | f 42/48 56/74 43/51 648 | f 43/51 56/74 57/75 649 | f 43/51 57/75 44/54 650 | f 44/54 57/75 58/76 651 | f 44/54 58/76 47/60 652 | f 47/60 58/76 20/77 653 | f 47/60 20/77 22/64 654 | f 48/66 59/78 49/67 655 | f 48/79 60/80 59/78 656 | f 49/67 59/78 61/81 657 | f 49/67 61/81 50/68 658 | f 59/78 60/80 62/82 659 | f 59/78 62/82 61/81 660 | f 50/68 61/81 63/83 661 | f 50/68 63/83 51/69 662 | f 61/81 62/82 64/84 663 | f 61/81 64/84 63/83 664 | f 51/69 63/83 65/85 665 | f 51/69 65/85 52/70 666 | f 63/83 64/84 66/86 667 | f 63/83 66/86 65/85 668 | f 52/70 65/85 67/87 669 | f 52/70 67/87 53/71 670 | f 65/85 66/86 68/88 671 | f 65/85 68/88 67/87 672 | f 53/71 67/87 69/89 673 | f 53/71 69/89 54/72 674 | f 67/87 68/88 70/90 675 | f 67/87 70/90 69/89 676 | f 54/72 69/89 71/91 677 | f 54/72 71/91 55/73 678 | f 69/89 70/90 72/92 679 | f 69/89 72/92 71/91 680 | f 55/73 71/91 73/93 681 | f 55/73 73/93 56/74 682 | f 71/91 72/92 74/94 683 | f 71/91 74/94 73/93 684 | f 56/74 73/93 75/95 685 | f 56/74 75/95 57/75 686 | f 73/93 74/94 76/96 687 | f 73/93 76/96 75/95 688 | f 77/97 58/76 57/75 689 | f 77/97 57/75 75/95 690 | f 77/97 75/95 78/98 691 | f 75/95 76/96 79/99 692 | f 75/95 79/99 78/98 693 | f 58/76 77/97 20/100 694 | f 77/97 78/98 20/101 695 | f 78/98 79/99 20/102 696 | f 48/103 80/104 60/80 697 | f 48/105 81/106 80/104 698 | f 48/107 82/108 81/106 699 | f 83/109 84/110 82/108 700 | f 60/80 80/104 85/111 701 | f 60/80 85/111 62/82 702 | f 80/104 81/106 86/112 703 | f 80/104 86/112 85/111 704 | f 81/106 82/108 87/113 705 | f 81/106 87/113 86/112 706 | f 82/108 84/110 88/114 707 | f 82/108 88/114 87/113 708 | f 62/82 85/111 89/115 709 | f 62/82 89/115 64/84 710 | f 85/111 86/112 90/116 711 | f 85/111 90/116 89/115 712 | f 86/112 87/113 91/117 713 | f 86/112 91/117 90/116 714 | f 87/113 88/114 92/118 715 | f 87/113 92/118 91/117 716 | f 64/84 89/115 93/119 717 | f 64/84 93/119 66/86 718 | f 89/115 90/116 94/120 719 | f 89/115 94/120 93/119 720 | f 90/116 91/117 95/121 721 | f 90/116 95/121 94/120 722 | f 91/117 92/118 96/122 723 | f 91/117 96/122 95/121 724 | f 66/86 93/119 97/123 725 | f 66/86 97/123 68/88 726 | f 93/119 94/120 98/124 727 | f 93/119 98/124 97/123 728 | f 94/120 95/121 99/125 729 | f 94/120 99/125 98/124 730 | f 95/121 96/122 100/126 731 | f 95/121 100/126 99/125 732 | f 68/88 97/123 101/127 733 | f 68/88 101/127 70/90 734 | f 97/123 98/124 102/128 735 | f 97/123 102/128 101/127 736 | f 98/124 99/125 103/129 737 | f 98/124 103/129 102/128 738 | f 99/125 100/126 104/130 739 | f 99/125 104/130 103/129 740 | f 70/90 101/127 105/131 741 | f 70/90 105/131 72/92 742 | f 101/127 102/128 106/132 743 | f 101/127 106/132 105/131 744 | f 102/128 103/129 107/133 745 | f 102/128 107/133 106/132 746 | f 103/129 104/130 108/134 747 | f 103/129 108/134 107/133 748 | f 72/92 105/131 109/135 749 | f 72/92 109/135 74/94 750 | f 105/131 106/132 110/136 751 | f 105/131 110/136 109/135 752 | f 106/132 107/133 111/137 753 | f 106/132 111/137 110/136 754 | f 107/133 108/134 112/138 755 | f 107/133 112/138 111/137 756 | f 74/94 109/135 113/139 757 | f 74/94 113/139 76/96 758 | f 109/135 110/136 114/140 759 | f 109/135 114/140 113/139 760 | f 110/136 111/137 115/141 761 | f 110/136 115/141 114/140 762 | f 111/137 112/138 116/142 763 | f 111/137 116/142 115/141 764 | f 76/96 113/139 117/143 765 | f 76/96 117/143 79/99 766 | f 113/139 114/140 118/144 767 | f 113/139 118/144 117/143 768 | f 114/140 115/141 119/145 769 | f 114/140 119/145 118/144 770 | f 115/141 116/142 120/146 771 | f 115/141 120/146 119/145 772 | f 79/99 117/143 20/147 773 | f 117/143 118/144 20/148 774 | f 118/144 119/145 121/149 775 | f 119/145 120/146 121/150 776 | f 83/151 122/152 84/110 777 | f 84/110 122/152 123/153 778 | f 84/110 123/153 88/114 779 | f 88/114 123/153 124/154 780 | f 88/114 124/154 92/118 781 | f 92/118 124/154 125/155 782 | f 92/118 125/155 96/122 783 | f 96/122 125/155 126/156 784 | f 96/122 126/156 100/126 785 | f 100/126 126/156 127/157 786 | f 100/126 127/157 104/130 787 | f 104/130 127/157 128/158 788 | f 104/130 128/158 108/134 789 | f 108/134 128/158 129/159 790 | f 108/134 129/159 112/138 791 | f 112/138 129/159 130/160 792 | f 112/138 130/160 116/142 793 | f 116/142 130/160 131/161 794 | f 116/142 131/161 120/146 795 | f 120/146 131/161 121/162 796 | f 83/163 132/164 122/152 797 | f 83/165 133/166 132/164 798 | f 122/152 132/164 134/167 799 | f 122/152 134/167 123/153 800 | f 132/164 133/166 135/168 801 | f 132/164 135/168 134/167 802 | f 123/153 134/167 136/169 803 | f 123/153 136/169 124/154 804 | f 134/167 135/168 137/170 805 | f 134/167 137/170 136/169 806 | f 124/154 136/169 138/171 807 | f 124/154 138/171 125/155 808 | f 136/169 137/170 139/172 809 | f 136/169 139/172 138/171 810 | f 125/155 138/171 140/173 811 | f 125/155 140/173 126/156 812 | f 138/171 139/172 141/174 813 | f 138/171 141/174 140/173 814 | f 126/156 140/173 142/175 815 | f 126/156 142/175 127/157 816 | f 140/173 141/174 143/176 817 | f 140/173 143/176 142/175 818 | f 127/157 142/175 144/177 819 | f 127/157 144/177 128/158 820 | f 142/175 143/176 145/178 821 | f 142/175 145/178 144/177 822 | f 128/158 144/177 146/179 823 | f 128/158 146/179 129/159 824 | f 144/177 145/178 147/180 825 | f 144/177 147/180 146/179 826 | f 129/159 146/179 148/181 827 | f 129/159 148/181 130/160 828 | f 146/179 147/180 149/182 829 | f 146/179 149/182 148/181 830 | f 130/160 148/181 150/183 831 | f 130/160 150/183 131/161 832 | f 148/181 149/182 151/184 833 | f 148/181 151/184 150/183 834 | f 131/161 150/183 121/185 835 | f 150/183 151/184 121/186 836 | f 83/187 152/188 133/166 837 | f 153/189 154/190 152/188 838 | f 133/166 152/188 155/191 839 | f 133/166 155/191 135/168 840 | f 152/188 154/190 156/192 841 | f 152/188 156/192 155/191 842 | f 135/168 155/191 157/193 843 | f 135/168 157/193 137/170 844 | f 155/191 156/192 158/194 845 | f 155/191 158/194 157/193 846 | f 137/170 157/193 159/195 847 | f 137/170 159/195 139/172 848 | f 157/193 158/194 160/196 849 | f 157/193 160/196 159/195 850 | f 139/172 159/195 161/197 851 | f 139/172 161/197 141/174 852 | f 159/195 160/196 162/198 853 | f 159/195 162/198 161/197 854 | f 141/174 161/197 163/199 855 | f 141/174 163/199 143/176 856 | f 161/197 162/198 164/200 857 | f 161/197 164/200 163/199 858 | f 143/176 163/199 165/201 859 | f 143/176 165/201 145/178 860 | f 163/199 164/200 166/202 861 | f 163/199 166/202 165/201 862 | f 145/178 165/201 167/203 863 | f 145/178 167/203 147/180 864 | f 165/201 166/202 168/204 865 | f 165/201 168/204 167/203 866 | f 147/180 167/203 169/205 867 | f 147/180 169/205 149/182 868 | f 167/203 168/204 170/206 869 | f 167/203 170/206 169/205 870 | f 149/182 169/205 171/207 871 | f 149/182 171/207 151/184 872 | f 169/205 170/206 172/208 873 | f 169/205 172/208 171/207 874 | f 151/184 171/207 173/209 875 | f 171/207 172/208 173/210 876 | f 153/211 174/212 154/190 877 | f 154/190 174/212 175/213 878 | f 154/190 175/213 156/192 879 | f 156/192 175/213 176/214 880 | f 156/192 176/214 158/194 881 | f 158/194 176/214 177/215 882 | f 158/194 177/215 160/196 883 | f 160/196 177/215 178/216 884 | f 160/196 178/216 162/198 885 | f 162/198 178/216 179/217 886 | f 162/198 179/217 164/200 887 | f 164/200 179/217 180/218 888 | f 164/200 180/218 166/202 889 | f 166/202 180/218 181/219 890 | f 166/202 181/219 168/204 891 | f 168/204 181/219 182/220 892 | f 168/204 182/220 170/206 893 | f 170/206 182/220 183/221 894 | f 170/206 183/221 172/208 895 | f 172/208 183/221 173/222 896 | f 153/223 184/224 174/212 897 | f 153/225 185/226 184/224 898 | f 153/227 186/228 185/226 899 | f 28/229 187/230 186/228 900 | f 174/212 184/224 188/231 901 | f 174/212 188/231 175/213 902 | f 184/224 185/226 189/232 903 | f 184/224 189/232 188/231 904 | f 185/226 186/228 190/233 905 | f 185/226 190/233 189/232 906 | f 186/228 187/230 191/234 907 | f 186/228 191/234 190/233 908 | f 175/213 188/231 192/235 909 | f 175/213 192/235 176/214 910 | f 188/231 189/232 193/236 911 | f 188/231 193/236 192/235 912 | f 189/232 190/233 194/237 913 | f 189/232 194/237 193/236 914 | f 190/233 191/234 195/238 915 | f 190/233 195/238 194/237 916 | f 176/214 192/235 196/239 917 | f 176/214 196/239 177/215 918 | f 192/235 193/236 197/240 919 | f 192/235 197/240 196/239 920 | f 193/236 194/237 198/241 921 | f 193/236 198/241 197/240 922 | f 194/237 195/238 199/242 923 | f 194/237 199/242 198/241 924 | f 177/215 196/239 200/243 925 | f 177/215 200/243 178/216 926 | f 196/239 197/240 201/244 927 | f 196/239 201/244 200/243 928 | f 197/240 198/241 202/245 929 | f 197/240 202/245 201/244 930 | f 198/241 199/242 203/246 931 | f 198/241 203/246 202/245 932 | f 178/216 200/243 204/247 933 | f 178/216 204/247 179/217 934 | f 200/243 201/244 205/248 935 | f 200/243 205/248 204/247 936 | f 201/244 202/245 206/249 937 | f 201/244 206/249 205/248 938 | f 202/245 203/246 207/250 939 | f 202/245 207/250 206/249 940 | f 179/217 204/247 208/251 941 | f 179/217 208/251 180/218 942 | f 204/247 205/248 209/252 943 | f 204/247 209/252 208/251 944 | f 205/248 206/249 210/253 945 | f 205/248 210/253 209/252 946 | f 206/249 207/250 211/254 947 | f 206/249 211/254 210/253 948 | f 180/218 208/251 212/255 949 | f 180/218 212/255 181/219 950 | f 208/251 209/252 213/256 951 | f 208/251 213/256 212/255 952 | f 209/252 210/253 214/257 953 | f 209/252 214/257 213/256 954 | f 210/253 211/254 215/258 955 | f 210/253 215/258 214/257 956 | f 181/219 212/255 216/259 957 | f 181/219 216/259 182/220 958 | f 212/255 213/256 217/260 959 | f 212/255 217/260 216/259 960 | f 213/256 214/257 218/261 961 | f 213/256 218/261 217/260 962 | f 214/257 215/258 219/262 963 | f 214/257 219/262 218/261 964 | f 182/220 216/259 220/263 965 | f 182/220 220/263 183/221 966 | f 216/259 217/260 221/264 967 | f 216/259 221/264 220/263 968 | f 217/260 218/261 222/265 969 | f 217/260 222/265 221/264 970 | f 218/261 219/262 223/266 971 | f 218/261 223/266 222/265 972 | f 183/221 220/263 173/267 973 | f 220/263 221/264 173/268 974 | f 221/264 222/265 22/269 975 | f 222/265 223/266 22/270 976 | f 28/271 224/272 187/230 977 | f 28/273 225/274 224/272 978 | f 187/230 224/272 226/275 979 | f 187/230 226/275 191/234 980 | f 224/272 225/274 227/276 981 | f 224/272 227/276 226/275 982 | f 191/234 226/275 228/277 983 | f 191/234 228/277 195/238 984 | f 226/275 227/276 229/278 985 | f 226/275 229/278 228/277 986 | f 195/238 228/277 230/279 987 | f 195/238 230/279 199/242 988 | f 228/277 229/278 231/280 989 | f 228/277 231/280 230/279 990 | f 199/242 230/279 232/281 991 | f 199/242 232/281 203/246 992 | f 230/279 231/280 233/282 993 | f 230/279 233/282 232/281 994 | f 203/246 232/281 234/283 995 | f 203/246 234/283 207/250 996 | f 232/281 233/282 235/284 997 | f 232/281 235/284 234/283 998 | f 207/250 234/283 236/285 999 | f 207/250 236/285 211/254 1000 | f 234/283 235/284 237/286 1001 | f 234/283 237/286 236/285 1002 | f 211/254 236/285 238/287 1003 | f 211/254 238/287 215/258 1004 | f 236/285 237/286 239/288 1005 | f 236/285 239/288 238/287 1006 | f 215/258 238/287 240/289 1007 | f 215/258 240/289 219/262 1008 | f 238/287 239/288 241/290 1009 | f 238/287 241/290 240/289 1010 | f 219/262 240/289 242/291 1011 | f 219/262 242/291 223/266 1012 | f 243/292 242/291 240/289 1013 | f 243/292 240/289 241/290 1014 | f 243/292 241/290 244/293 1015 | f 223/266 242/291 22/294 1016 | f 242/291 243/292 22/295 1017 | f 243/292 244/293 22/296 1018 | f 28/297 48/298 245/299 1019 | f 28/297 245/299 225/274 1020 | f 225/274 245/299 246/300 1021 | f 225/274 246/300 227/276 1022 | f 227/276 246/300 247/301 1023 | f 227/276 247/301 229/278 1024 | f 229/278 247/301 248/302 1025 | f 229/278 248/302 231/280 1026 | f 231/280 248/302 2/2 1027 | f 231/280 2/2 233/282 1028 | f 233/282 2/2 7/7 1029 | f 233/282 7/7 235/284 1030 | f 235/284 7/7 6/6 1031 | f 235/284 6/6 237/286 1032 | f 237/286 6/6 11/11 1033 | f 237/286 11/11 239/288 1034 | f 239/288 11/11 14/14 1035 | f 239/288 14/14 241/290 1036 | f 241/290 14/14 16/16 1037 | f 241/290 16/16 244/293 1038 | f 244/293 16/16 20/303 1039 | f 244/293 20/303 22/296 1040 | f 48/298 249/304 245/299 1041 | f 24/305 249/304 48/306 1042 | f 25/307 24/305 48/306 1043 | f 26/308 25/307 48/306 1044 | f 27/309 26/308 48/306 1045 | f 28/310 27/309 48/306 1046 | f 249/304 246/300 245/299 1047 | f 31/311 246/300 249/304 1048 | f 30/312 31/311 249/304 1049 | f 24/305 30/312 249/304 1050 | f 33/313 35/314 247/301 1051 | f 33/313 247/301 246/300 1052 | f 33/313 246/300 31/311 1053 | f 36/315 38/316 248/302 1054 | f 36/315 248/302 247/301 1055 | f 36/315 247/301 35/314 1056 | f 39/317 3/3 2/2 1057 | f 39/317 2/2 248/302 1058 | f 39/317 248/302 38/316 1059 | f 1/1 8/8 7/7 1060 | f 1/1 7/7 2/2 1061 | o Cylinder 1062 | v 1.062100 -0.000000 1.778400 1063 | v 0.973000 -0.000000 1.794900 1064 | v 0.973000 0.773500 1.794900 1065 | v 1.148800 0.773500 1.773100 1066 | v 1.148800 -0.000000 1.773100 1067 | v 0.973000 1.547000 1.794900 1068 | v 1.148800 1.547000 1.773100 1069 | v 1.062100 2.320500 1.778400 1070 | v 1.148800 2.320500 1.773100 1071 | v 0.973000 2.320500 1.794900 1072 | v 0.884000 -0.000000 1.823400 1073 | v 0.797800 -0.000000 1.864700 1074 | v 0.797800 0.773500 1.864700 1075 | v 0.797800 1.547000 1.864700 1076 | v 0.884000 2.320500 1.823400 1077 | v 0.797800 2.320500 1.864700 1078 | v 0.716700 -0.000000 1.919200 1079 | v 0.642800 -0.000000 1.984900 1080 | v 0.642800 0.773500 1.984900 1081 | v 0.577500 -0.000000 2.059200 1082 | v 0.522700 -0.000000 2.139800 1083 | v 0.522700 0.773500 2.139800 1084 | v 0.642800 1.547000 1.984900 1085 | v 0.522700 1.547000 2.139800 1086 | v 0.716700 2.320500 1.919200 1087 | v 0.642800 2.320500 1.984900 1088 | v 0.577500 2.320500 2.059201 1089 | v 0.522700 2.320500 2.139801 1090 | v 0.479800 -0.000000 2.224300 1091 | v 0.449100 -0.000000 2.311500 1092 | v 0.449100 0.773500 2.311500 1093 | v 0.430500 -0.000000 2.400700 1094 | v 0.424300 -0.000000 2.490700 1095 | v 0.424300 0.773500 2.490700 1096 | v 0.430300 -0.000000 2.580800 1097 | v 0.448700 -0.000000 2.669900 1098 | v 0.448700 0.773500 2.669900 1099 | v 0.479500 -0.000000 2.757200 1100 | v 0.522700 -0.000000 2.841700 1101 | v 0.522700 0.773500 2.841700 1102 | v 0.449100 1.547000 2.311500 1103 | v 0.424300 1.547000 2.490700 1104 | v 0.448700 1.547000 2.669900 1105 | v 0.522700 1.547000 2.841700 1106 | v 0.479800 2.320499 2.224300 1107 | v 0.449100 2.320499 2.311501 1108 | v 0.430500 2.320499 2.400701 1109 | v 0.424300 2.320499 2.490700 1110 | v 0.430300 2.320499 2.580801 1111 | v 0.448700 2.320499 2.669900 1112 | v 0.479500 2.320499 2.757200 1113 | v 0.522700 2.320499 2.841701 1114 | v 0.578100 -0.000000 2.922300 1115 | v 0.643800 -0.000000 2.996600 1116 | v 0.717700 -0.000000 3.062300 1117 | v 0.797800 0.773499 3.116700 1118 | v 0.797800 -0.000001 3.116700 1119 | v 0.797800 1.547000 3.116700 1120 | v 0.578100 2.320499 2.922301 1121 | v 0.643800 2.320499 2.996600 1122 | v 0.717700 2.320499 3.062300 1123 | v 0.797800 2.320499 3.116700 1124 | v 0.882000 -0.000001 3.158100 1125 | v 0.969300 -0.000001 3.186600 1126 | v 0.969300 0.773499 3.186600 1127 | v 1.058500 -0.000001 3.203100 1128 | v 1.148800 -0.000001 3.208400 1129 | v 1.148800 0.773499 3.208400 1130 | v 0.969300 1.547000 3.186600 1131 | v 1.148800 1.547000 3.208400 1132 | v 0.882000 2.320499 3.158100 1133 | v 0.969300 2.320499 3.186600 1134 | v 1.058500 2.320499 3.203100 1135 | v 1.148800 2.320499 3.208400 1136 | v 1.239000 -0.000001 3.203100 1137 | v 1.328200 -0.000001 3.186600 1138 | v 1.328200 0.773499 3.186600 1139 | v 1.415500 -0.000001 3.158100 1140 | v 1.499700 -0.000001 3.116700 1141 | v 1.499700 0.773499 3.116700 1142 | v 1.328200 1.547000 3.186600 1143 | v 1.499700 1.547000 3.116700 1144 | v 1.239000 2.320499 3.203100 1145 | v 1.328200 2.320499 3.186600 1146 | v 1.415500 2.320499 3.158100 1147 | v 1.499700 2.320499 3.116700 1148 | v 1.579800 -0.000000 3.062300 1149 | v 1.653700 -0.000000 2.996600 1150 | v 1.719400 -0.000000 2.922300 1151 | v 1.774800 0.773500 2.841700 1152 | v 1.774800 -0.000000 2.841700 1153 | v 1.774800 1.547000 2.841700 1154 | v 1.579800 2.320499 3.062300 1155 | v 1.653700 2.320499 2.996600 1156 | v 1.719400 2.320499 2.922301 1157 | v 1.774800 2.320499 2.841701 1158 | v 1.818000 -0.000000 2.757200 1159 | v 1.848800 -0.000000 2.669900 1160 | v 1.848800 0.773500 2.669900 1161 | v 1.867200 -0.000000 2.580800 1162 | v 1.873200 -0.000000 2.490700 1163 | v 1.873200 0.773500 2.490700 1164 | v 1.867000 -0.000000 2.400700 1165 | v 1.848400 -0.000000 2.311500 1166 | v 1.848400 0.773500 2.311500 1167 | v 1.817700 -0.000000 2.224300 1168 | v 1.774800 -0.000000 2.139800 1169 | v 1.774800 0.773500 2.139800 1170 | v 1.848800 1.547000 2.669900 1171 | v 1.873200 1.547000 2.490700 1172 | v 1.848400 1.547000 2.311500 1173 | v 1.774800 1.547000 2.139800 1174 | v 1.818000 2.320499 2.757200 1175 | v 1.848800 2.320499 2.669900 1176 | v 1.867200 2.320499 2.580801 1177 | v 1.873200 2.320499 2.490700 1178 | v 1.867000 2.320499 2.400701 1179 | v 1.848400 2.320499 2.311501 1180 | v 1.817700 2.320499 2.224300 1181 | v 1.774800 2.320500 2.139801 1182 | v 1.720000 -0.000000 2.059200 1183 | v 1.654700 -0.000000 1.984900 1184 | v 1.654700 0.773500 1.984900 1185 | v 1.580800 -0.000000 1.919200 1186 | v 1.499700 -0.000000 1.864700 1187 | v 1.499700 0.773500 1.864700 1188 | v 1.654700 1.547000 1.984900 1189 | v 1.499700 1.547000 1.864700 1190 | v 1.720000 2.320500 2.059201 1191 | v 1.654700 2.320500 1.984900 1192 | v 1.580800 2.320500 1.919200 1193 | v 1.499700 2.320500 1.864700 1194 | v 1.413500 -0.000000 1.823400 1195 | v 1.324500 -0.000000 1.794900 1196 | v 1.324500 0.773500 1.794900 1197 | v 1.324500 1.547000 1.794900 1198 | v 1.413500 2.320500 1.823400 1199 | v 1.324500 2.320500 1.794900 1200 | v 1.235400 -0.000000 1.778400 1201 | v 1.235400 2.320500 1.778400 1202 | v 1.834900 -0.000000 2.713900 1203 | v 1.871800 -0.000000 2.504500 1204 | v 1.859500 -0.000000 2.625500 1205 | v 1.797900 -0.000000 2.799900 1206 | v 1.540400 -0.000001 3.091100 1207 | v 1.458000 -0.000001 3.139100 1208 | v 1.372200 -0.000001 3.173900 1209 | v 1.148800 -0.000000 2.504500 1210 | v 1.148800 -0.000001 3.203100 1211 | v 1.720000 -0.000000 2.059200 1212 | v 1.654700 -0.000000 1.984900 1213 | v 1.580800 -0.000000 1.919200 1214 | v 1.457100 -0.000000 1.842400 1215 | v 1.369200 -0.000000 1.807600 1216 | v 1.279800 -0.000000 1.785200 1217 | v 1.148800 -0.000000 1.773100 1218 | v 0.839500 -0.000001 3.139100 1219 | v 0.499600 -0.000000 2.799900 1220 | v 0.462600 -0.000000 2.713900 1221 | v 0.438000 -0.000000 2.625500 1222 | v 0.426900 -0.000000 2.504500 1223 | v 0.425800 -0.000000 2.535800 1224 | v 1.017700 -0.000000 1.785200 1225 | v 0.928300 -0.000000 1.807600 1226 | v 0.840400 -0.000000 1.842400 1227 | v 0.756500 -0.000000 1.890400 1228 | v 0.642800 -0.000000 1.984900 1229 | v 0.577500 -0.000000 2.059200 1230 | v 0.479800 -0.000000 2.224300 1231 | v 0.449100 -0.000000 2.311500 1232 | v 0.430500 -0.000000 2.400700 1233 | v 1.834900 2.320499 2.713901 1234 | v 1.859500 2.320499 2.625500 1235 | v 1.871800 2.320499 2.504500 1236 | v 1.797900 2.320499 2.799901 1237 | v 1.540400 2.320499 3.091100 1238 | v 1.458000 2.320499 3.139101 1239 | v 1.372200 2.320499 3.173900 1240 | v 1.148800 2.320499 2.504500 1241 | v 1.148800 2.320499 3.203100 1242 | v 1.457100 2.320500 1.842400 1243 | v 1.369200 2.320500 1.807600 1244 | v 1.279800 2.320500 1.785200 1245 | v 0.839500 2.320499 3.139101 1246 | v 0.499600 2.320499 2.799901 1247 | v 0.462600 2.320499 2.713901 1248 | v 0.438000 2.320499 2.625500 1249 | v 0.426900 2.320499 2.504500 1250 | v 0.425800 2.320499 2.535800 1251 | v 1.017700 2.320500 1.785200 1252 | v 0.928300 2.320500 1.807600 1253 | v 0.840400 2.320500 1.842400 1254 | v 0.756500 2.320500 1.890400 1255 | vt 0.018300 0.000000 1256 | vt 0.037500 0.000000 1257 | vt 0.037500 0.333300 1258 | vt 0.000000 0.333300 1259 | vt 0.000000 0.000000 1260 | vt 0.037500 0.666700 1261 | vt 0.000000 0.666700 1262 | vt 0.018300 1.000000 1263 | vt 0.000000 1.000000 1264 | vt 0.037500 1.000000 1265 | vt 0.057300 0.000000 1266 | vt 0.077800 0.000000 1267 | vt 0.077800 0.333300 1268 | vt 0.077800 0.666700 1269 | vt 0.057300 1.000000 1270 | vt 0.077800 1.000000 1271 | vt 0.098900 0.000000 1272 | vt 0.120400 0.000000 1273 | vt 0.120400 0.333300 1274 | vt 0.142100 0.000000 1275 | vt 0.163700 0.000000 1276 | vt 0.163700 0.333300 1277 | vt 0.120400 0.666700 1278 | vt 0.163700 0.666700 1279 | vt 0.098900 1.000000 1280 | vt 0.120400 1.000000 1281 | vt 0.142100 1.000000 1282 | vt 0.163700 1.000000 1283 | vt 0.185200 0.000000 1284 | vt 0.206400 0.000000 1285 | vt 0.206400 0.333300 1286 | vt 0.227600 0.000000 1287 | vt 0.248600 0.000000 1288 | vt 0.248600 0.333300 1289 | vt 0.269700 0.000000 1290 | vt 0.290900 0.000000 1291 | vt 0.290900 0.333300 1292 | vt 0.312200 0.000000 1293 | vt 0.333800 0.000000 1294 | vt 0.333800 0.333300 1295 | vt 0.206400 0.666700 1296 | vt 0.248600 0.666700 1297 | vt 0.290900 0.666700 1298 | vt 0.333800 0.666700 1299 | vt 0.185200 1.000000 1300 | vt 0.206400 1.000000 1301 | vt 0.227600 1.000000 1302 | vt 0.248600 1.000000 1303 | vt 0.269700 1.000000 1304 | vt 0.290900 1.000000 1305 | vt 0.312200 1.000000 1306 | vt 0.333800 1.000000 1307 | vt 0.355500 0.000000 1308 | vt 0.377400 0.000000 1309 | vt 0.399000 0.000000 1310 | vt 0.420200 0.333300 1311 | vt 0.420200 0.000000 1312 | vt 0.420200 0.666700 1313 | vt 0.355500 1.000000 1314 | vt 0.377400 1.000000 1315 | vt 0.399000 1.000000 1316 | vt 0.420200 1.000000 1317 | vt 0.440700 0.000000 1318 | vt 0.460800 0.000000 1319 | vt 0.460800 0.333300 1320 | vt 0.480500 0.000000 1321 | vt 0.500000 0.000000 1322 | vt 0.500000 0.333300 1323 | vt 0.460800 0.666700 1324 | vt 0.500000 0.666700 1325 | vt 0.440700 1.000000 1326 | vt 0.460800 1.000000 1327 | vt 0.480500 1.000000 1328 | vt 0.500000 1.000000 1329 | vt 0.519500 0.000000 1330 | vt 0.539200 0.000000 1331 | vt 0.539200 0.333300 1332 | vt 0.559300 0.000000 1333 | vt 0.579800 0.000000 1334 | vt 0.579800 0.333300 1335 | vt 0.539200 0.666700 1336 | vt 0.579800 0.666700 1337 | vt 0.519500 1.000000 1338 | vt 0.539200 1.000000 1339 | vt 0.559300 1.000000 1340 | vt 0.579800 1.000000 1341 | vt 0.601000 0.000000 1342 | vt 0.622600 0.000000 1343 | vt 0.644500 0.000000 1344 | vt 0.666200 0.333300 1345 | vt 0.666200 0.000000 1346 | vt 0.666200 0.666700 1347 | vt 0.601000 1.000000 1348 | vt 0.622600 1.000000 1349 | vt 0.644500 1.000000 1350 | vt 0.666200 1.000000 1351 | vt 0.687800 0.000000 1352 | vt 0.709100 0.000000 1353 | vt 0.709100 0.333300 1354 | vt 0.730300 0.000000 1355 | vt 0.751400 0.000000 1356 | vt 0.751400 0.333300 1357 | vt 0.772400 0.000000 1358 | vt 0.793600 0.000000 1359 | vt 0.793600 0.333300 1360 | vt 0.814800 0.000000 1361 | vt 0.836300 0.000000 1362 | vt 0.836300 0.333300 1363 | vt 0.709100 0.666700 1364 | vt 0.751400 0.666700 1365 | vt 0.793600 0.666700 1366 | vt 0.836300 0.666700 1367 | vt 0.687800 1.000000 1368 | vt 0.709100 1.000000 1369 | vt 0.730300 1.000000 1370 | vt 0.751400 1.000000 1371 | vt 0.772400 1.000000 1372 | vt 0.793600 1.000000 1373 | vt 0.814800 1.000000 1374 | vt 0.836300 1.000000 1375 | vt 0.857900 0.000000 1376 | vt 0.879600 0.000000 1377 | vt 0.879600 0.333300 1378 | vt 0.901100 0.000000 1379 | vt 0.922200 0.000000 1380 | vt 0.922200 0.333300 1381 | vt 0.879600 0.666700 1382 | vt 0.922200 0.666700 1383 | vt 0.857900 1.000000 1384 | vt 0.879600 1.000000 1385 | vt 0.901100 1.000000 1386 | vt 0.922200 1.000000 1387 | vt 0.942700 0.000000 1388 | vt 0.962500 0.000000 1389 | vt 0.962500 0.333300 1390 | vt 0.962500 0.666700 1391 | vt 0.942700 1.000000 1392 | vt 0.962500 1.000000 1393 | vt 0.981700 0.000000 1394 | vt 1.000000 0.000000 1395 | vt 1.000000 0.333300 1396 | vt 1.000000 0.666700 1397 | vt 0.981700 1.000000 1398 | vt 1.000000 1.000000 1399 | vt 0.359700 0.056500 1400 | vt 0.500000 0.032700 1401 | vt 0.418900 0.040600 1402 | vt 0.302100 0.080400 1403 | vt 0.220100 0.131200 1404 | vt 0.170200 0.173600 1405 | vt 0.107000 0.246900 1406 | vt 0.074800 0.300100 1407 | vt 0.051400 0.355600 1408 | vt 0.031900 0.441700 1409 | vt 0.500000 0.500000 1410 | vt 0.031900 0.500000 1411 | vt 0.569600 0.035800 1412 | vt 0.509200 0.031800 1413 | vt 0.629300 0.047800 1414 | vt 0.687800 0.067700 1415 | vt 0.798400 0.130800 1416 | vt 0.848300 0.173000 1417 | vt 0.892300 0.220800 1418 | vt 0.943700 0.300700 1419 | vt 0.967100 0.357500 1420 | vt 0.982100 0.415300 1421 | vt 0.990200 0.500000 1422 | vt 0.031900 0.558300 1423 | vt 0.042900 0.616000 1424 | vt 0.074800 0.699900 1425 | vt 0.126200 0.778600 1426 | vt 0.220100 0.868800 1427 | vt 0.302100 0.919600 1428 | vt 0.359700 0.943500 1429 | vt 0.418900 0.959400 1430 | vt 0.500000 0.966500 1431 | vt 0.479000 0.967300 1432 | vt 0.982100 0.584700 1433 | vt 0.967100 0.642500 1434 | vt 0.943700 0.699300 1435 | vt 0.911500 0.753500 1436 | vt 0.848300 0.827000 1437 | vt 0.798400 0.869200 1438 | vt 0.687800 0.932300 1439 | vt 0.629300 0.952200 1440 | vt 0.569600 0.964200 1441 | usemtl wire_087224143 1442 | s 1 1443 | f 250/318 251/319 252/320 1444 | f 250/318 252/320 253/321 1445 | f 250/318 253/321 254/322 1446 | f 253/321 252/320 255/323 1447 | f 253/321 255/323 256/324 1448 | f 257/325 258/326 256/324 1449 | f 257/325 256/324 255/323 1450 | f 257/325 255/323 259/327 1451 | f 260/328 261/329 262/330 1452 | f 260/328 262/330 252/320 1453 | f 260/328 252/320 251/319 1454 | f 252/320 262/330 263/331 1455 | f 252/320 263/331 255/323 1456 | f 264/332 259/327 255/323 1457 | f 264/332 255/323 263/331 1458 | f 264/332 263/331 265/333 1459 | f 266/334 267/335 268/336 1460 | f 266/334 268/336 262/330 1461 | f 266/334 262/330 261/329 1462 | f 269/337 270/338 271/339 1463 | f 269/337 271/339 268/336 1464 | f 269/337 268/336 267/335 1465 | f 262/330 268/336 272/340 1466 | f 262/330 272/340 263/331 1467 | f 268/336 271/339 273/341 1468 | f 268/336 273/341 272/340 1469 | f 274/342 265/333 263/331 1470 | f 274/342 263/331 272/340 1471 | f 274/342 272/340 275/343 1472 | f 276/344 275/343 272/340 1473 | f 276/344 272/340 273/341 1474 | f 276/344 273/341 277/345 1475 | f 278/346 279/347 280/348 1476 | f 278/346 280/348 271/339 1477 | f 278/346 271/339 270/338 1478 | f 281/349 282/350 283/351 1479 | f 281/349 283/351 280/348 1480 | f 281/349 280/348 279/347 1481 | f 284/352 285/353 286/354 1482 | f 284/352 286/354 283/351 1483 | f 284/352 283/351 282/350 1484 | f 287/355 288/356 289/357 1485 | f 287/355 289/357 286/354 1486 | f 287/355 286/354 285/353 1487 | f 271/339 280/348 290/358 1488 | f 271/339 290/358 273/341 1489 | f 280/348 283/351 291/359 1490 | f 280/348 291/359 290/358 1491 | f 283/351 286/354 292/360 1492 | f 283/351 292/360 291/359 1493 | f 286/354 289/357 293/361 1494 | f 286/354 293/361 292/360 1495 | f 294/362 277/345 273/341 1496 | f 294/362 273/341 290/358 1497 | f 294/362 290/358 295/363 1498 | f 296/364 295/363 290/358 1499 | f 296/364 290/358 291/359 1500 | f 296/364 291/359 297/365 1501 | f 298/366 297/365 291/359 1502 | f 298/366 291/359 292/360 1503 | f 298/366 292/360 299/367 1504 | f 300/368 299/367 292/360 1505 | f 300/368 292/360 293/361 1506 | f 300/368 293/361 301/369 1507 | f 302/370 289/357 288/356 1508 | f 303/371 289/357 302/370 1509 | f 304/372 289/357 303/371 1510 | f 305/373 289/357 304/372 1511 | f 306/374 305/373 304/372 1512 | f 289/357 305/373 307/375 1513 | f 289/357 307/375 293/361 1514 | f 308/376 301/369 293/361 1515 | f 309/377 308/376 293/361 1516 | f 310/378 309/377 293/361 1517 | f 311/379 310/378 293/361 1518 | f 307/375 311/379 293/361 1519 | f 312/380 313/381 314/382 1520 | f 312/380 314/382 305/373 1521 | f 312/380 305/373 306/374 1522 | f 315/383 316/384 317/385 1523 | f 315/383 317/385 314/382 1524 | f 315/383 314/382 313/381 1525 | f 305/373 314/382 318/386 1526 | f 305/373 318/386 307/375 1527 | f 314/382 317/385 319/387 1528 | f 314/382 319/387 318/386 1529 | f 320/388 311/379 307/375 1530 | f 320/388 307/375 318/386 1531 | f 320/388 318/386 321/389 1532 | f 322/390 321/389 318/386 1533 | f 322/390 318/386 319/387 1534 | f 322/390 319/387 323/391 1535 | f 324/392 325/393 326/394 1536 | f 324/392 326/394 317/385 1537 | f 324/392 317/385 316/384 1538 | f 327/395 328/396 329/397 1539 | f 327/395 329/397 326/394 1540 | f 327/395 326/394 325/393 1541 | f 317/385 326/394 330/398 1542 | f 317/385 330/398 319/387 1543 | f 326/394 329/397 331/399 1544 | f 326/394 331/399 330/398 1545 | f 332/400 323/391 319/387 1546 | f 332/400 319/387 330/398 1547 | f 332/400 330/398 333/401 1548 | f 334/402 333/401 330/398 1549 | f 334/402 330/398 331/399 1550 | f 334/402 331/399 335/403 1551 | f 336/404 329/397 328/396 1552 | f 337/405 329/397 336/404 1553 | f 338/406 329/397 337/405 1554 | f 339/407 329/397 338/406 1555 | f 340/408 339/407 338/406 1556 | f 329/397 339/407 341/409 1557 | f 329/397 341/409 331/399 1558 | f 342/410 335/403 331/399 1559 | f 343/411 342/410 331/399 1560 | f 344/412 343/411 331/399 1561 | f 345/413 344/412 331/399 1562 | f 341/409 345/413 331/399 1563 | f 346/414 347/415 348/416 1564 | f 346/414 348/416 339/407 1565 | f 346/414 339/407 340/408 1566 | f 349/417 350/418 351/419 1567 | f 349/417 351/419 348/416 1568 | f 349/417 348/416 347/415 1569 | f 352/420 353/421 354/422 1570 | f 352/420 354/422 351/419 1571 | f 352/420 351/419 350/418 1572 | f 355/423 356/424 357/425 1573 | f 355/423 357/425 354/422 1574 | f 355/423 354/422 353/421 1575 | f 339/407 348/416 358/426 1576 | f 339/407 358/426 341/409 1577 | f 348/416 351/419 359/427 1578 | f 348/416 359/427 358/426 1579 | f 351/419 354/422 360/428 1580 | f 351/419 360/428 359/427 1581 | f 354/422 357/425 361/429 1582 | f 354/422 361/429 360/428 1583 | f 362/430 345/413 341/409 1584 | f 362/430 341/409 358/426 1585 | f 362/430 358/426 363/431 1586 | f 364/432 363/431 358/426 1587 | f 364/432 358/426 359/427 1588 | f 364/432 359/427 365/433 1589 | f 366/434 365/433 359/427 1590 | f 366/434 359/427 360/428 1591 | f 366/434 360/428 367/435 1592 | f 368/436 367/435 360/428 1593 | f 368/436 360/428 361/429 1594 | f 368/436 361/429 369/437 1595 | f 370/438 371/439 372/440 1596 | f 370/438 372/440 357/425 1597 | f 370/438 357/425 356/424 1598 | f 373/441 374/442 375/443 1599 | f 373/441 375/443 372/440 1600 | f 373/441 372/440 371/439 1601 | f 357/425 372/440 376/444 1602 | f 357/425 376/444 361/429 1603 | f 372/440 375/443 377/445 1604 | f 372/440 377/445 376/444 1605 | f 378/446 369/437 361/429 1606 | f 378/446 361/429 376/444 1607 | f 378/446 376/444 379/447 1608 | f 380/448 379/447 376/444 1609 | f 380/448 376/444 377/445 1610 | f 380/448 377/445 381/449 1611 | f 382/450 383/451 384/452 1612 | f 382/450 384/452 375/443 1613 | f 382/450 375/443 374/442 1614 | f 375/443 384/452 385/453 1615 | f 375/443 385/453 377/445 1616 | f 386/454 381/449 377/445 1617 | f 386/454 377/445 385/453 1618 | f 386/454 385/453 387/455 1619 | f 388/456 254/457 253/458 1620 | f 388/456 253/458 384/452 1621 | f 388/456 384/452 383/451 1622 | f 384/452 253/458 256/459 1623 | f 384/452 256/459 385/453 1624 | f 389/460 387/455 385/453 1625 | f 389/460 385/453 256/459 1626 | f 389/460 256/459 258/461 1627 | f 390/462 391/463 392/464 1628 | f 393/465 391/463 390/462 1629 | f 338/466 391/463 393/465 1630 | f 337/467 391/463 338/466 1631 | f 394/468 391/463 337/467 1632 | f 395/469 391/463 394/468 1633 | f 396/470 391/463 395/469 1634 | f 324/471 391/463 396/470 1635 | f 397/472 391/463 324/471 1636 | f 398/473 397/472 324/471 1637 | f 352/474 350/475 391/463 1638 | f 353/476 352/474 391/463 1639 | f 355/477 353/476 391/463 1640 | f 399/478 355/477 391/463 1641 | f 400/479 399/478 391/463 1642 | f 401/480 400/479 391/463 1643 | f 402/481 401/480 391/463 1644 | f 403/482 402/481 391/463 1645 | f 404/483 403/482 391/463 1646 | f 405/484 404/483 391/463 1647 | f 397/472 405/484 391/463 1648 | f 315/485 397/472 398/473 1649 | f 313/486 397/472 315/485 1650 | f 406/487 397/472 313/486 1651 | f 304/488 397/472 406/487 1652 | f 302/489 397/472 304/488 1653 | f 407/490 397/472 302/489 1654 | f 408/491 397/472 407/490 1655 | f 409/492 397/472 408/491 1656 | f 410/493 397/472 409/492 1657 | f 411/494 410/493 409/492 1658 | f 412/495 405/484 397/472 1659 | f 413/496 412/495 397/472 1660 | f 414/497 413/496 397/472 1661 | f 415/498 414/497 397/472 1662 | f 416/499 415/498 397/472 1663 | f 417/500 416/499 397/472 1664 | f 418/501 417/500 397/472 1665 | f 419/502 418/501 397/472 1666 | f 420/503 419/502 397/472 1667 | f 410/493 420/503 397/472 1668 | f 421/462 422/464 423/463 1669 | f 424/465 421/462 423/463 1670 | f 344/466 424/465 423/463 1671 | f 343/467 344/466 423/463 1672 | f 425/468 343/467 423/463 1673 | f 426/469 425/468 423/463 1674 | f 427/470 426/469 423/463 1675 | f 332/471 427/470 423/463 1676 | f 428/472 332/471 423/463 1677 | f 429/473 332/471 428/472 1678 | f 366/474 423/463 365/475 1679 | f 367/476 423/463 366/474 1680 | f 368/477 423/463 367/476 1681 | f 378/478 423/463 368/477 1682 | f 379/479 423/463 378/478 1683 | f 380/480 423/463 379/479 1684 | f 430/481 423/463 380/480 1685 | f 431/482 423/463 430/481 1686 | f 432/483 423/463 431/482 1687 | f 258/484 423/463 432/483 1688 | f 428/472 423/463 258/484 1689 | f 322/485 429/473 428/472 1690 | f 321/486 322/485 428/472 1691 | f 433/487 321/486 428/472 1692 | f 310/488 433/487 428/472 1693 | f 308/489 310/488 428/472 1694 | f 434/490 308/489 428/472 1695 | f 435/491 434/490 428/472 1696 | f 436/492 435/491 428/472 1697 | f 437/493 436/492 428/472 1698 | f 438/494 436/492 437/493 1699 | f 439/495 428/472 258/484 1700 | f 440/496 428/472 439/495 1701 | f 441/497 428/472 440/496 1702 | f 442/498 428/472 441/497 1703 | f 275/499 428/472 442/498 1704 | f 276/500 428/472 275/499 1705 | f 294/501 428/472 276/500 1706 | f 295/502 428/472 294/501 1707 | f 296/503 428/472 295/502 1708 | f 437/493 428/472 296/503 1709 | o Pyramid 1710 | v -1.373000 -0.000000 2.996600 1711 | v -1.373000 -0.000000 1.418200 1712 | v -0.354600 -0.000000 1.418200 1713 | v -0.354600 -0.000000 2.996600 1714 | v 0.663800 -0.000000 1.418200 1715 | v 0.663800 -0.000000 2.996600 1716 | v -0.354600 1.715500 2.207400 1717 | v 0.663800 -0.000000 2.207400 1718 | v -1.373000 -0.000000 2.207400 1719 | vt 1.000000 0.000000 1720 | vt 1.000000 1.000000 1721 | vt 0.500000 1.000000 1722 | vt 0.500000 0.000000 1723 | vt 0.000000 1.000000 1724 | vt 0.000000 0.000000 1725 | vt 0.499000 1.000000 1726 | vt 0.501000 1.000000 1727 | usemtl wire_108008136 1728 | s 1 1729 | f 443/504 444/505 445/506 1730 | f 443/504 445/506 446/507 1731 | f 446/507 445/506 447/508 1732 | f 446/507 447/508 448/509 1733 | f 447/510 449/507 450/506 1734 | f 450/506 449/504 448/511 1735 | f 448/510 449/507 446/506 1736 | f 449/504 443/511 446/506 1737 | f 444/510 449/507 445/506 1738 | f 445/506 449/504 447/511 1739 | f 443/510 449/507 451/506 1740 | f 451/506 449/504 444/511 1741 | o Box 1742 | v -3.229700 0.000000 -0.405200 1743 | v -3.229700 0.000000 -2.405200 1744 | v -2.229700 0.000000 -2.405200 1745 | v -2.229700 0.000000 -0.405200 1746 | v -1.229700 0.000000 -2.405200 1747 | v -1.229700 0.000000 -0.405200 1748 | v -1.229700 2.000000 -0.405200 1749 | v -1.229700 2.000000 -2.405200 1750 | v -2.229700 2.000000 -2.405200 1751 | v -2.229700 2.000000 -0.405200 1752 | v -3.229700 2.000000 -2.405200 1753 | v -3.229700 2.000000 -0.405200 1754 | v -3.229700 2.000000 -1.405200 1755 | v -3.229700 0.000000 -1.405200 1756 | v -1.229700 2.000000 -1.405200 1757 | v -1.229700 0.000000 -1.405200 1758 | vt 1.000000 0.000000 1759 | vt 1.000000 1.000000 1760 | vt 0.500000 1.000000 1761 | vt 0.500000 0.000000 1762 | vt 0.000000 1.000000 1763 | vt 0.000000 0.000000 1764 | usemtl wire_154154229 1765 | s 1 1766 | f 452/512 453/513 454/514 1767 | f 452/512 454/514 455/515 1768 | f 455/515 454/514 456/516 1769 | f 455/515 456/516 457/517 1770 | f 458/512 459/513 460/514 1771 | f 458/512 460/514 461/515 1772 | f 461/515 460/514 462/516 1773 | f 461/515 462/516 463/517 1774 | f 452/512 463/513 464/514 1775 | f 452/512 464/514 465/515 1776 | f 465/515 464/514 462/516 1777 | f 465/515 462/516 453/517 1778 | f 457/512 458/513 461/514 1779 | f 457/512 461/514 455/515 1780 | f 455/515 461/514 463/516 1781 | f 463/516 452/517 455/515 1782 | f 456/512 459/513 466/514 1783 | f 456/512 466/514 467/515 1784 | f 467/515 466/514 458/516 1785 | f 467/515 458/516 457/517 1786 | f 453/512 462/513 460/514 1787 | f 453/512 460/514 454/515 1788 | f 454/515 460/514 459/516 1789 | f 454/515 459/516 456/517 1790 | -------------------------------------------------------------------------------- /examples/testnurbs.mtl: -------------------------------------------------------------------------------- 1 | # 3ds Max Wavefront OBJ Exporter v0.97b - (c)2007 guruware 2 | # File Created: 24.04.2013 13:32:59 3 | 4 | newmtl wire_154154229 5 | Ns 32 6 | d 1 7 | Tr 0 8 | Tf 1 1 1 9 | illum 2 10 | Ka 0.6039 0.6039 0.8980 11 | Kd 0.6039 0.6039 0.8980 12 | Ks 0.3500 0.3500 0.3500 13 | 14 | newmtl wire_148177026 15 | Ns 32 16 | d 1 17 | Tr 0 18 | Tf 1 1 1 19 | illum 2 20 | Ka 0.5804 0.6941 0.1020 21 | Kd 0.5804 0.6941 0.1020 22 | Ks 0.3500 0.3500 0.3500 23 | 24 | newmtl wire_087224143 25 | Ns 32 26 | d 1 27 | Tr 0 28 | Tf 1 1 1 29 | illum 2 30 | Ka 0.3412 0.8784 0.5608 31 | Kd 0.3412 0.8784 0.5608 32 | Ks 0.3500 0.3500 0.3500 33 | 34 | newmtl wire_108008136 35 | Ns 32 36 | d 1 37 | Tr 0 38 | Tf 1 1 1 39 | illum 2 40 | Ka 0.4235 0.0314 0.5333 41 | Kd 0.4235 0.0314 0.5333 42 | Ks 0.3500 0.3500 0.3500 43 | -------------------------------------------------------------------------------- /examples/textures/main.py: -------------------------------------------------------------------------------- 1 | 2 | import os 3 | import kivy3 4 | from kivy.app import App 5 | from kivy.clock import Clock 6 | from kivy3 import Scene, Renderer, PerspectiveCamera 7 | from kivy3.loaders import OBJMTLLoader 8 | from kivy.uix.floatlayout import FloatLayout 9 | 10 | # Resources pathes 11 | _this_path = os.path.dirname(os.path.realpath(__file__)) 12 | shader_file = os.path.join(_this_path, "./simple.glsl") 13 | obj_file = os.path.join(_this_path, "./orion.obj") 14 | mtl_file = os.path.join(_this_path, "./orion.mtl") 15 | 16 | 17 | class MainApp(App): 18 | 19 | def build(self): 20 | root = FloatLayout() 21 | self.renderer = Renderer(shader_file=shader_file) 22 | scene = Scene() 23 | camera = PerspectiveCamera(15, 1, 1, 1000) 24 | loader = OBJMTLLoader() 25 | obj = loader.load(obj_file, mtl_file) 26 | 27 | scene.add(*obj.children) 28 | for obj in scene.children: 29 | obj.pos.z = -20. 30 | 31 | self.renderer.render(scene, camera) 32 | self.orion = scene.children[0] 33 | 34 | root.add_widget(self.renderer) 35 | self.renderer.bind(size=self._adjust_aspect) 36 | Clock.schedule_interval(self._rotate_obj, 1 / 20) 37 | return root 38 | 39 | def _adjust_aspect(self, inst, val): 40 | rsize = self.renderer.size 41 | aspect = rsize[0] / float(rsize[1]) 42 | self.renderer.camera.aspect = aspect 43 | 44 | def _rotate_obj(self, dt): 45 | self.orion.rot.x += 2 46 | 47 | 48 | if __name__ == '__main__': 49 | MainApp().run() 50 | -------------------------------------------------------------------------------- /examples/textures/orion.mtl: -------------------------------------------------------------------------------- 1 | # Blender MTL File: 'orion.blend' 2 | # Material Count: 1 3 | 4 | newmtl Material_orion.png 5 | Ns 0.000000 6 | Ka 0.000000 0.000000 0.000000 7 | Kd 0.800000 0.800000 0.800000 8 | Ks 0.000000 0.000000 0.000000 9 | Ni 1.000000 10 | d 1.000000 11 | illum 1 12 | map_Kd orion.png 13 | -------------------------------------------------------------------------------- /examples/textures/orion.obj: -------------------------------------------------------------------------------- 1 | # Blender3D v249 OBJ File: orion.blend 2 | # www.blender3d.org 3 | o Orion 4 | v 0.074437 0.074437 0.200325 5 | v 0.101683 0.027246 0.200325 6 | v 0.101683 -0.027246 0.200325 7 | v 0.074437 -0.074437 0.200325 8 | v 0.027246 -0.101683 0.200325 9 | v -0.027246 -0.101683 0.200325 10 | v -0.074437 -0.074437 0.200325 11 | v -0.101683 -0.027246 0.200325 12 | v -0.101683 0.027246 0.200325 13 | v -0.074437 0.074437 0.200325 14 | v -0.027246 0.101683 0.200325 15 | v 0.027246 0.101683 0.200325 16 | v 0.027246 -0.101683 0.279154 17 | v -0.027246 -0.101683 0.279154 18 | v -0.074437 -0.074437 0.279154 19 | v -0.101683 -0.027246 0.279154 20 | v -0.101683 0.027246 0.279154 21 | v -0.027246 0.101683 0.279154 22 | v 0.027246 0.101683 0.279154 23 | v 0.353549 0.353549 -0.304347 24 | v 0.461934 0.191339 -0.304347 25 | v 0.499994 -0.000000 -0.304347 26 | v 0.461934 -0.191339 -0.304347 27 | v 0.353549 -0.353549 -0.304347 28 | v 0.191339 -0.461934 -0.304347 29 | v 0.000000 -0.499994 -0.304347 30 | v -0.191339 -0.461934 -0.304347 31 | v -0.353549 -0.353549 -0.304347 32 | v -0.461934 -0.191339 -0.304347 33 | v -0.499994 0.000000 -0.304347 34 | v -0.461934 0.191339 -0.304347 35 | v -0.353549 0.353549 -0.304347 36 | v -0.191339 0.461934 -0.304347 37 | v 0.000000 0.499994 -0.304347 38 | v 0.191340 0.461934 -0.304347 39 | v 0.126716 0.126716 0.200295 40 | v 0.165563 0.068578 0.200295 41 | v 0.179204 -0.000000 0.200295 42 | v 0.165562 -0.068578 0.200295 43 | v 0.126716 -0.126716 0.200295 44 | v 0.068578 -0.165563 0.200295 45 | v -0.000000 -0.179203 0.200295 46 | v -0.068579 -0.165562 0.200295 47 | v -0.126716 -0.126716 0.200295 48 | v -0.165563 -0.068578 0.200295 49 | v -0.179204 0.000000 0.200295 50 | v -0.165562 0.068579 0.200295 51 | v -0.126716 0.126716 0.200295 52 | v -0.068578 0.165563 0.200295 53 | v 0.000001 0.179203 0.200295 54 | v 0.068579 0.165562 0.200295 55 | v -0.000000 -0.000000 0.200295 56 | v 0.191340 0.461934 -0.345528 57 | v 0.000000 0.499994 -0.345528 58 | v -0.191339 0.461934 -0.345528 59 | v -0.353549 0.353549 -0.345528 60 | v -0.461934 0.191339 -0.345528 61 | v -0.499994 0.000000 -0.345528 62 | v -0.461934 -0.191339 -0.345528 63 | v -0.353549 -0.353549 -0.345528 64 | v -0.191339 -0.461934 -0.345528 65 | v 0.000000 -0.499994 -0.345528 66 | v 0.191339 -0.461934 -0.345528 67 | v 0.353549 -0.353549 -0.345528 68 | v 0.461934 -0.191339 -0.345528 69 | v 0.499994 -0.000000 -0.345528 70 | v 0.461934 0.191339 -0.345528 71 | v 0.353549 0.353549 -0.345528 72 | v 0.182792 0.182792 -0.423003 73 | v 0.238829 0.098926 -0.423003 74 | v 0.258507 -0.000000 -0.423003 75 | v 0.238829 -0.098926 -0.423003 76 | v 0.182792 -0.182792 -0.423003 77 | v 0.098926 -0.238830 -0.423003 78 | v 0.000000 -0.258507 -0.423003 79 | v -0.098926 -0.238830 -0.423003 80 | v -0.182792 -0.182792 -0.423003 81 | v -0.238830 -0.098927 -0.423003 82 | v -0.258507 0.000000 -0.423003 83 | v -0.238829 0.098927 -0.423003 84 | v -0.182792 0.182792 -0.423003 85 | v -0.098926 0.238830 -0.423003 86 | v 0.000000 0.258507 -0.423003 87 | v 0.098927 0.238829 -0.423003 88 | v 0.000000 -0.000000 -0.451819 89 | v 0.036168 0.087317 -0.451819 90 | v 0.000000 0.094511 -0.451819 91 | v -0.036168 0.087317 -0.451819 92 | v -0.066830 0.066830 -0.451819 93 | v -0.087317 0.036168 -0.451819 94 | v -0.094511 -0.000000 -0.451819 95 | v -0.087317 -0.036168 -0.451819 96 | v -0.066830 -0.066830 -0.451819 97 | v -0.036168 -0.087317 -0.451819 98 | v 0.000000 -0.094511 -0.451819 99 | v 0.036168 -0.087317 -0.451819 100 | v 0.066830 -0.066830 -0.451819 101 | v 0.087317 -0.036168 -0.451819 102 | v 0.094511 -0.000000 -0.451819 103 | v 0.087317 0.036168 -0.451819 104 | v 0.066830 0.066830 -0.451819 105 | v 0.087192 0.087192 0.200325 106 | v 0.113922 0.047188 0.200325 107 | v 0.123308 0.000000 0.200325 108 | v 0.113922 -0.047188 0.200325 109 | v 0.087192 -0.087192 0.200325 110 | v 0.047188 -0.113922 0.200325 111 | v -0.000000 -0.123308 0.200325 112 | v -0.047188 -0.113922 0.200325 113 | v -0.087192 -0.087192 0.200325 114 | v -0.113922 -0.047188 0.200325 115 | v -0.123308 0.000000 0.200325 116 | v -0.113922 0.047188 0.200325 117 | v -0.087192 0.087192 0.200325 118 | v -0.047188 0.113922 0.200325 119 | v 0.000000 0.123308 0.200325 120 | v 0.047188 0.113922 0.200325 121 | v 0.087192 0.087192 0.228335 122 | v 0.113922 0.047188 0.228335 123 | v 0.123308 -0.000000 0.228335 124 | v 0.113922 -0.047188 0.228335 125 | v 0.087192 -0.087192 0.228335 126 | v 0.047188 -0.113922 0.228335 127 | v -0.000000 -0.123308 0.228335 128 | v -0.047188 -0.113922 0.228335 129 | v -0.087192 -0.087192 0.228335 130 | v -0.113922 -0.047188 0.228335 131 | v -0.123308 0.000000 0.228335 132 | v -0.113922 0.047188 0.228335 133 | v -0.087192 0.087192 0.228335 134 | v -0.047188 0.113922 0.228335 135 | v 0.000000 0.123308 0.228335 136 | v 0.047188 0.113922 0.228335 137 | v 0.109789 0.109789 0.228335 138 | v 0.149975 0.040186 0.228335 139 | v 0.149975 -0.040186 0.228335 140 | v 0.109789 -0.109789 0.228335 141 | v 0.040186 -0.149975 0.228335 142 | v -0.040186 -0.149975 0.228335 143 | v -0.109789 -0.109789 0.228335 144 | v -0.149975 -0.040186 0.228335 145 | v -0.149975 0.040186 0.228335 146 | v -0.109789 0.109789 0.228335 147 | v -0.040186 0.149975 0.228335 148 | v 0.040185 0.149975 0.228335 149 | v 0.109789 0.109789 0.279154 150 | v 0.149975 0.040186 0.279154 151 | v 0.149975 -0.040185 0.279154 152 | v 0.109789 -0.109789 0.279154 153 | v 0.040186 -0.149975 0.279154 154 | v -0.040185 -0.149975 0.279154 155 | v -0.109789 -0.109789 0.279154 156 | v -0.149975 -0.040186 0.279154 157 | v -0.149975 0.040185 0.279154 158 | v -0.109789 0.109789 0.279154 159 | v -0.040186 0.149974 0.279154 160 | v 0.040185 0.149975 0.279154 161 | v -0.074437 0.074437 0.279154 162 | v 0.074437 -0.074437 0.279154 163 | v 0.101683 -0.027246 0.279154 164 | v 0.101683 0.027246 0.279154 165 | v 0.074437 0.074437 0.279154 166 | v 0.027246 0.101683 0.228335 167 | v -0.027246 0.101683 0.228335 168 | v -0.074437 0.074437 0.228335 169 | v -0.101683 0.027246 0.228335 170 | v -0.101683 -0.027246 0.228335 171 | v -0.074437 -0.074437 0.228335 172 | v -0.027246 -0.101683 0.228335 173 | v 0.027246 -0.101683 0.228335 174 | v 0.074437 -0.074437 0.228335 175 | v 0.101683 -0.027246 0.228335 176 | v 0.101683 0.027246 0.228335 177 | v 0.074437 0.074437 0.228335 178 | vt 0.347656 0.250000 179 | vt 0.405399 0.297835 180 | vt 0.391850 0.338388 181 | vt 0.410156 0.250000 182 | vt 0.405399 0.202164 183 | vt 0.391850 0.161611 184 | vt 0.371574 0.134515 185 | vt 0.347656 0.125000 186 | vt 0.323738 0.134515 187 | vt 0.303462 0.161612 188 | vt 0.289914 0.202165 189 | vt 0.285156 0.250000 190 | vt 0.289914 0.297836 191 | vt 0.303462 0.338389 192 | vt 0.323739 0.365485 193 | vt 0.347656 0.375000 194 | vt 0.371574 0.365485 195 | vt 0.125000 0.250000 196 | vt 0.140789 0.218423 197 | vt 0.145629 0.232910 198 | vt 0.147329 0.250000 199 | vt 0.145629 0.267090 200 | vt 0.140789 0.281577 201 | vt 0.133545 0.291258 202 | vt 0.125000 0.294657 203 | vt 0.116455 0.291258 204 | vt 0.109211 0.281577 205 | vt 0.104371 0.267090 206 | vt 0.102671 0.250000 207 | vt 0.104371 0.232910 208 | vt 0.109211 0.218423 209 | vt 0.116455 0.208742 210 | vt 0.125000 0.205343 211 | vt 0.133545 0.208742 212 | vt 0.757384 0.252576 213 | vt 0.754173 0.263342 214 | vt 0.753573 0.250618 215 | vt 0.751384 0.257799 216 | vt 0.748642 0.269431 217 | vt 0.747657 0.261854 218 | vt 0.742362 0.269034 219 | vt 0.743432 0.261602 220 | vt 0.737149 0.262476 221 | vt 0.739899 0.257192 222 | vt 0.734369 0.251563 223 | vt 0.737977 0.249887 224 | vt 0.734535 0.239386 225 | vt 0.738087 0.241643 226 | vt 0.737645 0.229161 227 | vt 0.740196 0.234630 228 | vt 0.742846 0.223331 229 | vt 0.743738 0.230605 230 | vt 0.748871 0.223283 231 | vt 0.747835 0.230592 232 | vt 0.754226 0.229299 233 | vt 0.751444 0.234737 234 | vt 0.757440 0.240049 235 | vt 0.753570 0.242113 236 | vt 0.762455 0.254743 237 | vt 0.771579 0.259897 238 | vt 0.765608 0.285870 239 | vt 0.758034 0.270189 240 | vt 0.762259 0.236731 241 | vt 0.774044 0.230094 242 | vt 0.757474 0.221573 243 | vt 0.765207 0.206267 244 | vt 0.749770 0.213633 245 | vt 0.752514 0.194228 246 | vt 0.741325 0.214217 247 | vt 0.739075 0.196085 248 | vt 0.734101 0.222514 249 | vt 0.728452 0.210795 250 | vt 0.729838 0.237030 251 | vt 0.720359 0.231834 252 | vt 0.729600 0.254343 253 | vt 0.718495 0.259956 254 | vt 0.733644 0.269804 255 | vt 0.727088 0.282564 256 | vt 0.741134 0.278871 257 | vt 0.738289 0.299622 258 | vt 0.750183 0.279319 259 | vt 0.753389 0.303930 260 | vt 0.204687 0.225000 261 | vt 0.204687 0.274999 262 | vt 0.191406 0.225000 263 | vt 0.191406 0.274999 264 | vt 0.217969 0.225000 265 | vt 0.217969 0.274999 266 | vt 0.231250 0.225000 267 | vt 0.231250 0.274999 268 | vt 0.032031 0.225000 269 | vt 0.032031 0.274999 270 | vt 0.018750 0.225000 271 | vt 0.018750 0.274999 272 | vt 0.045312 0.225000 273 | vt 0.045312 0.274999 274 | vt 0.058594 0.225000 275 | vt 0.058594 0.274999 276 | vt 0.071875 0.225000 277 | vt 0.071875 0.274999 278 | vt 0.085156 0.225000 279 | vt 0.085156 0.274999 280 | vt 0.098437 0.225000 281 | vt 0.098437 0.274999 282 | vt 0.111719 0.225000 283 | vt 0.111719 0.274999 284 | vt 0.125000 0.225000 285 | vt 0.125000 0.274999 286 | vt 0.138281 0.225000 287 | vt 0.138281 0.274999 288 | vt 0.151562 0.225000 289 | vt 0.151562 0.274999 290 | vt 0.164844 0.225000 291 | vt 0.164844 0.274999 292 | vt 0.178125 0.225000 293 | vt 0.178125 0.274999 294 | vt 0.168185 0.163630 295 | vt 0.181424 0.203257 296 | vt 0.186073 0.250000 297 | vt 0.181424 0.296743 298 | vt 0.168185 0.336370 299 | vt 0.148372 0.362848 300 | vt 0.125000 0.372146 301 | vt 0.101628 0.362848 302 | vt 0.081815 0.336370 303 | vt 0.068576 0.296743 304 | vt 0.063927 0.250000 305 | vt 0.068576 0.203257 306 | vt 0.081815 0.163630 307 | vt 0.101628 0.137152 308 | vt 0.125000 0.127854 309 | vt 0.148372 0.137152 310 | vt 0.170205 0.031734 311 | vt 0.208527 0.082946 312 | vt 0.125000 0.013750 313 | vt 0.079796 0.031733 314 | vt 0.041473 0.082946 315 | vt 0.015867 0.159591 316 | vt 0.006875 0.250000 317 | vt 0.015867 0.340409 318 | vt 0.041473 0.417054 319 | vt 0.079796 0.468267 320 | vt 0.125000 0.486250 321 | vt 0.170204 0.468267 322 | vt 0.208527 0.417054 323 | vt 0.234133 0.340409 324 | vt 0.243125 0.250000 325 | vt 0.234133 0.159591 326 | vt 0.812500 1.000000 327 | vt 0.812500 0.500000 328 | vt 0.874999 1.000000 329 | vt 0.875000 0.500000 330 | vt 0.937500 0.500000 331 | vt 0.937499 1.000000 332 | vt 1.000000 0.500000 333 | vt 1.000000 1.000000 334 | vt 0.062500 0.500000 335 | vt 0.062500 1.000000 336 | vt -0.000000 0.500000 337 | vt -0.000000 1.000000 338 | vt 0.125000 0.500000 339 | vt 0.125000 1.000000 340 | vt 0.187500 0.500000 341 | vt 0.187500 1.000000 342 | vt 0.250000 0.500000 343 | vt 0.250000 1.000000 344 | vt 0.312500 0.500000 345 | vt 0.312500 1.000000 346 | vt 0.375000 0.500000 347 | vt 0.375000 1.000000 348 | vt 0.437500 0.500000 349 | vt 0.437500 1.000000 350 | vt 0.500000 0.500000 351 | vt 0.500000 1.000000 352 | vt 0.562500 0.500000 353 | vt 0.562500 1.000000 354 | vt 0.625000 0.500000 355 | vt 0.625000 1.000000 356 | vt 0.687500 0.500000 357 | vt 0.687500 1.000000 358 | vt 0.750000 0.500000 359 | vt 0.750000 1.000000 360 | vt 0.808984 0.210528 361 | vt 0.808984 0.278762 362 | vt 0.789893 0.152690 363 | vt 0.759989 0.125000 364 | vt 0.728934 0.130281 365 | vt 0.703847 0.162312 366 | vt 0.687979 0.211756 367 | vt 0.685390 0.274127 368 | vt 0.700214 0.331997 369 | vt 0.726911 0.369307 370 | vt 0.761462 0.375000 371 | vt 0.792426 0.339618 372 | usemtl Material_orion.png 373 | s off 374 | f 52/1 37/2 36/3 375 | f 52/1 38/4 37/2 376 | f 52/1 39/5 38/4 377 | f 52/1 40/6 39/5 378 | f 52/1 41/7 40/6 379 | f 52/1 42/8 41/7 380 | f 52/1 43/9 42/8 381 | f 52/1 44/10 43/9 382 | f 52/1 45/11 44/10 383 | f 52/1 46/12 45/11 384 | f 52/1 47/13 46/12 385 | f 52/1 48/14 47/13 386 | f 52/1 49/15 48/14 387 | f 52/1 50/16 49/15 388 | f 52/1 51/17 50/16 389 | f 52/1 36/3 51/17 390 | f 85/18 101/19 100/20 391 | f 85/18 100/20 99/21 392 | f 85/18 99/21 98/22 393 | f 85/18 98/22 97/23 394 | f 85/18 97/23 96/24 395 | f 85/18 96/24 95/25 396 | f 85/18 95/25 94/26 397 | f 85/18 94/26 93/27 398 | f 85/18 93/27 92/28 399 | f 85/18 92/28 91/29 400 | f 85/18 91/29 90/30 401 | f 85/18 90/30 89/31 402 | f 85/18 89/31 88/32 403 | f 85/18 88/32 87/33 404 | f 85/18 87/33 86/34 405 | f 85/18 86/34 101/19 406 | f 134/35 135/36 174/37 407 | f 135/36 173/38 174/37 408 | f 135/36 136/39 173/38 409 | f 136/39 172/40 173/38 410 | f 136/39 137/41 172/40 411 | f 137/41 171/42 172/40 412 | f 137/41 138/43 171/42 413 | f 138/43 170/44 171/42 414 | f 138/43 139/45 170/44 415 | f 139/45 169/46 170/44 416 | f 139/45 140/47 168/48 417 | f 139/45 168/48 169/46 418 | f 140/47 141/49 167/50 419 | f 140/47 167/50 168/48 420 | f 141/49 142/51 166/52 421 | f 141/49 166/52 167/50 422 | f 142/51 143/53 165/54 423 | f 142/51 165/54 166/52 424 | f 143/53 144/55 164/56 425 | f 143/53 164/56 165/54 426 | f 144/55 145/57 163/58 427 | f 144/55 163/58 164/56 428 | f 134/35 174/37 163/58 429 | f 134/35 163/58 145/57 430 | f 146/59 162/60 161/61 431 | f 146/59 161/61 147/62 432 | f 146/59 157/63 19/64 433 | f 146/59 19/64 162/60 434 | f 156/65 18/66 19/64 435 | f 156/65 19/64 157/63 436 | f 155/67 158/68 18/66 437 | f 155/67 18/66 156/65 438 | f 154/69 17/70 158/68 439 | f 154/69 158/68 155/67 440 | f 153/71 16/72 17/70 441 | f 153/71 17/70 154/69 442 | f 152/73 15/74 153/71 443 | f 15/74 16/72 153/71 444 | f 151/75 14/76 152/73 445 | f 14/76 15/74 152/73 446 | f 150/77 13/78 14/76 447 | f 150/77 14/76 151/75 448 | f 149/79 159/80 150/77 449 | f 159/80 13/78 150/77 450 | f 148/81 160/82 149/79 451 | f 160/82 159/80 149/79 452 | f 147/62 161/61 160/82 453 | f 147/62 160/82 148/81 454 | f 145/57 157/63 146/59 455 | f 145/57 146/59 134/35 456 | f 144/55 156/65 157/63 457 | f 144/55 157/63 145/57 458 | f 143/53 155/67 156/65 459 | f 143/53 156/65 144/55 460 | f 142/51 154/69 155/67 461 | f 142/51 155/67 143/53 462 | f 141/49 153/71 154/69 463 | f 141/49 154/69 142/51 464 | f 140/47 152/73 153/71 465 | f 140/47 153/71 141/49 466 | f 139/45 151/75 152/73 467 | f 139/45 152/73 140/47 468 | f 138/43 150/77 151/75 469 | f 138/43 151/75 139/45 470 | f 137/41 149/79 150/77 471 | f 137/41 150/77 138/43 472 | f 136/39 148/81 149/79 473 | f 136/39 149/79 137/41 474 | f 135/36 147/62 148/81 475 | f 135/36 148/81 136/39 476 | f 134/35 146/59 147/62 477 | f 134/35 147/62 135/36 478 | f 117/83 133/84 102/85 479 | f 133/84 118/86 102/85 480 | f 116/87 132/88 117/83 481 | f 132/88 133/84 117/83 482 | f 115/89 131/90 116/87 483 | f 131/90 132/88 116/87 484 | f 114/91 130/92 115/93 485 | f 130/92 131/94 115/93 486 | f 113/95 129/96 114/91 487 | f 129/96 130/92 114/91 488 | f 112/97 128/98 113/95 489 | f 128/98 129/96 113/95 490 | f 111/99 127/100 112/97 491 | f 127/100 128/98 112/97 492 | f 110/101 126/102 111/99 493 | f 126/102 127/100 111/99 494 | f 109/103 125/104 110/101 495 | f 125/104 126/102 110/101 496 | f 108/105 124/106 109/103 497 | f 124/106 125/104 109/103 498 | f 107/107 123/108 108/105 499 | f 123/108 124/106 108/105 500 | f 106/109 122/110 107/107 501 | f 122/110 123/108 107/107 502 | f 105/111 121/112 106/109 503 | f 121/112 122/110 106/109 504 | f 104/113 120/114 105/111 505 | f 120/114 121/112 105/111 506 | f 103/115 119/116 104/113 507 | f 119/116 120/114 104/113 508 | f 102/85 118/86 103/115 509 | f 118/86 119/116 103/115 510 | f 69/117 70/118 100/20 511 | f 69/117 100/20 101/19 512 | f 70/118 71/119 100/20 513 | f 71/119 99/21 100/20 514 | f 71/119 72/120 98/22 515 | f 71/119 98/22 99/21 516 | f 72/120 73/121 98/22 517 | f 73/121 97/23 98/22 518 | f 73/121 74/122 96/24 519 | f 73/121 96/24 97/23 520 | f 74/122 75/123 95/25 521 | f 74/122 95/25 96/24 522 | f 75/123 76/124 94/26 523 | f 75/123 94/26 95/25 524 | f 76/124 77/125 93/27 525 | f 76/124 93/27 94/26 526 | f 77/125 78/126 92/28 527 | f 77/125 92/28 93/27 528 | f 78/126 79/127 91/29 529 | f 78/126 91/29 92/28 530 | f 79/127 80/128 91/29 531 | f 80/128 90/30 91/29 532 | f 80/128 81/129 90/30 533 | f 81/129 89/31 90/30 534 | f 81/129 82/130 88/32 535 | f 81/129 88/32 89/31 536 | f 82/130 83/131 88/32 537 | f 83/131 87/33 88/32 538 | f 83/131 84/132 87/33 539 | f 84/132 86/34 87/33 540 | f 84/132 69/117 101/19 541 | f 84/132 101/19 86/34 542 | f 53/133 68/134 69/117 543 | f 53/133 69/117 84/132 544 | f 54/135 53/133 83/131 545 | f 53/133 84/132 83/131 546 | f 55/136 54/135 82/130 547 | f 54/135 83/131 82/130 548 | f 56/137 55/136 82/130 549 | f 56/137 82/130 81/129 550 | f 57/138 56/137 80/128 551 | f 56/137 81/129 80/128 552 | f 58/139 57/138 80/128 553 | f 58/139 80/128 79/127 554 | f 59/140 58/139 79/127 555 | f 59/140 79/127 78/126 556 | f 60/141 59/140 78/126 557 | f 60/141 78/126 77/125 558 | f 61/142 60/141 77/125 559 | f 61/142 77/125 76/124 560 | f 62/143 61/142 76/124 561 | f 62/143 76/124 75/123 562 | f 63/144 62/143 75/123 563 | f 63/144 75/123 74/122 564 | f 64/145 63/144 74/122 565 | f 64/145 74/122 73/121 566 | f 65/146 64/145 72/120 567 | f 64/145 73/121 72/120 568 | f 66/147 65/146 72/120 569 | f 66/147 72/120 71/119 570 | f 67/148 66/147 70/118 571 | f 66/147 71/119 70/118 572 | f 68/134 67/148 70/118 573 | f 68/134 70/118 69/117 574 | f 20/134 21/148 67/148 575 | f 20/134 67/148 68/134 576 | f 21/148 22/147 66/147 577 | f 21/148 66/147 67/148 578 | f 22/147 23/146 65/146 579 | f 22/147 65/146 66/147 580 | f 23/146 24/145 64/145 581 | f 23/146 64/145 65/146 582 | f 24/145 25/144 63/144 583 | f 24/145 63/144 64/145 584 | f 25/144 26/143 62/143 585 | f 25/144 62/143 63/144 586 | f 26/143 27/142 61/142 587 | f 26/143 61/142 62/143 588 | f 27/142 28/141 60/141 589 | f 27/142 60/141 61/142 590 | f 28/141 29/140 59/140 591 | f 28/141 59/140 60/141 592 | f 29/140 30/139 58/139 593 | f 29/140 58/139 59/140 594 | f 30/139 31/138 57/138 595 | f 30/139 57/138 58/139 596 | f 31/138 32/137 56/137 597 | f 31/138 56/137 57/138 598 | f 32/137 33/136 55/136 599 | f 32/137 55/136 56/137 600 | f 33/136 34/135 54/135 601 | f 33/136 54/135 55/136 602 | f 34/135 35/133 53/133 603 | f 34/135 53/133 54/135 604 | f 35/133 20/134 68/134 605 | f 35/133 68/134 53/133 606 | f 36/149 20/150 51/151 607 | f 20/150 35/152 51/151 608 | f 34/153 50/154 35/152 609 | f 50/154 51/151 35/152 610 | f 33/155 49/156 34/153 611 | f 49/156 50/154 34/153 612 | f 32/157 48/158 33/159 613 | f 48/158 49/160 33/159 614 | f 31/161 47/162 32/157 615 | f 47/162 48/158 32/157 616 | f 30/163 46/164 31/161 617 | f 46/164 47/162 31/161 618 | f 29/165 45/166 30/163 619 | f 45/166 46/164 30/163 620 | f 28/167 44/168 29/165 621 | f 44/168 45/166 29/165 622 | f 27/169 43/170 28/167 623 | f 43/170 44/168 28/167 624 | f 26/171 42/172 27/169 625 | f 42/172 43/170 27/169 626 | f 25/173 41/174 26/171 627 | f 41/174 42/172 26/171 628 | f 24/175 40/176 25/173 629 | f 40/176 41/174 25/173 630 | f 23/177 39/178 24/175 631 | f 39/178 40/176 24/175 632 | f 22/179 38/180 23/177 633 | f 38/180 39/178 23/177 634 | f 21/181 37/182 22/179 635 | f 37/182 38/180 22/179 636 | f 20/150 36/149 21/181 637 | f 36/149 37/182 21/181 638 | f 12/183 1/184 162/60 639 | f 12/183 162/60 19/64 640 | f 11/185 12/183 19/64 641 | f 11/185 19/64 18/66 642 | f 10/186 11/185 18/66 643 | f 10/186 18/66 158/68 644 | f 9/187 10/186 158/68 645 | f 9/187 158/68 17/70 646 | f 8/188 9/187 17/70 647 | f 8/188 17/70 16/72 648 | f 7/189 8/188 16/72 649 | f 7/189 16/72 15/74 650 | f 6/190 7/189 15/74 651 | f 6/190 15/74 14/76 652 | f 5/191 6/190 14/76 653 | f 5/191 14/76 13/78 654 | f 4/192 5/191 13/78 655 | f 4/192 13/78 159/80 656 | f 3/193 4/192 159/80 657 | f 3/193 159/80 160/82 658 | f 2/194 3/193 160/82 659 | f 2/194 160/82 161/61 660 | f 1/184 2/194 161/61 661 | f 1/184 161/61 162/60 662 | -------------------------------------------------------------------------------- /examples/textures/orion.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivy/kivy3/e3364b39ec61a69aa31bf88e77fadaa148359ec6/examples/textures/orion.png -------------------------------------------------------------------------------- /examples/textures/simple.glsl: -------------------------------------------------------------------------------- 1 | ---VERTEX SHADER------------------------------------------------------- 2 | #ifdef GL_ES 3 | precision highp float; 4 | #endif 5 | 6 | attribute vec3 v_pos; 7 | attribute vec4 v_color; 8 | attribute vec2 v_tc0; 9 | 10 | uniform mat4 modelview_mat; 11 | uniform mat4 projection_mat; 12 | 13 | varying vec4 frag_color; 14 | varying vec2 uv_vec; 15 | 16 | void main (void) { 17 | vec4 pos = modelview_mat * vec4(v_pos,1.0); 18 | gl_Position = projection_mat * pos; 19 | frag_color = v_color; 20 | uv_vec = v_tc0; 21 | } 22 | 23 | 24 | ---FRAGMENT SHADER----------------------------------------------------- 25 | #ifdef GL_ES 26 | precision highp float; 27 | #endif 28 | 29 | varying vec4 frag_color; 30 | varying vec2 uv_vec; 31 | 32 | uniform sampler2D tex; 33 | 34 | void main (void){ 35 | vec4 color = texture2D(tex, uv_vec); 36 | gl_FragColor = color; 37 | } 38 | -------------------------------------------------------------------------------- /examples/trackball/Digital.tga: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivy/kivy3/e3364b39ec61a69aa31bf88e77fadaa148359ec6/examples/trackball/Digital.tga -------------------------------------------------------------------------------- /examples/trackball/MQ-27-2.obj.mtl: -------------------------------------------------------------------------------- 1 | # 2 | # Wavefront material file 3 | # Converted by Meshlab Group 4 | # 5 | 6 | newmtl material_0 7 | Ka 0.200000 0.200000 0.200000 8 | Kd 0.584314 0.584314 0.584314 9 | Ks 1.000000 1.000000 1.000000 10 | Tr 0.000000 11 | illum 2 12 | Ns 0.000000 13 | map_Kd Tan.tga 14 | 15 | newmtl material_1 16 | Ka 0.200000 0.200000 0.200000 17 | Kd 0.584314 0.584314 0.584314 18 | Ks 1.000000 1.000000 1.000000 19 | Tr 0.000000 20 | illum 2 21 | Ns 0.000000 22 | map_Kd gun.tga 23 | 24 | newmtl material_2 25 | Ka 0.200000 0.200000 0.200000 26 | Kd 0.584314 0.584314 0.584314 27 | Ks 1.000000 1.000000 1.000000 28 | Tr 0.000000 29 | illum 2 30 | Ns 0.000000 31 | map_Kd rotor.tga 32 | 33 | -------------------------------------------------------------------------------- /examples/trackball/MQ-27.mtl: -------------------------------------------------------------------------------- 1 | # 3ds Max Wavefront OBJ Exporter v0.97b - (c)2007 guruware 2 | # File Created: 16.01.2013 16:31:12 3 | 4 | newmtl Material__0 5 | Ns 10.0000 6 | Ni 1.5000 7 | d 1.0000 8 | Tr 0.0000 9 | Tf 1.0000 1.0000 1.0000 10 | illum 2 11 | Ka 0.5880 0.5880 0.5880 12 | Kd 0.5880 0.5880 0.5880 13 | Ks 0.0000 0.0000 0.0000 14 | Ke 0.0000 0.0000 0.0000 15 | map_Ka Tan.tga 16 | map_Kd Tan.tga 17 | 18 | newmtl Material__1 19 | Ns 10.0000 20 | Ni 1.5000 21 | d 1.0000 22 | Tr 0.0000 23 | Tf 1.0000 1.0000 1.0000 24 | illum 2 25 | Ka 0.5880 0.5880 0.5880 26 | Kd 0.5880 0.5880 0.5880 27 | Ks 0.0000 0.0000 0.0000 28 | Ke 0.0000 0.0000 0.0000 29 | map_Ka gun.tga 30 | map_Kd gun.tga 31 | 32 | newmtl Material__3 33 | Ns 10.0000 34 | Ni 1.5000 35 | d 1.0000 36 | Tr 0.0000 37 | Tf 1.0000 1.0000 1.0000 38 | illum 2 39 | Ka 0.5880 0.5880 0.5880 40 | Kd 0.5880 0.5880 0.5880 41 | Ks 0.0000 0.0000 0.0000 42 | Ke 0.0000 0.0000 0.0000 43 | map_Ka rotor.tga 44 | map_Kd rotor.tga 45 | -------------------------------------------------------------------------------- /examples/trackball/Tan.tga: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivy/kivy3/e3364b39ec61a69aa31bf88e77fadaa148359ec6/examples/trackball/Tan.tga -------------------------------------------------------------------------------- /examples/trackball/gun.tga: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivy/kivy3/e3364b39ec61a69aa31bf88e77fadaa148359ec6/examples/trackball/gun.tga -------------------------------------------------------------------------------- /examples/trackball/gun_normal.tga: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivy/kivy3/e3364b39ec61a69aa31bf88e77fadaa148359ec6/examples/trackball/gun_normal.tga -------------------------------------------------------------------------------- /examples/trackball/gun_spec.tga: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivy/kivy3/e3364b39ec61a69aa31bf88e77fadaa148359ec6/examples/trackball/gun_spec.tga -------------------------------------------------------------------------------- /examples/trackball/main.py: -------------------------------------------------------------------------------- 1 | 2 | import os 3 | import math 4 | from kivy.app import App 5 | from kivy.clock import Clock 6 | from kivy3 import Scene, Renderer, PerspectiveCamera 7 | from kivy3.loaders import OBJLoader 8 | from kivy.uix.floatlayout import FloatLayout 9 | 10 | # Resources pathes 11 | _this_path = os.path.dirname(os.path.realpath(__file__)) 12 | obj_file = os.path.join(_this_path, "./MQ-27.obj") 13 | 14 | 15 | class ObjectTrackball(FloatLayout): 16 | 17 | def __init__(self, camera, radius, *args, **kw): 18 | super(ObjectTrackball, self).__init__(*args, **kw) 19 | self.camera = camera 20 | self.radius = radius 21 | self.phi = 90 22 | self.theta = 0 23 | self._touches = [] 24 | self.camera.pos.z = radius 25 | camera.look_at((0, 0, 0)) 26 | 27 | def define_rotate_angle(self, touch): 28 | theta_angle = (touch.dx / self.width) * -360 29 | phi_angle = -1 * (touch.dy / self.height) * 360 30 | return phi_angle, theta_angle 31 | 32 | def on_touch_down(self, touch): 33 | touch.grab(self) 34 | self._touches.append(touch) 35 | 36 | def on_touch_up(self, touch): 37 | touch.ungrab(self) 38 | self._touches.remove(touch) 39 | 40 | def on_touch_move(self, touch): 41 | if touch in self._touches and touch.grab_current == self: 42 | if len(self._touches) == 1: 43 | self.do_rotate(touch) 44 | elif len(self._touches) == 2: 45 | pass 46 | 47 | def do_rotate(self, touch): 48 | d_phi, d_theta = self.define_rotate_angle(touch) 49 | self.phi += d_phi 50 | self.theta += d_theta 51 | 52 | _phi = math.radians(self.phi) 53 | _theta = math.radians(self.theta) 54 | z = self.radius * math.cos(_theta) * math.sin(_phi) 55 | x = self.radius * math.sin(_theta) * math.sin(_phi) 56 | y = self.radius * math.cos(_phi) 57 | self.camera.pos = x, y, z 58 | self.camera.look_at((0, 0, 0)) 59 | 60 | 61 | class MainApp(App): 62 | 63 | def build(self): 64 | self.renderer = Renderer() 65 | scene = Scene() 66 | camera = PerspectiveCamera(15, 1, 100, 2500) 67 | loader = OBJLoader() 68 | obj = loader.load(obj_file) 69 | self.obj3d = obj 70 | self.camera = camera 71 | root = ObjectTrackball(camera, 1500) 72 | 73 | scene.add(obj) 74 | 75 | self.renderer.render(scene, camera) 76 | self.renderer.main_light.intensity = 500 77 | 78 | root.add_widget(self.renderer) 79 | self.renderer.bind(size=self._adjust_aspect) 80 | return root 81 | 82 | def _adjust_aspect(self, inst, val): 83 | rsize = self.renderer.size 84 | aspect = rsize[0] / float(rsize[1]) 85 | self.renderer.camera.aspect = aspect 86 | 87 | 88 | if __name__ == '__main__': 89 | MainApp().run() 90 | -------------------------------------------------------------------------------- /examples/trackball/mq_normal.tga: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivy/kivy3/e3364b39ec61a69aa31bf88e77fadaa148359ec6/examples/trackball/mq_normal.tga -------------------------------------------------------------------------------- /examples/trackball/mq_spec.tga: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivy/kivy3/e3364b39ec61a69aa31bf88e77fadaa148359ec6/examples/trackball/mq_spec.tga -------------------------------------------------------------------------------- /examples/trackball/rotor.tga: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivy/kivy3/e3364b39ec61a69aa31bf88e77fadaa148359ec6/examples/trackball/rotor.tga -------------------------------------------------------------------------------- /kivy3.dia: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivy/kivy3/e3364b39ec61a69aa31bf88e77fadaa148359ec6/kivy3.dia -------------------------------------------------------------------------------- /kivy3/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | from .scenes.scene import Scene 3 | from .core.object3d import Object3D 4 | from .math.vectors import Vector4, Vector3, Vector2 5 | from .cameras import PerspectiveCamera, OrthographicCamera 6 | from .renderer import Renderer 7 | from .objects.mesh import Mesh 8 | from .materials import Material 9 | from .core.geometry import Geometry 10 | from .core.face3 import Face3 11 | -------------------------------------------------------------------------------- /kivy3/cameras/__init__.py: -------------------------------------------------------------------------------- 1 | from .orthographic_camera import OrthographicCamera 2 | from .perspective_camera import PerspectiveCamera 3 | from .camera import Camera 4 | -------------------------------------------------------------------------------- /kivy3/cameras/camera.py: -------------------------------------------------------------------------------- 1 | """ 2 | The MIT License (MIT) 3 | 4 | Copyright (c) 2013 Niko Skrypnik 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | """ 24 | 25 | """ 26 | Camera module 27 | ============= 28 | 29 | In this module base camera class is implemented. 30 | """ 31 | 32 | 33 | __all__ = ('Camera', ) 34 | 35 | import math 36 | 37 | from kivy.properties import NumericProperty, ListProperty, ObjectProperty, \ 38 | AliasProperty 39 | from kivy.graphics.transformation import Matrix 40 | from ..math.vectors import Vector3 41 | from ..core.object3d import Object3D 42 | from math import radians 43 | 44 | 45 | class Camera(Object3D): 46 | """ 47 | Base camera class 48 | """ 49 | 50 | scale = NumericProperty(1.0) 51 | _right = ObjectProperty(Vector3(1, 0, 0)) 52 | _up = ObjectProperty(Vector3(0, 1, 0)) 53 | _back = ObjectProperty(Vector3(0, 0, 1)) 54 | up = ObjectProperty(Vector3(0, 1, 0)) 55 | 56 | def __init__(self): 57 | super(Camera, self).__init__() 58 | self.projection_matrix = Matrix() 59 | self.modelview_matrix = Matrix() 60 | self.model_matrix = Matrix() 61 | self.viewport_matrix = (0, 0, 0, 0) 62 | self.renderer = None # renderer camera is bound to 63 | self._look_at = None 64 | self.look_at(Vector3(0, 0, -1)) 65 | 66 | def _set_position(self, val): 67 | super(Camera, self).on_pos_changed(val) 68 | self.look_at(self._look_at) 69 | self.update() 70 | 71 | def on_pos_changed(self, coord, v): 72 | """ Camera position was changed """ 73 | self.look_at(self._look_at) 74 | self.update() 75 | 76 | def on_up(self, instance, up): 77 | """ Camera up vector was changed """ 78 | pass 79 | 80 | def on_scale(self, instance, scale): 81 | """ Handler for change scale parameter event """ 82 | 83 | def look_at(self, *v): 84 | if len(v) == 1: 85 | v = v[0] 86 | m = Matrix() 87 | pos = self._position 88 | m = m.look_at(pos[0], pos[1], pos[2], v[0], v[1], v[2], 89 | self.up[0], self.up[1], self.up[2]) 90 | m = m.rotate(radians(self.rot.x), 1.0, 0.0, 0.0) 91 | m = m.rotate(radians(self.rot.y), 0.0, 1.0, 0.0) 92 | m = m.rotate(radians(self.rot.z), 0.0, 0.0, 1.0) 93 | self.modelview_matrix = m 94 | 95 | # set camera vectors from view matrix 96 | self._right = Vector3(m[0], m[1], m[2]) 97 | self._up = Vector3(m[4], m[5], m[6]) 98 | self._back = Vector3(m[8], m[9], m[10]) 99 | self._look_at = v 100 | self.update() 101 | 102 | def bind_to(self, renderer): 103 | """ Bind this camera to renderer """ 104 | self.renderer = renderer 105 | 106 | def update(self): 107 | if self.renderer: 108 | self.viewport_matrix = ( 109 | self.renderer._viewport.pos[0], 110 | self.renderer._viewport.pos[1], 111 | self.renderer._viewport.size[0], 112 | self.renderer._viewport.size[1] 113 | ) 114 | model_matrix = self.modelview_matrix.multiply( 115 | self.renderer.fbo['view_mat'].inverse()) 116 | self.model_matrix = model_matrix 117 | self.renderer._update_matrices() 118 | 119 | def update_projection_matrix(self): 120 | """ This function should be overridden in the subclasses 121 | """ 122 | -------------------------------------------------------------------------------- /kivy3/cameras/orthographic_camera.py: -------------------------------------------------------------------------------- 1 | """ 2 | The MIT License (MIT) 3 | 4 | Copyright (c) 2013 Niko Skrypnik 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | """ 24 | 25 | """ 26 | Orthographic camera module 27 | ============= 28 | 29 | Implements orthographic camera type. 30 | """ 31 | 32 | __all__ = () 33 | 34 | 35 | class OrthographicCamera(): 36 | """ Implements orthographic camera """ 37 | -------------------------------------------------------------------------------- /kivy3/cameras/perspective_camera.py: -------------------------------------------------------------------------------- 1 | """ 2 | The MIT License (MIT) 3 | 4 | Copyright (c) 2013 Niko Skrypnik 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | """ 24 | 25 | """ 26 | Perspective camera module 27 | ============= 28 | 29 | Implements perspective camera. 30 | """ 31 | 32 | __all__ = ('PerspectiveCamera', ) 33 | 34 | from kivy.properties import NumericProperty 35 | from kivy.graphics.transformation import Matrix 36 | from .camera import Camera 37 | 38 | 39 | class PerspectiveCamera(Camera): 40 | """ 41 | Implementation of the perspective camera. 42 | """ 43 | 44 | aspect = NumericProperty() 45 | 46 | def __init__(self, fov, aspect, near, far, **kw): 47 | 48 | super(PerspectiveCamera, self).__init__(**kw) 49 | self.fov = fov 50 | self.aspect = aspect 51 | self.near = near 52 | self.far = far 53 | self.update_projection_matrix() 54 | self.bind(aspect=self._on_aspect) 55 | 56 | def _on_aspect(self, inst, value): 57 | self.update_projection_matrix() 58 | self.update() 59 | 60 | def update_projection_matrix(self): 61 | m = Matrix() 62 | m.perspective(self.fov * 0.5, self.aspect, self.near, self.far) 63 | self.projection_matrix = m 64 | -------------------------------------------------------------------------------- /kivy3/core/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivy/kivy3/e3364b39ec61a69aa31bf88e77fadaa148359ec6/kivy3/core/__init__.py -------------------------------------------------------------------------------- /kivy3/core/face3.py: -------------------------------------------------------------------------------- 1 | """ 2 | The MIT License (MIT) 3 | 4 | Copyright (c) 2013 Niko Skrypnik 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | """ 24 | 25 | """ 26 | Face3 class 27 | ============= 28 | 29 | This class should store information about mesh face. Should be used 30 | with some vertices information as it doesn't contain vertices itself, 31 | but only its indices 32 | 33 | """ 34 | 35 | from kivy3 import Vector3 36 | 37 | 38 | class Face3(object): 39 | 40 | def __init__(self, a, b, c, normal=None): 41 | self.a = a 42 | self.b = b 43 | self.c = c 44 | self.normal = normal or Vector3(0, 0, 0) # face normal 45 | self.vertex_normals = [] # vertices normals 46 | -------------------------------------------------------------------------------- /kivy3/core/geometry.py: -------------------------------------------------------------------------------- 1 | """ 2 | The MIT License (MIT) 3 | 4 | Copyright (c) 2013 Niko Skrypnik 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | """ 24 | 25 | """ 26 | Geometry class 27 | ============= 28 | 29 | """ 30 | 31 | 32 | class Geometry(object): 33 | 34 | def __init__(self, name=''): 35 | self.name = name 36 | self.faces = [] 37 | self.vertices = [] 38 | self.face_vertex_uvs = [[]] 39 | 40 | def compute_vertex_normal(self): 41 | pass 42 | -------------------------------------------------------------------------------- /kivy3/core/object3d.py: -------------------------------------------------------------------------------- 1 | """ 2 | The MIT License (MIT) 3 | 4 | Copyright (c) 2013 Niko Skrypnik 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | """ 24 | 25 | """ 26 | Object3D class 27 | ============= 28 | 29 | """ 30 | 31 | from kivy.properties import ( 32 | NumericProperty, ListProperty, 33 | ObjectProperty, AliasProperty 34 | ) 35 | from kivy.graphics import ( 36 | Scale, Rotate, PushMatrix, PopMatrix, 37 | Translate, UpdateNormalMatrix 38 | ) 39 | from kivy.graphics.instructions import InstructionGroup 40 | from kivy.event import EventDispatcher 41 | 42 | from kivy3.math.vectors import Vector3 43 | 44 | 45 | class Object3D(EventDispatcher): 46 | """Base class for all 3D objects in rendered 47 | 3D world. 48 | """ 49 | 50 | def __init__(self, **kw): 51 | 52 | super(Object3D, self).__init__(**kw) 53 | self.name = kw.pop('name', '') 54 | self.children = list() 55 | self.parent = None 56 | 57 | self._scale = Scale(1., 1., 1.) 58 | self._position = Vector3(0, 0, 0) 59 | self._rotation = Vector3(0, 0, 0) 60 | self._position.set_change_cb(self.on_pos_changed) 61 | self._rotation.set_change_cb(self.on_angle_change) 62 | 63 | # general instructions 64 | self._pop_matrix = PopMatrix() 65 | self._push_matrix = PushMatrix() 66 | self._translate = Translate(*self._position) 67 | self._rotors = { 68 | "x": Rotate(self._rotation.x, 1, 0, 0), 69 | "y": Rotate(self._rotation.y, 0, 1, 0), 70 | "z": Rotate(self._rotation.z, 0, 0, 1), 71 | } 72 | 73 | self._instructions = InstructionGroup() 74 | 75 | def add(self, *objs): 76 | for obj in objs: 77 | self._add_child(obj) 78 | 79 | def _add_child(self, obj): 80 | self.children.append(obj) 81 | obj.parent = self 82 | 83 | def _set_position(self, val): 84 | if isinstance(val, Vector3): 85 | self._position = val 86 | else: 87 | self._position = Vector3(val) 88 | self._position.set_change_cb(self.on_pos_changed) 89 | 90 | def _get_position(self): 91 | return self._position 92 | 93 | position = AliasProperty(_get_position, _set_position) 94 | pos = position # just shortcut 95 | 96 | def _set_rotation(self, val): 97 | if isinstance(val, Vector3): 98 | self._rotation = val 99 | else: 100 | self._rotation = Vector3(val) 101 | self._rotation.set_change_cb(self.on_angle_change) 102 | self._rotors["x"].angle = self._rotation.x 103 | self._rotors["y"].angle = self._rotation.y 104 | self._rotors["z"].angle = self._rotation.z 105 | 106 | def _get_rotation(self): 107 | return self._rotation 108 | 109 | rotation = AliasProperty(_get_rotation, _set_rotation) 110 | rot = rotation 111 | 112 | def _set_scale(self, val): 113 | if isinstance(val, Scale): 114 | self._scale = val 115 | else: 116 | self._scale = Scale(*val) 117 | 118 | def _get_scale(self): 119 | return self._scale 120 | 121 | scale = AliasProperty(_get_scale, _set_scale) 122 | 123 | def on_pos_changed(self, coord, v): 124 | """ Some coordinate was changed """ 125 | self._translate.xyz = self._position 126 | 127 | def on_angle_change(self, axis, angle): 128 | self._rotors[axis].angle = angle 129 | 130 | def as_instructions(self): 131 | """ Get instructions set for renderer """ 132 | if not self._instructions.children: 133 | self._instructions.add(self._push_matrix) 134 | self._instructions.add(self._translate) 135 | self._instructions.add(self.scale) 136 | for rot in self._rotors.values(): 137 | self._instructions.add(rot) 138 | self._instructions.add(UpdateNormalMatrix()) 139 | for instr in self.custom_instructions(): 140 | self._instructions.add(instr) 141 | for child in self.get_children_instructions(): 142 | self._instructions.add(child) 143 | self._instructions.add(self._pop_matrix) 144 | return self._instructions 145 | 146 | def custom_instructions(self): 147 | """ Should be overriden in subclasses to provide some extra 148 | instructions 149 | """ 150 | return [] 151 | 152 | def get_children_instructions(self): 153 | for child in self.children: 154 | yield child.as_instructions() 155 | -------------------------------------------------------------------------------- /kivy3/default.glsl: -------------------------------------------------------------------------------- 1 | ---VERTEX SHADER------------------------------------------------------- 2 | #ifdef GL_ES 3 | precision highp float; 4 | #endif 5 | 6 | // inside VS, read-only 7 | attribute vec3 v_pos; 8 | attribute vec3 v_normal; 9 | attribute vec4 v_color; 10 | attribute vec2 v_tc0; 11 | 12 | // from python, read-only 13 | uniform mat4 modelview_mat; 14 | uniform mat4 projection_mat; 15 | uniform mat4 normal_mat; 16 | uniform mat4 model_mat; 17 | uniform mat4 view_mat; 18 | 19 | // used later in FS 20 | varying vec4 normal_vec; 21 | varying vec4 vertex_pos; 22 | varying vec4 frag_color; 23 | varying vec2 uv_vec; 24 | 25 | 26 | void main (void) { 27 | // fetch read-only for later use 28 | normal_vec = vec4(v_normal, 0.0); 29 | frag_color = v_color; 30 | uv_vec = v_tc0; 31 | 32 | vec4 pos = modelview_mat * vec4(v_pos, 1.0); 33 | vertex_pos = pos; 34 | 35 | // required shader clip-space output 36 | gl_Position = projection_mat * pos; 37 | } 38 | 39 | 40 | ---FRAGMENT SHADER----------------------------------------------------- 41 | #ifdef GL_ES 42 | precision highp float; 43 | #endif 44 | 45 | // from VS 46 | varying vec4 normal_vec; 47 | varying vec4 vertex_pos; 48 | varying vec4 frag_color; 49 | varying vec2 uv_vec; 50 | 51 | // from python, read-only 52 | uniform mat4 modelview_mat; 53 | uniform mat4 projection_mat; 54 | uniform mat4 normal_mat; 55 | uniform mat4 model_mat; 56 | uniform mat4 view_mat; 57 | 58 | uniform vec3 camera_pos; 59 | uniform vec3 Ka; // color (ambient) 60 | uniform vec3 Kd; // diffuse color 61 | uniform vec3 Ks; // specular color 62 | uniform float Tr; // transparency 63 | uniform float Ns; // shininess 64 | uniform float tex_ratio; 65 | 66 | uniform vec3 light_pos; 67 | uniform float light_intensity; 68 | 69 | uniform sampler2D tex; // texture 70 | 71 | 72 | void main (void){ 73 | // pull colors from texture 74 | vec4 tex_color = texture2D(tex, uv_vec); 75 | 76 | // force lightPos to lower-left (like in Kivy) 77 | vec4 lightPos = model_mat * vec4(light_pos, 0.0) - gl_FragCoord; 78 | float lightPosLen = length(lightPos); 79 | 80 | vec4 v_normal = normalize(normal_mat * normal_vec); 81 | vec4 vertex_world = modelview_mat * vertex_pos; 82 | vec4 v_light = vec4(light_pos, 1.0) - vertex_world; 83 | 84 | // set ambient, diffuse, specular color 85 | vec3 Ia = Ka * light_intensity / lightPosLen; 86 | vec3 Id = Kd * max(dot(v_light, v_normal), 0.0); 87 | vec3 Is = Ks * pow(max(dot(v_light, v_normal), 0.0), Ns); 88 | 89 | // modify texture color by light intensity 90 | tex_color = vec4( 91 | tex_color.rgb * light_intensity / lightPosLen, 92 | tex_color[3] 93 | ); 94 | 95 | // required shader output 96 | // window-space fragment color with texture 97 | gl_FragColor = vec4(Ia + Id + Is, Tr); 98 | gl_FragColor = mix(gl_FragColor, tex_color, tex_ratio); 99 | } 100 | -------------------------------------------------------------------------------- /kivy3/extras/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivy/kivy3/e3364b39ec61a69aa31bf88e77fadaa148359ec6/kivy3/extras/__init__.py -------------------------------------------------------------------------------- /kivy3/extras/geometries.py: -------------------------------------------------------------------------------- 1 | """ 2 | The MIT License (MIT) 3 | 4 | Copyright (c) 2013 Niko Skrypnik 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | """ 24 | from kivy3 import Vector3 25 | from kivy3.core.geometry import Geometry 26 | from kivy3.core.face3 import Face3 27 | 28 | import math 29 | 30 | 31 | def normalise_v3(vector): 32 | length= math.sqrt(vector[ 33 | 0]**2 + vector[1]**2 + vector[2]**2) 34 | new_vector = [x/length for x in vector] 35 | return new_vector 36 | 37 | class BoxGeometry(Geometry): 38 | 39 | _cube_vertices = [(-1, 1, -1), (1, 1, -1), 40 | (1, -1, -1), (-1, -1, -1), 41 | (-1, 1, 1), (1, 1, 1), 42 | (1, -1, 1), (-1, -1, 1), 43 | ] 44 | 45 | _cube_faces = [(0, 1, 2), (0, 2, 3), (3, 2, 6), 46 | (3, 6, 7), (7, 6, 5), (7, 5, 4), 47 | (4, 5, 1), (4, 1, 0), (4, 0, 3), 48 | (7, 4, 3), (5, 1, 2), (6, 5, 2) 49 | ] 50 | 51 | _cube_normals = [(0, 0, 1), (-1, 0, 0), (0, 0, -1), 52 | (1, 0, 0), (0, 1, 0), (0, -1, 0) 53 | ] 54 | 55 | def __init__(self, width, height, depth, **kw): 56 | name = kw.pop('name', '') 57 | super(BoxGeometry, self).__init__(name) 58 | self.width_segment = kw.pop('width_segment', 1) 59 | self.height_segment = kw.pop('height_segment', 1) 60 | self.depth_segment = kw.pop('depth_segment', 1) 61 | 62 | self.w = width 63 | self.h = height 64 | self.d = depth 65 | 66 | self._build_box() 67 | 68 | def _build_box(self): 69 | 70 | for v in self._cube_vertices: 71 | v = Vector3(0.5 * v[0] * self.w, 72 | 0.5 * v[1] * self.h, 73 | 0.5 * v[2] * self.d) 74 | self.vertices.append(v) 75 | 76 | n_idx = 0 77 | for f in self._cube_faces: 78 | face3 = Face3(*f) 79 | normal = self._cube_normals[int(n_idx / 2)] 80 | face3.vertex_normals = [normal, normal, normal] 81 | n_idx += 1 82 | self.faces.append(face3) 83 | 84 | class CylinderGeometry(Geometry): 85 | def __init__(self, radius, length, **kw): 86 | name = kw.pop('name', '') 87 | super(CylinderGeometry, self).__init__(name) 88 | self.circle_segment = kw.pop('circle_segment', 16) 89 | self.depth_segment = kw.pop('depth_segment', 1) 90 | 91 | self.rad = radius 92 | self.length = length 93 | 94 | self._build_cylinder() 95 | 96 | def _build_cylinder(self): 97 | 98 | _cylinder_vertices = [] 99 | top_vertices = [] 100 | bottom_vertices = [] 101 | cylinder_side_normals = [] 102 | _cylinder_normals = [] 103 | 104 | for i in range(self.circle_segment): 105 | x = math.cos(float(i) * (2.*math.pi)/float(self.circle_segment)) * 0.5 * float(self.rad) 106 | y = math.sin(float(i) * (2.*math.pi)/float(self.circle_segment)) * 0.5 * float(self.rad) 107 | 108 | n = Vector3(x,y,0) 109 | n.normalize() 110 | cylinder_side_normals.append(n) 111 | 112 | 113 | 114 | top_vertices.append((x,y,0.5 * float(self.length))) 115 | bottom_vertices.append((x,y,-0.5 * float(self.length))) 116 | 117 | _cylinder_vertices = top_vertices + bottom_vertices 118 | _cylinder_normals = cylinder_side_normals + cylinder_side_normals 119 | 120 | for f in range(1,self.circle_segment-1): 121 | # Top circle 122 | normal = Vector3(0,0,1) 123 | face = (0,f,f+1) 124 | face3 = Face3(*face) 125 | face3.vertex_normals=[normal,normal,normal] 126 | self.faces.append(face3) 127 | 128 | for f in range(self.circle_segment+1,(2*self.circle_segment)-1): 129 | # Top circle 130 | normal = Vector3(0,0,-1) 131 | face = (self.circle_segment,f,f+1) 132 | face3 = Face3(*face) 133 | face3.vertex_normals=[normal,normal,normal] 134 | self.faces.append(face3) 135 | 136 | 137 | for i in range(0,self.circle_segment): 138 | if i == (self.circle_segment-1): 139 | face = (i,0,i+self.circle_segment) 140 | else: 141 | face = (i,i+1,i+self.circle_segment) 142 | face3 = Face3(*face) 143 | face3.vertex_normals = [_cylinder_normals[i], _cylinder_normals[i+1], _cylinder_normals[i+self.circle_segment]] 144 | self.faces.append(face3) 145 | 146 | if i == (self.circle_segment-1): 147 | face = (0, i+self.circle_segment, self.circle_segment) 148 | face3=Face3(*face) 149 | face3.vertex_normals=(_cylinder_normals[i+1], _cylinder_normals[i+self.circle_segment], _cylinder_normals[self.circle_segment]) 150 | else: 151 | face = (i+1, i+self.circle_segment, i+self.circle_segment +1) 152 | 153 | face3=Face3(*face) 154 | face3.vertex_normals=(_cylinder_normals[i+1], _cylinder_normals[i+self.circle_segment], _cylinder_normals[i+self.circle_segment + 1]) 155 | self.faces.append(face3) 156 | 157 | 158 | self.vertices = _cylinder_vertices 159 | 160 | 161 | class SphereGeometry(Geometry): 162 | 163 | def __init__(self, radius=1, sectors=36, stacks=18, **kw): 164 | name = kw.pop('name', '') 165 | super(SphereGeometry, self).__init__(name) 166 | self.stacks = stacks 167 | self.sectors=sectors 168 | self.rad = radius 169 | 170 | self._build_sphere() 171 | 172 | def _build_sphere(self): 173 | #Create Vertices and normals 174 | _vertices = [] 175 | _normals = [] 176 | #Top vertex 177 | _vertices.append((0,0,1.*self.rad)) 178 | _normals.append((0,0,1)) 179 | 180 | # Generate the faces 181 | for i in range(1,self.stacks): 182 | theta_1 = float(i)*(math.pi/self.stacks) 183 | z = math.cos(theta_1) 184 | for j in range(self.sectors): 185 | theta_2 = float(j)*(2.*math.pi/self.sectors) 186 | x = math.sin(theta_1) * math.cos(theta_2) 187 | y = math.sin(theta_1) * math.sin(theta_2) 188 | 189 | vertex = (x*self.rad, y*self.rad, z*self.rad) 190 | _vertices.append(vertex) 191 | _normals.append((x,y,z)) 192 | 193 | # Bottom vertex 194 | _vertices.append((0,0,-1.*self.rad)) 195 | _normals.append((0,0,-1.)) 196 | 197 | # Generate the Faces with mapping to the vertices 198 | 199 | #Top one 200 | for i in range(1,self.sectors+1): 201 | 202 | a = 0 203 | b = i 204 | c = i+1 205 | if c == self.sectors+1: 206 | c = 1 207 | face3=Face3(a, b, c) 208 | face3.vertex_normals=[_normals[a],_normals[b],_normals[c]] 209 | self.faces.append(face3) 210 | 211 | #Stacks: 212 | for i in range(0, self.stacks-2): 213 | top_idx = (i*self.sectors +1, (i+1)*self.sectors+1) 214 | for j in range(top_idx[0],top_idx[1]): 215 | a = j 216 | b = j+1 217 | c = j+self.sectors 218 | if b == top_idx[1]: 219 | b = top_idx[0] 220 | face3=Face3(a, b, c) 221 | face3.vertex_normals = [_normals[a],_normals[b],_normals[c]] 222 | self.faces.append(face3) 223 | 224 | a = j+1 225 | b = j+self.sectors 226 | c = j+self.sectors +1 227 | if a == top_idx[1]: 228 | a = top_idx[0] 229 | if c == top_idx[1] + self.sectors: 230 | c = top_idx[1] 231 | 232 | face3=Face3(a, b, c) 233 | face3.vertex_normals = [_normals[a],_normals[b],_normals[c]] 234 | self.faces.append(face3) 235 | 236 | for i in range(len(_vertices)-1-self.sectors,len(_vertices)-1): 237 | 238 | a = len(_vertices)-1 239 | b = i 240 | c = i+1 241 | if c ==len(_vertices)-1: 242 | c = len(_vertices)-1-self.sectors 243 | face3=Face3(a, b, c) 244 | face3.vertex_normals=[_normals[a],_normals[b],_normals[c]] 245 | self.faces.append(face3) 246 | 247 | self.vertices = _vertices 248 | -------------------------------------------------------------------------------- /kivy3/light.py: -------------------------------------------------------------------------------- 1 | from kivy.core.window import Window 2 | from kivy.event import EventDispatcher 3 | from kivy.properties import ( 4 | NumericProperty, 5 | ReferenceListProperty 6 | ) 7 | 8 | # Map for light attributes to shader 9 | # uniform variables 10 | LIGHT_TO_SHADER_MAP = { 11 | "pos": "light_pos", 12 | "intensity": "light_intensity", 13 | } 14 | 15 | 16 | class LightError(Exception): 17 | pass 18 | 19 | 20 | class Light(EventDispatcher): 21 | 22 | # ensure floats everywhere, 23 | # otherwise it breaks stuff 24 | pos_x = NumericProperty(0.0) 25 | pos_y = NumericProperty(0.0) 26 | pos_z = NumericProperty(0.0) 27 | pos = ReferenceListProperty(pos_x, pos_y, pos_z) 28 | intensity = NumericProperty(1000.0) 29 | 30 | def __init__(self, renderer=None, intensity=None, 31 | pos=None, origin=None, **kwargs): 32 | if not renderer: 33 | raise LightError("Renderer is not defined!") 34 | super(Light, self).__init__(**kwargs) 35 | self.renderer = renderer 36 | self.on_pos(self, pos if pos else self.pos) 37 | self.on_intensity(self, intensity if intensity else self.intensity) 38 | 39 | def on_pos(self, instance, value): 40 | self._update_fbo( 41 | 'pos', 42 | (float(value[0]), 43 | float(value[1]), 44 | float(value[2])) 45 | ) 46 | 47 | def on_intensity(self, instance, value): 48 | self._update_fbo('intensity', float(value)) 49 | 50 | def _update_fbo(self, key, value): 51 | if key in LIGHT_TO_SHADER_MAP: 52 | uniform_var = LIGHT_TO_SHADER_MAP[key] 53 | self.renderer.fbo[uniform_var] = value 54 | -------------------------------------------------------------------------------- /kivy3/loaders/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | from .objloader import OBJLoader, OBJMTLLoader 3 | from .stlloader import STLLoader 4 | -------------------------------------------------------------------------------- /kivy3/loaders/empty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivy/kivy3/e3364b39ec61a69aa31bf88e77fadaa148359ec6/kivy3/loaders/empty.png -------------------------------------------------------------------------------- /kivy3/loaders/loader.py: -------------------------------------------------------------------------------- 1 | """ 2 | The MIT License (MIT) 3 | 4 | Copyright (c) 2013 Niko Skrypnik 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | """ 24 | 25 | """ 26 | Loader class 27 | ============= 28 | 29 | Base loader class which should be used by all other loaders implementations 30 | """ 31 | 32 | from kivy.clock import Clock 33 | 34 | 35 | class BaseLoader(object): 36 | 37 | def __init__(self, **kw): 38 | self._on_load_start = kw.pop("on_load_start", None) 39 | self._on_load_progress = kw.pop("on_load_progress", None) 40 | self._on_load_complete = kw.pop("on_load_complete", None) 41 | self.source = None 42 | 43 | def on_load_start(self): 44 | if callable(self._on_load_start): 45 | self._on_load_start() 46 | 47 | def on_load_progress(self): 48 | if callable(self._on_load_progress): 49 | self._on_load_progress() 50 | 51 | def on_load_complete(self): 52 | if callable(self._on_load_complete): 53 | self._on_load_complete() 54 | 55 | def __setattr__(self, k, v): 56 | if k in ["on_load_start", "on_load_progress", "on_load_complete"]: 57 | if not callable(v): 58 | raise Exception("%s should be callable" % k) 59 | setattr(self, "_%s" % k, v) 60 | else: 61 | super(BaseLoader, self).__setattr__(k, v) 62 | 63 | def load(self, source, on_load=None, on_progress=None, on_error=None): 64 | """This function loads objects from source. This function may work 65 | in both synchronous or asynchronous way. To make it asynchronous 66 | on_load callback function should be provided. 67 | """ 68 | self.source = source 69 | 70 | if not callable(on_load): 71 | return self.parse() 72 | 73 | def _async_load(dt): 74 | obj = self.parse() 75 | on_load(obj) 76 | 77 | Clock.schedule_once(_async_load, 0) 78 | 79 | def parse(self): 80 | """ This should be overridden in subclasses to provide 81 | parse of the source and return loaded from source object 82 | """ 83 | raise NotImplementedError('Must be overriden in subclass') 84 | -------------------------------------------------------------------------------- /kivy3/loaders/objloader.py: -------------------------------------------------------------------------------- 1 | """ 2 | The MIT License (MIT) 3 | 4 | Copyright (c) 2013 Niko Skrypnik 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | """ 24 | 25 | """ 26 | Loaders for Wavefront format .obj files 27 | ============= 28 | 29 | """ 30 | 31 | from .loader import BaseLoader 32 | from os.path import abspath, dirname, join, exists 33 | from kivy.core.image import Image 34 | from kivy.logger import Logger 35 | from kivy3 import Object3D, Mesh, Material, Vector2 36 | from kivy3.core.geometry import Geometry 37 | from kivy3.core.face3 import Face3 38 | 39 | folder = dirname(abspath(__file__)) 40 | 41 | 42 | class WaveObject(object): 43 | """ This class contains top level mesh object information like vertices, 44 | normals, texcoords and faces 45 | """ 46 | 47 | _mtl_map = {"Ka": "color", "Kd": "diffuse", "Ks": "specular", 48 | "Ns": "shininess", "Tr": "transparency", 49 | "d": "transparency", "map_Kd": "map" 50 | } 51 | 52 | def __init__(self, loader, name=''): 53 | self.name = name 54 | self.faces = [] 55 | self.loader = loader 56 | self.mtl_name = None 57 | 58 | def convert_to_mesh(self, vertex_format=None): 59 | """Converts data gotten from the .obj definition 60 | file and create Kivy3 Mesh object which may be used 61 | for drawing object in the scene 62 | """ 63 | 64 | geometry = Geometry() 65 | material = Material() 66 | mtl_dirname = abspath(dirname(self.loader.mtl_source)) 67 | 68 | v_idx = 0 69 | # create geometry for mesh 70 | for f in self.faces: 71 | verts = f[0] 72 | norms = f[1] 73 | tcs = f[2] 74 | face3 = Face3(0, 0, 0) 75 | for i, e in enumerate(['a', 'b', 'c']): 76 | # get normal components 77 | n = (0.0, 0.0, 0.0) 78 | if norms[i] != -1: 79 | n = self.loader.normals[norms[i] - 1] 80 | face3.vertex_normals.append(n) 81 | 82 | # get vertex components 83 | v = self.loader.vertices[verts[i] - 1] 84 | geometry.vertices.append(v) 85 | setattr(face3, e, v_idx) 86 | v_idx += 1 87 | 88 | # get texture coordinate components 89 | t = (0.0, 0.0) 90 | if tcs[i] != -1: 91 | t = self.loader.texcoords[tcs[i] - 1] 92 | tc = Vector2(t[0], 1. - t[1]) 93 | geometry.face_vertex_uvs[0].append(tc) 94 | 95 | geometry.faces.append(face3) 96 | 97 | # apply material for object 98 | if self.mtl_name in self.loader.mtl_contents: 99 | raw_material = self.loader.mtl_contents[self.mtl_name] 100 | # shader ignores values 101 | zeros = ['0', '0.0', '0.00', '0.000', '0.0000', 102 | '0.00000', '0.000000'] 103 | for k, v in raw_material.items(): 104 | _k = self._mtl_map.get(k, None) 105 | # TODO: also handle map_Ka and map_Ks 106 | if k in ["map_Kd", ]: 107 | # TODO: map file path may contains spaces. 108 | # current implementation fails. 109 | map_path = join(mtl_dirname, v[0]) 110 | if not exists(map_path): 111 | msg = u'WaveObject: Texture not found <{}>' 112 | Logger.warning(msg.format(map_path)) 113 | continue 114 | tex = Image(map_path).texture 115 | material.map = tex 116 | continue 117 | if _k: 118 | if len(v) == 1: 119 | v[0] = '0.000001' if v[0] in zeros else v[0] 120 | v = float(v[0]) 121 | if k == 'Tr': 122 | v = 1. - v 123 | setattr(material, _k, v) 124 | else: 125 | v = list(map(lambda x: float(x), v)) 126 | setattr(material, _k, v) 127 | 128 | if not material.map: 129 | material.map = Image(folder + '/empty.png').texture 130 | material.texture_ratio = 0.0 131 | mesh = Mesh(geometry, material) 132 | return mesh 133 | 134 | 135 | class OBJLoader(BaseLoader): 136 | 137 | def __init__(self, **kw): 138 | super(OBJLoader, self).__init__(**kw) 139 | self.mtl_source = None # source of MTL 140 | self.mtl_contents = {} # should be filled in load_mtl 141 | 142 | def load_mtl(self): 143 | if not exists(self.mtl_source): 144 | msg = u'OBJLoader: mtl file not found <{}>' 145 | Logger.warning(msg.format(self.mtl_source)) 146 | return 147 | for line in open(self.mtl_source, "r"): 148 | if line.startswith('#'): 149 | continue 150 | values = line.split() 151 | if not values: 152 | continue 153 | if values[0] == 'newmtl': 154 | mtl = self.mtl_contents[values[1]] = {} 155 | continue 156 | elif mtl is None: 157 | raise ValueError("mtl doesn't start with newmtl statement") 158 | mtl[values[0]] = values[1:] 159 | 160 | def _load_meshes(self): 161 | 162 | wvobj = WaveObject(self) 163 | self.vertices = [] 164 | self.normals = [] 165 | self.texcoords = [] 166 | faces_section = False 167 | 168 | for line in open(self.source, "r"): 169 | if line.startswith('#'): 170 | continue 171 | if line.startswith('s'): 172 | continue 173 | values = line.split() 174 | if not values: 175 | continue 176 | if values[0] == 'o' or values[0] == 'g': 177 | wvobj.name = values[1] 178 | elif values[0] == 'mtllib': 179 | if not self.mtl_source: 180 | _obj_dir = abspath(dirname(self.source)) 181 | self.mtl_source = join(_obj_dir, values[1]) 182 | self.load_mtl() 183 | elif values[0] == 'usemtl': 184 | wvobj.mtl_name = values[1] 185 | elif values[0] == 'v': 186 | if faces_section: 187 | # here we yield new mesh object 188 | faces_section = False 189 | yield wvobj 190 | wvobj = WaveObject(self) 191 | v = list(map(float, values[1:4])) 192 | if self.swapyz: 193 | v = v[0], v[2], v[1] 194 | self.vertices.append(v) 195 | elif values[0] == 'vn': 196 | v = list(map(float, values[1:4])) 197 | if self.swapyz: 198 | v = v[0], v[2], v[1] 199 | self.normals.append(v) 200 | elif values[0] == 'vt': 201 | self.texcoords.append(list(map(float, values[1:3]))) 202 | elif values[0] == 'f': 203 | if not faces_section: 204 | faces_section = True 205 | # face values 206 | f = values[1:] 207 | # triangle 208 | if len(f) == 3: 209 | fcs = [f] 210 | # square, convert into two triangles 211 | elif len(f) == 4: 212 | fcs = [ 213 | f[:3], 214 | [f[0], f[2], f[3]] 215 | ] 216 | for f in fcs: 217 | face = [] 218 | texcoords = [] 219 | norms = [] 220 | for v in f: 221 | w = v.split('/') 222 | face.append(int(w[0])) 223 | if len(w) >= 2 and len(w[1]) > 0: 224 | texcoords.append(int(w[1])) 225 | else: 226 | texcoords.append(-1) 227 | if len(w) >= 3 and len(w[2]) > 0: 228 | norms.append(int(w[2])) 229 | else: 230 | norms.append(-1) 231 | wvobj.faces.append((face, norms, texcoords)) 232 | yield wvobj 233 | 234 | def load(self, source, **kw): 235 | self.swapyz = kw.pop("swapyz", False) 236 | return super(OBJLoader, self).load(source, **kw) 237 | 238 | def parse(self): 239 | 240 | obj = Object3D() 241 | 242 | for wvobj in self._load_meshes(): 243 | obj.add(wvobj.convert_to_mesh()) 244 | 245 | return obj 246 | 247 | 248 | class OBJMTLLoader(OBJLoader): 249 | """ This subclass of Wafefront format files loader 250 | which allows to use custom MTL file, but not the one is 251 | defined in .obj file 252 | """ 253 | 254 | def load(self, source, mtl_source, **kw): 255 | self.mtl_source = mtl_source 256 | self.load_mtl() 257 | return super(OBJMTLLoader, self).load(source, **kw) 258 | -------------------------------------------------------------------------------- /kivy3/loaders/stlloader.py: -------------------------------------------------------------------------------- 1 | from .loader import BaseLoader 2 | from os.path import abspath, dirname, join, exists 3 | from kivy.core.image import Image 4 | from kivy.graphics import Mesh as KivyMesh 5 | from kivy.logger import Logger 6 | from kivy3 import Object3D, Mesh, Material, Vector2 7 | from kivy3.core.geometry import Geometry 8 | from kivy3.core.face3 import Face3 9 | import numpy as np 10 | from stl import mesh 11 | 12 | DEFAULT_VERTEX_FORMAT = [ 13 | (b'v_pos', 3, 'float'), 14 | (b'v_normal', 3, 'float'), 15 | (b'v_tc0', 2, 'float') 16 | ] 17 | DEFAULT_MESH_MODE = 'triangles' 18 | 19 | class STLMesh(Object3D): 20 | def __init__(self, v0, v1, v2, normals, material, **kw): 21 | super(STLMesh, self).__init__(**kw) 22 | self.vertex_format = kw.pop('vertex_format', DEFAULT_VERTEX_FORMAT) 23 | self.mesh_mode = kw.pop('mesh_mode', DEFAULT_MESH_MODE) 24 | self.material = material 25 | self.v0 = v0 26 | self.v1 = v1 27 | self.v2 = v2 28 | self.normals = normals 29 | indices = list(range(0,len(self.v0)*3)) 30 | uvs = np.zeros((len(self.v0), 2)).astype(np.float32) 31 | vertices = np.block([self.v0,self.normals,uvs,self.v1,self.normals,uvs,self.v2,self.normals,uvs]).flatten() 32 | 33 | kw=dict(vertices=vertices, 34 | indices=indices, 35 | fmt=self.vertex_format, 36 | mode=self.mesh_mode) 37 | 38 | if self.material.map: 39 | kw['texture'] = self.material.map 40 | self._mesh = KivyMesh(**kw) 41 | 42 | 43 | class STLObject(Object3D): 44 | def __init__(self, stl_mesh, material, **kw): 45 | super(STLObject, self).__init__(**kw) 46 | self.stl_mesh = stl_mesh 47 | self.material = material 48 | self.mtl = self.material # shortcut for material property 49 | 50 | self.create_mesh() 51 | 52 | def create_mesh(self): 53 | """ Create real mesh object from the geometry and material """ 54 | max_faces = 65530//3 55 | #geometries = [] 56 | start = 0 57 | 58 | while(True): 59 | _faces=[] 60 | _vertices = [] 61 | if (len(self.stl_mesh.v0)-start) >= max_faces: 62 | print("Faces are more than max") 63 | length = max_faces 64 | # 65 | # mesh = STLMesh(self.stl_mesh.v0[start:start+length], self.stl_mesh.v1[start:start+length], self.stl_mesh.v2[start:start+length], self.stl_mesh.normals[start:start+length], 66 | # self.material) 67 | # 68 | # self.add(mesh) 69 | _vertices = np.concatenate((self.stl_mesh.v0[start:start+length],self.stl_mesh.v1[start:start+length],self.stl_mesh.v2[start:start+length])) 70 | for i in range(length): 71 | 72 | f3 = Face3(i,i+length, i+ length*2) 73 | f3.vertex_normals = [self.stl_mesh.normals[start+i],self.stl_mesh.normals[start+i],self.stl_mesh.normals[start+i]] 74 | _faces.append(f3) 75 | 76 | 77 | 78 | geo = Geometry() 79 | geo.vertices = _vertices 80 | geo.faces = _faces 81 | mesh = Mesh(geo, self.material) 82 | self.add(mesh) 83 | start = start+length 84 | 85 | 86 | else: 87 | length = len(self.stl_mesh.v0)-start 88 | _vertices = np.concatenate((self.stl_mesh.v0[start:],self.stl_mesh.v1[start:],self.stl_mesh.v2[start:])) 89 | for i in range(length): 90 | f3 = Face3(i,i+length, i+ length*2) 91 | f3.vertex_normals = [self.stl_mesh.normals[i+start],self.stl_mesh.normals[i+start],self.stl_mesh.normals[i+start]] 92 | _faces.append(f3) 93 | geo = Geometry() 94 | geo.vertices = _vertices 95 | geo.faces = _faces 96 | #geometries.append(geo) 97 | mesh = Mesh(geo, self.material) 98 | self.add(mesh) 99 | 100 | # length = max_faces 101 | # 102 | # mesh = STLMesh(self.stl_mesh.v0[start:], self.stl_mesh.v1[start:], self.stl_mesh.v2[start:], self.stl_mesh.normals[start:], 103 | # self.material) 104 | # 105 | # self.add(mesh) 106 | break 107 | 108 | return self 109 | 110 | 111 | 112 | 113 | class STLLoader(BaseLoader): 114 | def __init__(self, **kw): 115 | super(STLLoader, self).__init__(**kw) 116 | 117 | def load(self, source, material, **kw): 118 | self.material = material 119 | return super(STLLoader, self).load(source, **kw) 120 | 121 | 122 | def parse(self): 123 | 124 | stl = mesh.Mesh.from_file(self.source) 125 | 126 | 127 | 128 | stl_object = STLObject(stl,self.material) 129 | 130 | 131 | 132 | return stl_object 133 | -------------------------------------------------------------------------------- /kivy3/materials.py: -------------------------------------------------------------------------------- 1 | """ 2 | The MIT License (MIT) 3 | 4 | Copyright (c) 2013 Niko Skrypnik 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | """ 24 | 25 | from kivy.graphics import ChangeState 26 | 27 | # Map for material attributes to shader 28 | # uniform variables 29 | MATERIAL_TO_SHADER_MAP = { 30 | "color": "Ka", 31 | "transparency": "Tr", 32 | "diffuse": "Kd", 33 | "specular": "Ks", 34 | "shininess": "Ns", # specular coefficient 35 | "texture_ratio": "tex_ratio" 36 | } 37 | 38 | 39 | def set_attribute_to_uniform(attr_name, uniform_var): 40 | MATERIAL_TO_SHADER_MAP[attr_name] = uniform_var 41 | 42 | 43 | class Material(ChangeState): 44 | 45 | def __init__(self, map=None, transparency=1.0, color=(1, 1, 1), 46 | diffuse=(0, 0, 0), specular=(0, 0, 0), 47 | shininess=10.0, texture_ratio=0.0, **kwargs): 48 | self.map = map 49 | super(Material, self).__init__() 50 | transparency = float(transparency) 51 | color = tuple(float(c) for c in color) 52 | diffuse = tuple(float(d) for d in diffuse) 53 | specular = tuple(float(s) for s in specular) 54 | shininess = float(shininess) 55 | texture_ratio = float(texture_ratio) 56 | 57 | # set attribute from locals 58 | for k, v in list(locals().items()): 59 | setattr(self, k, v) 60 | 61 | def __setattr__(self, k, v): 62 | if k in MATERIAL_TO_SHADER_MAP: 63 | uniform_var = MATERIAL_TO_SHADER_MAP[k] 64 | self.changes[uniform_var] = v 65 | else: 66 | if k == 'map' and v: 67 | self.changes['tex_ratio'] = 1.0 68 | if type(v) in [float, int, str, list]: 69 | self.changes[k] = v 70 | super(Material, self).__setattr__(k, v) 71 | -------------------------------------------------------------------------------- /kivy3/math/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivy/kivy3/e3364b39ec61a69aa31bf88e77fadaa148359ec6/kivy3/math/__init__.py -------------------------------------------------------------------------------- /kivy3/math/vectors.py: -------------------------------------------------------------------------------- 1 | """ 2 | The MIT License (MIT) 3 | 4 | Copyright (c) 2013 Niko Skrypnik 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | """ 24 | 25 | __all__ = ('Vector2', 'Vector3', 'Vector4', ) 26 | 27 | import math 28 | 29 | from copy import copy 30 | 31 | 32 | class BaseVector(list): 33 | """ 34 | BaseVector is actually 4D vector for optimization 35 | """ 36 | 37 | _d = 4 # dimension size 38 | _indeces = [0, 1, 2, 3] 39 | _null = [0, 0, 0, 0] 40 | _coords = {'x': 0, 'y': 1, 'z': 2, 'v': 3} 41 | 42 | def __init__(self, *largs): 43 | if len(largs) == 1: 44 | if len(largs[0]) == self._d: 45 | super(BaseVector, self).__init__(largs[0]) 46 | else: 47 | raise Exception('Invalid vector') 48 | else: 49 | if len(largs) == self._d: 50 | super(BaseVector, self).__init__(largs) 51 | else: 52 | raise Exception('Invalid vector') 53 | self._change_cb = None 54 | 55 | def set_change_cb(self, cb): 56 | self._change_cb = cb 57 | 58 | def set_vector(self, v): 59 | for i in self._indeces: 60 | self[i] = v[i] 61 | 62 | def __add__(self, other): 63 | res = copy(self._null) 64 | 65 | if isinstance(other, BaseVector): 66 | for i in self._indeces: 67 | res[i] = self[i] + other[i] 68 | else: 69 | for i in self._indeces: 70 | res[i] = self[i] + other 71 | return self.__class__(res) 72 | 73 | def add(self, other): 74 | self.set_vector(self + other) 75 | 76 | @classmethod 77 | def add_vectors(cls, first, second): 78 | return first + second 79 | 80 | def __sub__(self, other): 81 | res = copy(self._null) 82 | if isinstance(other, BaseVector): 83 | for i in self._indeces: 84 | res[i] = self[i] - other[i] 85 | else: 86 | for i in self._indeces: 87 | res[i] = self[i] - other 88 | return self.__class__(res) 89 | 90 | def sub(self, other): 91 | self.set_vector(self - other) 92 | 93 | @classmethod 94 | def sub_vectors(cls, first, second): 95 | return first - second 96 | 97 | def __mul__(self, other): 98 | res = copy(self._null) 99 | if isinstance(other, BaseVector): 100 | for i in self._indeces: 101 | res[i] = self[i] * float(other[i]) 102 | else: 103 | for i in self._indeces: 104 | res[i] = self[i] * float(other) 105 | return self.__class__(res) 106 | 107 | def multiply(self, other): 108 | self.set_vector(self * other) 109 | 110 | @classmethod 111 | def multiply_vectors(cls, first, second): 112 | return first * second 113 | 114 | def __div__(self, other): 115 | res = copy(self._null) 116 | if isinstance(other, BaseVector): 117 | for i in self._indeces: 118 | res[i] = self[i] / float(other[i]) 119 | else: 120 | for i in self._indeces: 121 | res[i] = self[i] / float(other) 122 | return self.__class__(res) 123 | 124 | def divide(self, other): 125 | self.set_vector(self / other) 126 | 127 | @classmethod 128 | def divide_vectors(cls, first, second): 129 | return first / second 130 | 131 | def min(self, v): 132 | for i in self._indeces: 133 | if v[i] < self[i]: 134 | self[i] = v[i] 135 | 136 | def max(self, v): 137 | for i in self._indeces: 138 | if v[i] > self[i]: 139 | self[i] = v[i] 140 | 141 | def clamp(self, vmin, vmax): 142 | """ This function assumes min < max, if this assumption isn't true 143 | it will not operate correctly 144 | """ 145 | for i in self._indeces: 146 | if self[i] < vmin[i]: 147 | self[i] = vmin[i] 148 | elif self[i] > vmax[i]: 149 | self[i] = vmax[i] 150 | 151 | def negate(self): 152 | self.set_vector(self * -1) 153 | 154 | def dot(self, v): 155 | dot = 0 156 | for i in self._indeces: 157 | dot += v[i] * self[i] 158 | return dot 159 | 160 | def length_sq(self): 161 | length_sq = 0 162 | for i in self._indeces: 163 | length_sq += self[i] * self[i] 164 | return length_sq 165 | 166 | def length(self): 167 | return math.sqrt(self.length_sq()) 168 | 169 | def length_manhattan(self): 170 | res = 0 171 | for i in self._indeces: 172 | res += math.fabs(self[i]) 173 | return res 174 | 175 | def normalize(self): 176 | self[:] = [x/self.length() for x in self] 177 | return self 178 | 179 | def lerp(self, v, alpha): 180 | for i in self._indeces: 181 | self[i] += (v[i] - self[i]) * alpha 182 | 183 | return self 184 | 185 | def clamp_scalar(self, n, min, max): 186 | if n < min: 187 | return min 188 | if n > max: 189 | return max 190 | return n 191 | 192 | def angle(self, v): 193 | theta = self.dot(v) / (self.length() * v.length()) 194 | 195 | return math.acos(self.clamp_scalar(theta, -1, 1)) 196 | 197 | angle_to = angle # alias for three.js back capability 198 | 199 | def distance(self, v): 200 | d = self - v 201 | return d.length() 202 | 203 | distance_to = distance 204 | 205 | def distance_to_squared(self, v): 206 | d = self - v 207 | return d.length_sq() 208 | 209 | def __getattr__(self, k): 210 | if k in self._coords: 211 | return self[self._coords[k]] 212 | else: 213 | raise AttributeError 214 | 215 | def __setattr__(self, k, v): 216 | if k in self._coords: 217 | if type(v) == int or type(v) == float: 218 | self[self._coords[k]] = v 219 | if self._change_cb: 220 | self._change_cb(k, v) 221 | super(BaseVector, self).__setattr__(k, v) 222 | 223 | 224 | class Vector4(BaseVector): 225 | pass 226 | 227 | 228 | class Vector3(BaseVector): 229 | _d = 3 230 | _indeces = [0, 1, 2] 231 | _null = [0, 0, 0] 232 | _coords = {'x': 0, 'y': 1, 'z': 2} 233 | 234 | def cross(self, v): 235 | t = copy(self) 236 | 237 | self[0] = t[1] * v[2] - t[2] * v[1] 238 | self[1] = t[2] * v[0] - t[0] * v[2] 239 | self[2] = t[0] * v[1] - t[1] * v[0] 240 | 241 | @classmethod 242 | def cross_vectors(cls): 243 | pass 244 | 245 | 246 | 247 | class Vector2(BaseVector): 248 | _d = 2 249 | _indeces = [0, 1] 250 | _null = [0, 0] 251 | _coords = {'x': 0, 'y': 1} 252 | -------------------------------------------------------------------------------- /kivy3/objects/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivy/kivy3/e3364b39ec61a69aa31bf88e77fadaa148359ec6/kivy3/objects/__init__.py -------------------------------------------------------------------------------- /kivy3/objects/mesh.py: -------------------------------------------------------------------------------- 1 | """ 2 | The MIT License (MIT) 3 | 4 | Copyright (c) 2013 Niko Skrypnik 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | """ 24 | 25 | from kivy.graphics import Mesh as KivyMesh 26 | from kivy3 import Vector3 27 | from kivy3.core.object3d import Object3D 28 | 29 | DEFAULT_VERTEX_FORMAT = [ 30 | (b'v_pos', 3, 'float'), 31 | (b'v_normal', 3, 'float'), 32 | (b'v_tc0', 2, 'float') 33 | ] 34 | DEFAULT_MESH_MODE = 'triangles' 35 | 36 | 37 | class Mesh(Object3D): 38 | 39 | def __init__(self, geometry, material, **kw): 40 | super(Mesh, self).__init__(**kw) 41 | self.geometry = geometry 42 | self.material = material 43 | self.mtl = self.material # shortcut for material property 44 | self.vertex_format = kw.pop('vertex_format', DEFAULT_VERTEX_FORMAT) 45 | self.mesh_mode = kw.pop('mesh_mode', DEFAULT_MESH_MODE) 46 | self.create_mesh() 47 | 48 | def create_mesh(self): 49 | """ Create real mesh object from the geometry and material """ 50 | vertices = [] 51 | indices = [] 52 | idx = 0 53 | for face in self.geometry.faces: 54 | for i, k in enumerate(['a', 'b', 'c']): 55 | v_idx = getattr(face, k) 56 | vertex = self.geometry.vertices[v_idx] 57 | vertices.extend(vertex) 58 | try: 59 | normal = face.vertex_normals[i] 60 | except IndexError: 61 | normal = Vector3([0, 0, 0]) 62 | vertices.extend(normal) 63 | try: 64 | tex_coords = self.geometry.face_vertex_uvs[0][idx] 65 | vertices.extend(tex_coords) 66 | except IndexError: 67 | vertices.extend([0, 0]) 68 | indices.append(idx) 69 | idx += 1 70 | if idx >= 65535 - 1: 71 | msg = 'Mesh must not contain more than 65535 indices, {} given' 72 | raise ValueError(msg.format(idx + 1)) 73 | kw = dict( 74 | vertices=vertices, 75 | indices=indices, 76 | fmt=self.vertex_format, 77 | mode=self.mesh_mode 78 | ) 79 | if self.material.map: 80 | kw['texture'] = self.material.map 81 | self._mesh = KivyMesh(**kw) 82 | 83 | def custom_instructions(self): 84 | yield self.material 85 | yield self._mesh 86 | -------------------------------------------------------------------------------- /kivy3/renderer.py: -------------------------------------------------------------------------------- 1 | 2 | """ 3 | The MIT License (MIT) 4 | 5 | Copyright (c) 2013 Niko Skrypnik 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in 15 | all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | THE SOFTWARE. 24 | """ 25 | 26 | """ 27 | Renderer class 28 | ============= 29 | 30 | Unlike of THREE.js we may provide only one renderer which is the 31 | Kivy widget and uses Kivy canvas and FBO concept for drawing graphics. 32 | You may use this class as usual widget and place it wherever you need 33 | in your application 34 | """ 35 | 36 | import os 37 | import kivy3 38 | 39 | 40 | from kivy.uix.widget import Widget 41 | from kivy.clock import Clock 42 | from kivy.graphics.fbo import Fbo 43 | from kivy.core.window import Window 44 | from kivy.graphics.instructions import InstructionGroup 45 | from kivy.graphics.opengl import glEnable, glDisable, GL_DEPTH_TEST 46 | from kivy.graphics.transformation import Matrix 47 | from kivy.graphics import ( 48 | Callback, PushMatrix, PopMatrix, 49 | Rectangle, Canvas, UpdateNormalMatrix 50 | ) 51 | 52 | from .light import Light 53 | kivy3_path = os.path.abspath(os.path.dirname(kivy3.__file__)) 54 | 55 | 56 | class RendererError(Exception): 57 | pass 58 | 59 | 60 | class Renderer(Widget): 61 | 62 | def __init__(self, **kw): 63 | self.shader_file = kw.pop("shader_file", None) 64 | self.canvas = Canvas() 65 | super(Renderer, self).__init__(**kw) 66 | 67 | with self.canvas: 68 | self._viewport = Rectangle(size=self.size, pos=self.pos) 69 | self.fbo = Fbo(size=self.size, 70 | with_depthbuffer=True, compute_normal_mat=True, 71 | clear_color=(0., 0., 0., 0.)) 72 | self._config_fbo() 73 | self.texture = self.fbo.texture 74 | self.camera = None 75 | self.scene = None 76 | self.main_light = Light(renderer=self) 77 | 78 | def _config_fbo(self): 79 | # set shader file here 80 | self.fbo.shader.source = self.shader_file or \ 81 | os.path.join(kivy3_path, "default.glsl") 82 | with self.fbo: 83 | Callback(self._setup_gl_context) 84 | PushMatrix() 85 | # instructions set for all instructions 86 | self._instructions = InstructionGroup() 87 | PopMatrix() 88 | Callback(self._reset_gl_context) 89 | 90 | def _setup_gl_context(self, *args): 91 | glEnable(GL_DEPTH_TEST) 92 | self.fbo.clear_buffer() 93 | 94 | def _reset_gl_context(self, *args): 95 | glDisable(GL_DEPTH_TEST) 96 | 97 | def render(self, scene, camera): 98 | self.scene = scene 99 | self.camera = camera 100 | self.camera.bind_to(self) 101 | self._instructions.add(scene.as_instructions()) 102 | Clock.schedule_once(self._update_matrices, -1) 103 | 104 | def on_size(self, instance, value): 105 | self.fbo.size = value 106 | self._viewport.texture = self.fbo.texture 107 | self._viewport.size = value 108 | self._viewport.pos = self.pos 109 | self._update_matrices() 110 | 111 | def on_pos(self, instance, value): 112 | self._viewport.pos = self.pos 113 | self._update_matrices() 114 | 115 | def on_texture(self, instance, value): 116 | self._viewport.texture = value 117 | 118 | def _update_matrices(self, dt=None): 119 | if self.camera: 120 | self.fbo['projection_mat'] = self.camera.projection_matrix 121 | self.fbo['modelview_mat'] = self.camera.modelview_matrix 122 | self.fbo['model_mat'] = self.camera.model_matrix 123 | self.fbo['camera_pos'] = [float(p) for p in self.camera.position] 124 | self.fbo['view_mat'] = Matrix().rotate( 125 | Window.rotation, 0.0, 0.0, 1.0) 126 | else: 127 | raise RendererError("Camera is not defined for renderer") 128 | 129 | def set_clear_color(self, color): 130 | self.fbo.clear_color = color 131 | -------------------------------------------------------------------------------- /kivy3/scenes/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivy/kivy3/e3364b39ec61a69aa31bf88e77fadaa148359ec6/kivy3/scenes/__init__.py -------------------------------------------------------------------------------- /kivy3/scenes/scene.py: -------------------------------------------------------------------------------- 1 | 2 | """ 3 | The MIT License (MIT) 4 | 5 | Copyright (c) 2013 Niko Skrypnik 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in 15 | all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | THE SOFTWARE. 24 | """ 25 | 26 | from kivy.graphics import Callback, UpdateNormalMatrix 27 | from kivy.graphics.opengl import glEnable, glDisable, GL_DEPTH_TEST 28 | from kivy3.core.object3d import Object3D 29 | 30 | 31 | class Scene(Object3D): 32 | """ Scene object """ 33 | 34 | def as_instructions(self): 35 | if not self._instructions.children: 36 | for child in self.get_children_instructions(): 37 | self._instructions.add(child) 38 | return self._instructions 39 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from setuptools import find_packages, setup 4 | from os.path import join, dirname 5 | from os import walk 6 | 7 | examples = {} 8 | for root, subFolders, files in walk('examples'): 9 | for fn in files: 10 | ext = fn.split('.')[-1].lower() 11 | filename = join(root, fn) 12 | directory = '%s%s' % ('share/kivy3-', dirname(filename)) 13 | if directory not in examples: 14 | examples[directory] = [] 15 | examples[directory].append(filename) 16 | 17 | setup( 18 | name='kivy3', 19 | version='0.1', 20 | description='Kivy extensions for 3D graphics', 21 | author='Niko Skrypnik', 22 | author_email='nskrypnik@gmail.com', 23 | include_package_data=True, 24 | packages=find_packages(exclude=("tests",)), 25 | data_files=list(examples.items()), 26 | requires=['kivy', ] 27 | ) 28 | -------------------------------------------------------------------------------- /test.py: -------------------------------------------------------------------------------- 1 | print("Hello World") 2 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivy/kivy3/e3364b39ec61a69aa31bf88e77fadaa148359ec6/tests/__init__.py -------------------------------------------------------------------------------- /tests/core/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivy/kivy3/e3364b39ec61a69aa31bf88e77fadaa148359ec6/tests/core/__init__.py -------------------------------------------------------------------------------- /tests/core/test_object3d.py: -------------------------------------------------------------------------------- 1 | 2 | import unittest 3 | from kivy3 import Object3D 4 | from tests.utils import Sandbox 5 | 6 | 7 | class DummyObject: 8 | pass 9 | 10 | 11 | class Object3DTest(unittest.TestCase): 12 | 13 | def setUp(self): 14 | self.sandbox = Sandbox() 15 | self.obj = Object3D() 16 | 17 | def tearDown(self): 18 | self.sandbox.restore() 19 | 20 | def test_position(self): 21 | obj = self.obj 22 | obj.pos.x = 10 23 | self.assertEqual(obj._position[0], 10) 24 | obj.position.y = 8 25 | self.assertEqual(obj._position[1], 8) 26 | obj.pos.z = 3 27 | self.assertEqual(obj._position[2], 3) 28 | 29 | def test_add_objects(self): 30 | obj = self.obj 31 | self.sandbox.stub(obj, '_add_child') 32 | 33 | obj.add(DummyObject(), DummyObject(), DummyObject()) 34 | self.assertEqual(obj._add_child.call_count, 3) 35 | 36 | def test_add_child(self): 37 | obj = self.obj 38 | child = DummyObject() 39 | obj._add_child(child) 40 | self.assertEqual(child.parent, obj) 41 | self.assertEqual(len(obj.children), 1) 42 | 43 | 44 | if __name__ == "__main__": 45 | unittest.main() 46 | -------------------------------------------------------------------------------- /tests/loaders/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivy/kivy3/e3364b39ec61a69aa31bf88e77fadaa148359ec6/tests/loaders/__init__.py -------------------------------------------------------------------------------- /tests/loaders/test_loader.py: -------------------------------------------------------------------------------- 1 | 2 | import os 3 | import unittest 4 | from kivy3.loaders.loader import BaseLoader 5 | from tests.utils import Spy, Sandbox 6 | from kivy.clock import Clock 7 | 8 | 9 | this_dir = os.path.abspath(os.path.dirname(__file__)) 10 | 11 | 12 | class BaseLoadertestCase(unittest.TestCase): 13 | 14 | def setUp(self): 15 | self.loader = BaseLoader() 16 | self.sandbox = Sandbox() 17 | 18 | def tearDown(self): 19 | self.sandbox.restore() 20 | 21 | def test_load_when_no_on_load(self): 22 | loader = self.loader 23 | loader.parse = Spy() 24 | loader.load('somefile') 25 | self.assertTrue(loader.parse.is_called()) 26 | 27 | def test_on_load_called(self): 28 | loader = self.loader 29 | loader.parse = Spy() 30 | _on_load = Spy() 31 | # mock Clock.schedule_once 32 | self.sandbox.stub(Clock, 'schedule_once', call_fake=lambda x, t: x(0)) 33 | loader.load('somesource', on_load=_on_load) 34 | self.assertTrue( 35 | _on_load.is_called(), 36 | 'on_load callback should be called' 37 | ) 38 | 39 | 40 | if __name__ == '__main__': 41 | unittest.main() 42 | -------------------------------------------------------------------------------- /tests/loaders/test_objloader.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from kivy3.loaders import OBJLoader 3 | 4 | 5 | class OBJLoaderTest(unittest.TestCase): 6 | pass 7 | 8 | 9 | if __name__ == '__main__': 10 | unittest.main() 11 | -------------------------------------------------------------------------------- /tests/test_materials.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from utils import Sandbox 3 | from kivy3 import Material 4 | 5 | 6 | class MaterialTest(unittest.TestCase): 7 | 8 | def setUp(self): 9 | self.sandbox = Sandbox() 10 | self.mat = Material() 11 | 12 | def tearDown(self): 13 | self.sandbox.restore() 14 | 15 | def test_setattr(self): 16 | self.mat.color = (0., 0., 0.) 17 | self.assertEquals(self.mat.changes['Ka'], (0., 0., 0.)) 18 | self.mat.shininess = 5 19 | self.assertEquals(self.mat.changes['Ns'], 5.) 20 | 21 | 22 | if __name__ == '__main__': 23 | unittest.main() 24 | -------------------------------------------------------------------------------- /tests/test_vectors.py: -------------------------------------------------------------------------------- 1 | 2 | import unittest 3 | import math 4 | 5 | from kivy3 import Vector3, Vector4, Vector2 6 | 7 | # good values for vector 3, 4, 12, 84 8 | 9 | 10 | class Vector3Test(unittest.TestCase): 11 | 12 | def test_create(self): 13 | v = Vector3(1, 2, 3) 14 | self.assertEquals(v[0], 1) 15 | self.assertEquals(v[1], 2) 16 | self.assertEquals(v[2], 3) 17 | v = Vector3([4, 5, 6]) 18 | self.assertEquals(v[0], 4) 19 | self.assertEquals(v[1], 5) 20 | self.assertEquals(v[2], 6) 21 | try: 22 | Vector3(1, 2, 3, 4) 23 | assert False, "This shold not reached" 24 | except: 25 | pass 26 | try: 27 | Vector3([3, 4, 2, 1]) 28 | assert False, "This shold not reached" 29 | except: 30 | pass 31 | 32 | def test_add(self): 33 | v1 = Vector3(1, 2, 3) 34 | v2 = Vector3(4, 5, 6) 35 | v = v1 + v2 36 | self.assertEqual(v, [5, 7, 9]) 37 | v1.add(v2) 38 | self.assertEqual(v1, [5, 7, 9]) 39 | self.assertEqual(v + 2, [7, 9, 11]) 40 | 41 | def test_sub(self): 42 | v1 = Vector3(4, 5, 6) 43 | v2 = Vector3(1, 2, 3) 44 | v = v1 - v2 45 | self.assertEqual(v, [3, 3, 3]) 46 | v1.sub(v2) 47 | self.assertEqual(v1, [3, 3, 3]) 48 | self.assertEqual(v - 3, [0, 0, 0]) 49 | 50 | def test_multiply(self): 51 | v1 = Vector3(5, 6, 7) 52 | v2 = Vector3(2, 2, 2) 53 | self.assertEqual(v1 * v2, [10., 12., 14.]) 54 | v1.multiply(v2) 55 | self.assertEqual(v1, [10., 12., 14.]) 56 | 57 | def test_divide(self): 58 | v1 = Vector3(6, 4, 8) 59 | v2 = Vector3(2, 2, 2) 60 | self.assertEqual(v1 / v2, [3., 2., 4.]) 61 | v1.divide(v2) 62 | self.assertEqual(v1, [3., 2., 4.]) 63 | 64 | def test_minmax(self): 65 | v = Vector3(6, 7, 4) 66 | v1 = Vector3(3, 5, 8) 67 | v.min(v1) 68 | self.assertEqual(v, [3, 5, 4]) 69 | v2 = Vector3(1, 7, 6) 70 | v.max(v2) 71 | self.assertEqual(v, [3, 7, 6]) 72 | 73 | def test_clamp(self): 74 | v1 = Vector3(1, 2, 3) 75 | v2 = Vector3(3, 4, 6) 76 | v = Vector3(0, 5, 4) 77 | v.clamp(v1, v2) 78 | self.assertEqual(v, [1, 4, 4]) 79 | 80 | def test_negate(self): 81 | v = Vector3(2, 2, 2) 82 | v.negate() 83 | self.assertEqual(v, [-2, -2, -2]) 84 | 85 | def test_length(self): 86 | v = Vector3(3, 12, 4) 87 | v = Vector3(12, 4, 3) 88 | 89 | self.assertEqual(v.length(), 13) 90 | self.assertEqual(v.length_sq(), 13 * 13) 91 | 92 | def test_angle(self): 93 | v1 = Vector3(0, 0, 1) 94 | v2 = Vector3(0, 1, 0) 95 | angle = v1.angle(v2) 96 | self.assertEqual(math.degrees(angle), 90.0) 97 | v1 = Vector3(0, 0, 1) 98 | v2 = Vector3(0, 0, -1) 99 | angle = v1.angle(v2) 100 | self.assertEqual(math.degrees(angle), 180.0) 101 | 102 | def test_distance(self): 103 | v1 = Vector3(2, 1, 6) 104 | v2 = Vector3(2, 5, 6) 105 | 106 | self.assertEqual(v1.distance(v2), 4) 107 | 108 | def test_attributes(self): 109 | v = Vector3(0, 0, 0) 110 | v.x = 4 111 | self.assertEqual(v[0], v.x) 112 | self.assertEqual(v[0], 4) 113 | 114 | v.z = 6 115 | self.assertEqual(v[2], v.z) 116 | self.assertEqual(v[2], 6) 117 | 118 | try: 119 | t = v.v 120 | assert False, "executing of this string is error" 121 | except AttributeError: 122 | pass 123 | 124 | 125 | class Vector2Test(unittest.TestCase): 126 | 127 | def test_create(self): 128 | v = Vector2(1, 2) 129 | try: 130 | v = Vector2(1, 2, 3) 131 | assert False, "This should not be normally reached" 132 | except: 133 | pass # test is passed normally 134 | 135 | def test_attrbutes(self): 136 | v = Vector2(0, 0) 137 | v.x = 4 138 | self.assertEqual(v[0], v.x) 139 | self.assertEqual(v[0], 4) 140 | 141 | v.y = 7 142 | self.assertEqual(v[1], v.y) 143 | self.assertEqual(v[1], 7) 144 | 145 | try: 146 | t = v.z 147 | assert False, "executing of this string is error" 148 | except AttributeError: 149 | pass 150 | 151 | 152 | if __name__ == '__main__': 153 | unittest.main() 154 | -------------------------------------------------------------------------------- /tests/utils.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Module provides some test utilities 3 | ''' 4 | 5 | 6 | class Spy: 7 | ''' 8 | This is the test helper which helps us to check whether function has been 9 | called and which parameters have been passed to 10 | ''' 11 | def __init__(self, call_fake=None, returns=None): 12 | self.call_count = 0 13 | self.args = [] 14 | self.call_fake = call_fake 15 | self.returns = returns 16 | 17 | def __call__(self, *args, **kwargs): 18 | self.args.append((args, kwargs)) 19 | self.call_count += 1 20 | if callable(self.call_fake): 21 | return self.call_fake(*args, **kwargs) 22 | else: 23 | if self.returns: 24 | return self.returns 25 | 26 | def is_called(self): 27 | return self.call_count > 0 28 | 29 | 30 | class Sandbox: 31 | ''' 32 | This little sucker helps us to mock some modules and functions and then 33 | restore it 34 | ''' 35 | 36 | def __init__(self): 37 | 'Constructor' 38 | self._storage = {} 39 | 40 | def stub(self, obj, func_name, **kw): 41 | if not callable(getattr(obj, func_name)): 42 | raise Exception('You may stub only callable objects') 43 | # save previous value of stubbed function 44 | if obj not in self._storage: 45 | obj_storage = {} 46 | self._storage[obj] = obj_storage 47 | else: 48 | obj_storage = self._storage[obj] 49 | 50 | if func_name in obj_storage: 51 | raise Exception('%s function has been already stubbed' % func_name) 52 | # store function into sandbox storage 53 | obj_storage[func_name] = getattr(obj, func_name) 54 | 55 | setattr(obj, func_name, Spy(**kw)) 56 | 57 | def restore(self): 58 | if not hasattr(self, '_storage'): 59 | return 60 | 61 | for obj, obj_storage in self._storage.iteritems(): 62 | keys_to_del = [] 63 | for key, original_value in obj_storage.iteritems(): 64 | # restore all original value to an object 65 | setattr(obj, key, original_value) 66 | keys_to_del.append(key) 67 | del self._storage 68 | 69 | def __del__(self): 70 | 'When we destruct object don\'t forget to restore all values' 71 | self.restore() 72 | --------------------------------------------------------------------------------