Welcome!
This is the community forum for my apps Pythonista and Editorial.
For individual support questions, you can also send an email. If you have a very short question or just want to say hello — I'm @olemoritz on Twitter.
Python OpenGLES
-
I know there are already ports of the OpenGLES framework however I plan to make a binding which is specifically for the Pythonista 1.6+ builds
Project is here.
If anyone is interested in helping that would be great.
Currently I have an issue in the generation of glGenRenderbuffer. (I have already created a post however it was not transferred over to the new forum.) -
Quite honestly, I don't fully understand your code, and my experience with OpenGL is somewhat limited/outdated. But I've done some experimentation with GLKit myself, so the following code may still be helpful to some degree. It's basically the minimal setup for using
GLKViewController
. The demo just draws a single color that changes over time. Note that you'll need the latest beta for this (build 160023 from earlier today).from objc_util import * import time import colorsys GLKView = ObjCClass('GLKView') GLKViewController = ObjCClass('GLKViewController') UINavigationController = ObjCClass('UINavigationController') UIBarButtonItem = ObjCClass('UIBarButtonItem') EAGLContext = ObjCClass('EAGLContext') glClearColor = c.glClearColor glClearColor.restype = None glClearColor.argtypes = [c_float, c_float, c_float, c_float] glClear = c.glClear glClear.restype = None glClear.argtypes = [c_uint] GL_COLOR_BUFFER_BIT = 0x00004000 def glkView_drawInRect_(_self, _cmd, view, rect): r, g, b = colorsys.hsv_to_rgb((time.time() * 0.1) % 1.0, 1, 1) glClearColor(r, g, b, 1.0) glClear(GL_COLOR_BUFFER_BIT) MyGLViewDelegate = create_objc_class('MyGLViewDelegate', methods=[glkView_drawInRect_], protocols=['GLKViewDelegate']) def dismiss(_self, _cmd): self = ObjCInstance(_self) self.view().delegate().release() self.view().setDelegate_(None) self.dismissViewControllerAnimated_completion_(True, None) MyGLViewController = create_objc_class('MyGLViewController', GLKViewController, methods=[dismiss]) @on_main_thread def main(): context = EAGLContext.alloc().initWithAPI_(2).autorelease() glview = GLKView.alloc().initWithFrame_(((0, 0), (320, 320))).autorelease() delegate = MyGLViewDelegate.alloc().init() glview.setDelegate_(delegate) glview.setContext_(context) glview.setEnableSetNeedsDisplay_(False) glvc = MyGLViewController.alloc().initWithNibName_bundle_(None, None).autorelease() glvc.setTitle_('GLKit Demo') glvc.setView_(glview) done_b = UIBarButtonItem.alloc().initWithTitle_style_target_action_('Done', 2, glvc, 'dismiss').autorelease() glvc.navigationItem().setRightBarButtonItem_(done_b) nav = UINavigationController.alloc().initWithRootViewController_(glvc) rootvc = UIApplication.sharedApplication().keyWindow().rootViewController() rootvc.presentModalViewController_animated_(nav, True) nav.release() main()
-
Thanks @omz for the response, it seems to work much better than what I had.
I am in the process of intergrating it now, would it be possible to add the GLViewController into the pythonista ui.View? so that it would be possible to use Pythonista's view system instead of having to reference through ctypes to UIKit?I will push an updated version of the repo soon
Thanks again -
you should be able to add a glkview as a subview of a ui.View. You might even consider a wrapper class which does that for you, creating the glview instance and storing it as an instance variable, setting the frame/bounds/flex correctly, etc.
as the simplest approach,
wrapper= ui.View(frame=(0,0,320,320)) ObjCInstance(wrapper).addSubview_(glview)
-
-
this worked (after glvc.setview...)
v = ui.View(frame=(0,0,600,600)) vo = ObjCInstance(v) v.present('sheet') #must be presented for nextResponder to work vo.nextResponder().addChildViewController_(glvc) vo.addSubview_(glview)
not sure this can be represented after the view is closed, might be worth hanging onto glvc, so you can add it after v is re-presented.
-
Thanks @JonB it seems to be working now
-
incidentally, when experimenting with this, i often got "The view is already being presented or an animation is running"..... @omz what does pythonista use to determine whether a view is already being presented (so we can make sure to clean it up before closing?)
-
@JonB It basically checks if
nextResponder
is aUIViewController
. Theui
module creates view controllers for presentation automatically, and if a view already has an associated view controller, it usually means that it's currently being presented... -
How do I properly setup a GLKViewController delegate?
My current code does not seem to work at alldef glkViewControllerUpdate_(_controller): print "Update", _controller GLKViewControllerDelegate_Class = create_objc_class('GLKViewControllerDelegate_Class', methods=[glkViewControllerUpdate_], protocols='GLKViewControllerDelegate') def GLKViewControllerDelegate(): return GLKViewControllerDelegate_Class.alloc().init()
which is called in the GLKView class
self.vc = GKLViewController("Test GLES", self.glview) self.vcd = GLKViewControllerDelegate() self.vc.delegate = self.vcd
GKLViewController
is just a wrapper for the ctypes function -
@Cethric Your
glkViewControllerUpdate_
method needs to have three parameters, e.g.def glkViewControllerUpdate_(_self, _cmd, _controller): ...
(the actual names of the parameters don't really matter, I tend to use underscores to indicate that these are pointers and not actual objects...)
To actually set the delegate, use the
setDelegate_
method, like this:self.vc.setDelegate_(self.vcd)
-
@omz Thank you so much it seems to work now
Hopefully one last question, the 3 parameters only return pointers so what would be the 'best' solution to get theGLKViewController.framesPerSecond
variable? -
Wrap the
_controller
parameter in anObjCInstance
:def glkViewControllerUpdate_(_self, _cmd, _controller): controller = ObjCInstance(_controller) fps = controller.framesPerSecond() dt = controller.timeSinceLastUpdate() # ...
-
@omz thanks again it works now
-
glCreateShader always fails but I don't know why
def loadShader(source, glsl_type): shader = GLuint() compiled = GLint() # Create the shader object shader = glCreateShader(glsl_type) if(shader == 0): print "Failed to create shader" return 0; # Load the shader source glShaderSource(shader, 1, shaderSrc, 0) # Compile the shader glCompileShader(shader) # Check the compile status glGetShaderiv(shader, GL_COMPILE_STATUS, ctypes.byref(compiled)) if(not compiled): infoLen = GLint(0) glGetShaderiv(shader, GL_INFO_LOG_LENGTH, ctypes.byref(infoLen)) if(infoLen > 1): infoLog = (ctypes.c_char * infoLen)() glGetShaderInfoLog(shader, infoLen, 0, infoLog); print("Error compiling shader:\n%s\n" % infoLog); glDeleteShader(shader); return 0; return shader;
How glCreateShader is referenced
try: glCreateShader = c.glCreateShader glCreateShader.restype = GLuint glCreateShader.argtypes = [GLenum] except AttributeError as e: if DEBUG: print 'could not load the function' print e
Called in the setup process as
class Renderer(Util.RenderCycler): def __init__(self): Util.RenderCycler.__init__(self) self.r, self.g, self.b = colorsys.hsv_to_rgb((time.time() * 0.1) % 1.0, 0.1, 1) def setup(self, context): if (EAGL.setCurrentContext(context)): glClearColor(1, 1, 1, 1.0) s = Util.loadShader("void main() {}", GLenum(GL_FRAGMENT_SHADER)) print s else: print "Could not Setup OpenGLES" def update(self, dt): self.r, self.g, self.b = colorsys.hsv_to_rgb((time.time() * 0.1) % 1.0, 1.0, 1) def render(self, context): if (EAGL.setCurrentContext(context)): glClearColor(self.r, self.g, self.b, 1.0) glClear(GL_COLOR_BUFFER_BIT)
-
-
-
you will need to find the structure definitions, and create your own ctypes structs.
for instance http://developer.limneos.net/?framework=GLKit.framework&header=GLKit-Structs.h
You will need to create classes that extend Structure, and implement the
_fields_
appropriately. (note some of these are unions... you can either onherit from Union, or just pick which way you'd rather refer to the fields, and just use a Structure). these mostly sppesr to be simple arrays of 16 floats for example, so you could slso probably doGLKMatrix4=c_float*16
for example.All of the GLKMatrix4Makexxxxxxxx functions are inlined, so you have to make your own constructors. For the most basic stule, you just define the 16 coefficients directly. zfor the more complicated versions, https://searchcode.com/codesearch/view/70695332/ may have some ideas on what these should look like, so you can roll your own.
-
Will look into it, thanks for the response
-
Working on an example file main.py to test shaders and rendering. However I cannot get the view to show a cube I think the issue is with the
MVP
however I do not know at what point I am going wrong, can someone please look at it and let me know
For simplicity I am using the euclid.py math library.Thanks in advanced.