iOS runLoop and openGL - opengl-es

I'm building an iOS application that uses openGL and I have the following problem:
I'have a certain object that I want to show on my glView. If I just draw it once in the view it works just fine. But if I add my drawView function to the runLoop it calls the function perfectly but it doesn't draw anything and I'm just left with a blank white screen.
Here is all relevant code.
redraw is a flag that indicates the draw function when to draw the scene again.
I expect the following code to rotate my object each time it's drawn:
static double theta = 0;
theta += 0.03;
glRotatef(theta, 1, 1, 0);
The rotation works if I don't add the draw function to the runLoop but draw it manually.
Thanks.

The chances are that there is an error in your OpenGL code somewhere.
If everything works in some scenarios it might be context related. Try putting glError calls after and before every OpenGL call. This way you will know where the problematic function is.
You will need to ensure that you set the context to be the correct context for the currently active view.

problem solved!
I just had to add
[self setCurrent];
to the glView class in the drawView function.

Related

Render texture doesn't update changes made, how to ensure this happens?

I'm building a system which has a set of quads in front of each other, forming a layer system. This layers are being rendered by a orthographic camera with a render texture, which is used to generate a texture and save it to disk after the layers are populated. It happens that I need to disable some of those layers before the final texture is generated. So I built a module that disable those specific layers' mesh renderers and raise an event to start the render to texture conversion.
To my surprise, the final image still presents the disabled layers in the final image. I'm really confused about this, cause I already debugged the code in every way I could and those specific layers shouldn't be visible at all considering the code. It must have something to do with how often render textures update or some other obscure execution order. The entire module is composed of 3 or 4 classes with dozens of lines, so to exemplify the issue in a more succinct way, I'll post only the method where the RT is being converted into a texture with some checks I made just before the RT pixels are read into the new texture:
public void SaveTexture(string textureName, TextureFormat textureFormat)
{
renderTexture = GetComponent<Camera>().targetTexture;
RenderTexture.active = renderTexture;
var finalTexture = new Texture2D(renderTexture.width,
renderTexture.height, textureFormat, false);
/*First test, confirming that the marked quad' mesh renderer
is, in fact, disabled, meaning it shouldn't be visible in the camera,
consequently invisible in the RT. The console shows "false", meaning it's
disabled. Even so, the quad still being rendered in the final image.*/
//Debug.Log(transform.GetChild(6).GetChild(0).GetComponent<MeshRenderer>().enabled);
/*Second test, changing the object' layer, because the projection camera
has a culling mask enabled to only capture objects in one specific layer.
Again, it doesn't work and the quad content still being saved in the final image.*/
//transform.GetChild(6).GetChild(0).gameObject.layer = 0;
/*Final test, destroying the object to ensure it doesn't appear in the RT.
This also doesn't work, confirming that no matter what I do, the RT is
"fixed" at this point of execution and it doesn't update any changes made
on it's composition.*/
//Destroy(transform.GetChild(6).GetChild(0).gameObject);
finalTexture.ReadPixels(new Rect(0, 0, renderTexture.width,
renderTexture.height), 0, 0);
finalTexture.Apply();
finalTexture.name = textureName;
var teamTitle = generationController.activeTeam.title;
var kitIndex = generationController.activeKitIndex;
var customDirectory = saveDirectory + teamTitle + "/"+kitIndex+"/";
StorageManager<Texture2D>.Save(finalTexture, customDirectory, finalTexture.name);
RenderTexture.active = null;
onSaved();
}
Funny thing is, if I manually disable that quad in inspector (at runtime, just before trigger the method above), it works, and the final texture is generated without the disabled layer.
I tried my best to show my problem, this is one of those issues that are kinda hard to show here but hopefully somebody will have some insight of what is happening and what should I do to solve that.
There are two possible solutions to my issue (got the answer at Unity Forum). The first one, is to use the methods OnPreRender and OnPostRender to properly organize what should happens before or after the camera render update. What I end up doing though was calling the manual render method in the Camera, using the "GetComponenent().Render();" line, which updates the camera render manually. Considering that my structure was ready already, this single line solved my problem!

Adding animation to Android application

I'm currently working on a new app, and I want to add customized animations to it (not talking about activity transitions).
To show you exactly what I mean, take a look at this video at 2:30-2:33:
https://www.youtube.com/watch?v=XBMdjX5bbvk&nohtml5=False
You see the chest jumping to the screen and opens smoothly with beautiful animation?
I'd really like to know how can it be added to an Android app, is it a frame animation?
I mean, I can make this animation, in 2D, I just want to know how to add it (I'm using Android Studio) without causing memory overflow.
Thanks!
For you question:
You see the chest jumping to the screen and opens smoothly with
beautiful animation? I'd really like to know how can it be added to an
Android app, is it a frame animation?
I don't think it is a frame animation. I guess this has been implemented using OpenGL. You can find the official tutorial here.
If you want to make simple 2d animations, you can use the AnimationDrawable api provided by android. You basically need frames for the sequence of animations and then you can create the animation using the following code:
// you would need an `ImageView` object as a placeholder for the animation
ImageView mMascotView = findViewById(...);
// prepare the animation object ..
AnimationDrawable mMascotAnimation = new AnimationDrawable();
final int frameTime = 250; // time in milliseconds
// adding the frames to the animation object. You can specify different
// times for each of these in milliseconds
mMascotAnimation.addFrame(getResources().getDrawable(R.drawable.frame1),frameTime);
mMascotAnimation.addFrame(getResources().getDrawable(R.drawable.frame2),frameTime);
mMascotAnimation.addFrame(getResources().getDrawable(R.drawable.frame3),frameTime);
// make it loop infinitely ..
mMascotAnimation.setOneShot(false);
// set the background of the `ImageView` as the `AnimationDrawable`object ..
mMascotView.setBackground(mMascotAnimation);
// start the animation ..
mMascotAnimation.start();
Note: You should not call the AnimationDrawable.start()inside the onCreate() method of the activity. The views are not ready yet. You should use the callback on onWindowFocusChanged() method and start the animation there:
#Override
public void onWindowFocusChanged (boolean hasFocus)
{
//Start animation here
if(hasFocus) {
mMascotAnimation.start();
}
}

Loading new level OpenGL

I am working on a small 2d game engine for android-ndk using opengl.
I am facing difficulty on how to change levels, eg. from menu to game screen.
Because the texture ids are not working when loading new textures for game screen using glGenTextures, glGenTextures keeps returning duplicate ids.
// class to bind ndk with java
Renderer.java
void onSurfaceChanged(gl, width, height){
nativeSurfaceChanged();
}
void onDrawFrame(){
nativeDrawFrame();
}
// c++ code
Game.cpp
Screen *screen;
void SetScreen(Screen *scrn){
screen = scrn;
// load textures and create openGL objects (mesh and textures)
screen->Initialize();
}
void Update(){
screen->Update();
screen->Render();
}
NDKActivity.cpp
Game *game;
void nativeSurfaceChanged(){
// initlizes stuff like audio engine, rendering engine
game->Initialize();
// set current screen to main menu
game->SetScreen(new MainMenu());
}
void nativeDrawFrame(){
game->Update();
}
MainMenu.cpp
void Update(){
// if some button is clicked
game->SetScreen(new GameScreen());
}
Now when menu is initialized, everything works fine. But on loading GameScreen textue ids get all mixed up
I basically ported it from windows app where I was using GLUT for creating OpenGL context and there it was working fine.
And please let me know if more info is needed
glGenTextures keeps returning duplicate ids
That should not happen, unless you're deleting the texture with that ID somewhere (else) or end up in a different GL context.
I am facing difficulty on how to change levels, eg. from menu to game screen.
It's as easy as drawing something different. Have two functions draw_menu and draw_level; maybe a draw_loadingscreen and while you're in the loading screen or menu you can replace all the stuff the level uses.
Or you could use a modern streaming approach, where you don't discriminate between menu, loading screen and level and instead upon drawing each frame collect the resources required to draw it, load what's not yet loaded into the GL context and then draw.
Deleting GL resources can be mostly offloaded into a background garbage collection routine. I.e. every frame for every resource of your game you increment a counter; in the frame setup, when you actually are about to draw it you reset the counter to zero. Once the counter hits a certain threshold you delete it. If when loading resources into GL you hit an out-of-memory condition you can work yourself through the resources with the highest counter value downward, deleting them from the GL context.
so as it turns out I was listening for change screen method in OnTouch() method which apparently runs on different thread than opengl and thus every thing was falling apart. So I had to add a callback which would change screen in onDrawFrame and it fixed the issue.
thanks for helping :)

Custom Draw in NSView without erasing the previous background

I am trying to plot few points dynamically on my Custom View using Quartz functions so that i get a complete graph. I handle drawing of lines inside the drawRect method of Custom View where I get the current context and draw the lines. But, they get erased when i try to draw a new line. I want to have those lines also visible along with the new ones drawn. Please let me know how to do this. I can't store all the points together and draw at the end. I want to continously update my view. Thanks in advance.
Add a method to your custom view:
- (BOOL) isOpaque { return YES; }
That will prevent the drawing of any views behind yours including the background.
Note, however, that on resize you'll need to redraw everything either way. A more proper solution would be to use off-screen image to draw into instead.
You could use CALayers: add a new child layer to the root each time you have new data, and draw to that layer. Your drawing code can remain the same: you just need to put in the code for creating and using layers, which is actually pretty easy.
See: http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/CoreAnimation_guide/Introduction/Introduction.html#//apple_ref/doc/uid/TP40004514

Core Animation... cyclic animations?

To phrase my question as simply as possible, is there a way to create a core animation sequence to repeat over and over until a stop?
Specifically, I'm making a custom class that I want to have a -start and -stop method that will cause it to pulsate. Writing the animation code for the pulse is not the problem, rather, how to make it repetitive?
Thanks in advance for any answers!
According to the documentation, you do it by creating an animation with an extremely large repeatCount (code excerpted from the documentation I linked to):
// create the animation that will handle the pulsing.
CABasicAnimation* pulseAnimation = [CABasicAnimation animation];
// over a one second duration, and run an infinite
// number of times
pulseAnimation.duration = 1.0;
pulseAnimation.repeatCount = HUGE_VALF;
// we want it to fade on, and fade off, so it needs to
// automatically autoreverse.. this causes the intensity
// input to go from 0 to 1 to 0
pulseAnimation.autoreverses = YES;
edit: The OP asked how to stop the animation. From the next paragraph in the documentation:
You start an explicit animation by
sending a addAnimation:forKey: message
to the target layer, passing the
animation and an identifier as
parameters. Once added to the target
layer the explicit animation will run
until the animation completes, or it
is removed from the layer. The
identifier used to add an animation to
a layer is also used to stop it by
invoking removeAnimationForKey:. You
can stop all animations for a layer by
sending the layer a
removeAllAnimations message.

Resources