It seems that no matter what GL function I call, I get EXC_BAD_ACCESS. However, I'm calling these functions in readFromURL:ofType:error: of an NSDocument subclass, for some offscreen drawing. If I remove that code, and try to use GL later, once everything's loaded, everything works fine. Is this a GL context issue?
I read Apple's GL guide, but in the section about offscreen drawing, it just told me how to use framebuffers. Which I do, but since glGenFramebuffersEXT crashes just like everything else, it's not very helpful.
Is there some sort of context creation I need to perform, and if so, what's the best way to do it?
Yes, OpenGL calls need a context. If you have NSOpenGLView, you need to get its context and make it current:
[[openGLView openGLContext] makeCurrentContext];
// glCalls()
If you're not using NSOpenGLView, you can create NSOpenGLContext youself.
Related
I have an existing openGL context, using an OpenGL 2.1 core profile. I am able to draw objects/textures/etc no problem. However, now I want to be able to have my application to launch a separate NSWindow, with an NSOpenGLView, that displays part of a texture I drew in the original renderer's view. After some reading, I eventually bumped into the topic of context sharing, which I think may be the route I have to take if I want to pull this off.
My shared openGL context is of type - CGLContextObj, but I don't know what to do with it as my window resides in a different process. I've read the Apple documentation on rendering contexts, but I am unable to apply the concepts they laid out if there's barely any examples for me to go through. Any advice will be really appreciated, thank you in advance.
EDIT:
Perhaps I did not give enough description, my apologies. I subclass my NSOpenGLView, and it's init I do the following:
// *** irrelevant initialization stuff above inside init *** //
// Get pixel format from first context to be used for NSOpenGLView when it's finally initialized later
_pixFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:(void*)_attribs];
// We will create CGPixelFormatObj from our C array of pixel format ttributes
GLint nPix;
CGPixelFormatObj myCgPixObj;
CGLChoosePixelFormat(_attribs, &myCgPixOPbj, &nPix);
// Now that we have the pixel format in CGPixelFormatObj form, create CGLContextObj to be passed in later when we init NSOpenGLView
CGLContextObj newContext;
CGLCreateContext(myCgPixObj, mainRenderingContext, &newContext);
// Create an NSOpenGLContext object here to feed into NSOpenGLView
NSOpenGLContext* _contextForGLView = [[NSOpenGLContext alloc] initWithCGLContextObj:newContext];
[newContext setView:self];
[self setOpenGLContext:newContext];
// We don't need this anymore
CGLDestroyPixelFormat(myCgPixObj);
return self;
I am able to draw objects in this view just fine. But I get a blank white rectangle whenever I try to use the textures created in the main rendering context. I'm a little lost on how to proceed from here, I have never dealt with shared contexts before.
Seems like I got it working, partially at least since I had to force the view to redraw by moving my Window around to actually render the texture from the main context (another problem for another time!). Anyways, here's how I did it:
My main rendering context is supplied by a host application (yes, I'm working on a plugin), and is of type CGLContextObj. I wrap that context in an NSOpenGLContext object via calling initWithCGLContextObj
Next step was to create an NSOpenGLPixelFormat object, initializing it with the pixel format attributes used by the host application's renderer. This step is important as it ensures that the rendering context that will be used in my view will have the same OpenGL core profile, along with other attributes used by the host application.
Then in my subclassed NSOpenGLView, I create a new NSOpenGLContext object, preferably in the prepareOpenGL method, by using initWithFormat:shareContext: for allocation. I used the NSOpenGLPixelFormat and NSOpenGLContext objects created previously to pass as parameters.
Upon assigning the newly created context to my view, I was able to render the textures from the main rendering context.
I recently discovered that in > iOS5 UINavigationBar does not get its drawRect called. I want to figure out how to draw with Core Graphics in a category.
The end goal I am trying to achieve is eliminating images from my app and have everything drawn at runtime. I am also trying to make this library automatic, so that users don't have to think about using my custom classes.
Is there a way to replace a class with one of your own at runtime? like: replaceClass([UINavigationBar class], [MyCustomBar class]);
Thanks in advance.
Is there a way to replace a class with one of your own at runtime?
In Objective-C this is know as class posing.
Class posing is based on the use of NSObject's poseClass method, which is now deprecated (on 64 bit platforms, including the iPhone).
Alternative approaches have been investigated; you can read about one here, but they do not seem quite to fit the bill.
I found the solution, Instead of messing with draw rect, I just made some methods that draw to a UIImage then set the image as the background view for the elements i am customizing. It makes my custom UI magic again.
In the new GLKit GLView reference, there is this warning that is emphasized:
Important: Your drawing method should only modify the contents of the framebuffer object. Never attempt to read the pixel information from the underlying framebuffer object, modify or dispose of the framebuffer object, or read its other properties by calling OpenGL ES functions. Instead, rely on the properties and methods provided by the GLKView class
Previously, with EAGLView the best practice published all over was for hit testing which included the use of glReadPixels using a framebuffer which was rendered but not presented.
With GLKView the only thing that seems to come close is a "-snapshot" call to make a UIImage object from the render. Then dig out the pixels. This seems very inefficient.
Is there a "best practice" for hit testing with the new GLKit funcitons? It seems that binding and rebinding of a seperate framebuffer are possible but then I'm not sure of what the dramatic warning in the GLKView reference means.
Any ideas on the best approach for hit testing when using GLKit?
Check out this very informative SO post which includes sample code. I believe it is exactly what you're looking for- it worked great for me.
Greetings! I'm attempting to use MKMapView without any Apple code samples, though there are a few others out there of varying clarity. (I know, "Read the friendly manual." I've done that but it's not 100% clear, so please bear with me on this one.)
Here's the situation. I have a MKMapView object, wherein I have added a set of about ten MKPinAnnotation objects. So far, so good. Everything is alloced/released sanely and there doesn't appear to be any complaints from Instruments.
Upon initial display, I set up a MKCoordinateRegion object with the centerpoint at our first pin location, and a (arbitrary) span of 0.2 x 0.2. I then call:
[mapView setRegion:region animated:YES];
[mapView regionThatFits:region];
Wow! That worked well.
Meanwhile ... I also have a segmented control to allow for movement to each pin location. So as I tap through the list, the map animates to each new pin location with a new pair of calls to setRegion:animated: and regionThatFits: ... or at least that's the idea.
While the map does "travel" to the new pin location, the map itself doesn't update underneath. Instead, I see my pin on a gray/blank-map background ... until I nudge the map in any direction, however slightly. Then the map shows through! (If I'm only moving within a short distance of the previous pin location, I'll usually see whatever part of the map was already loaded.)
I suspect I'm doing something dumb here, but I haven't been able to figure out what, at least not from the MapKit docs. Perhaps I'm using the wrong calls? (Well, I do need to set the region at least once, yes? Moving that around doesn't seem to help though.) I have also tried using setCenterCoordinate:animated: - same problem.
I'm assuming nothing at this point (no pun intended). Just trying to find my way.
Clues welcome/appreciated!
UPDATE: Calling setRegion:animated: and regionThatFits: the first time, followed by setCenterCoordinate:animated: while traversing the list, has no effect. Interesting finding though: If I change animated to NO in both cases, the map updates!!! Only when it's set to YES. (Wha happen?! Is animated: broken? That can't be ... ???)
It turns out that the map update doesn't work when using the SIMULATOR. When I try setCenterCoordinate:animated: on the device, I do get the map update underneath.
Bottom line: I was trusting the simulator to match the device in terms of map updating behavior. Alas, I was mistaken! Lesson learned. "Don't let this happen to you." :)
You need to invoke the setRegion:animated: call in the Main thread context.
Just do something like:
....
[self performSelectorOnMainThread:#selector(updateMyMap) withObject:nil waitUntilDone:NO];
}
-(void) updateMyMap {
[myMap setRegion:myRegion animated:YES];
}
and it should work in any case (animated or not), with the map updated underneath.
Hum strange. The map updates on my Mac even in the simulator. Maybe a network setting (proxy or whatever) that would prevent the map widget to download the tiles on the simulator ?
Even though this is an old topic I thought I'd ring in with my experience. It seems the map animation only fails on devices running iOS 3.1.x and the simulator running 3.1.x. My dev iPod touch with 3.1.3 fails to zoom if animation is on.
I'm working on a simple proof-of-concept for an iPhone app (and important bit of info, I'm pretty new to Mac OSX development all around). I created a view based app with a timer. I declared my NSTimer in the interface of my app's controller, used #property and #synthesize, and I initialize it in the controller's viewDidLoad method with scheduledTimerWithTimeInterval method. My selector is a method with the signature -(void)someMethod:(NSTimer *)timer which is declared in the interface and defined in the implementation file of the controller as well. I can step past the line where I assign the timer and see that it points to a valid object, but my program goes no further than the end of the viewDidLoad method and never reaches the breakpoint at the first line of my method that is called by the timer. Also, I see GDB: Program received bad signal: "EXC_BAD_ACCESS" in the status bar of xcode at this point (viewDidLoad end is reached). I didn't do anything in IB but add a view and a picker just so I'd see if the UI actually loads...it never does.
So, am I doing something wrong with the NSTimer, or are my troubles elsewhere? How can I use the debugging tools in xcode to get more information?
EXC_BAD_ACCESS usually indicates a memory management error, without seeing the code probably from somewhere else in your app. It's a very common error for beginners, but an important subject to fully understand, so I'd suggest looking through some of the questions on memory management here and find a few guides or tutorials to look through. It's actually pretty easy to learn.
Also, it shouldn't hurt but unless you need to access the timer in between fire events, you don't actually need to store it as an instance variable. Once you create and start a timer it's added to and retained by the application's run loop.
Have you got NSZombieEnabled?
Might be useful if this is failing on an over released object.