Sunday, 12 May 2013

OpenGL ES 1.1: lighted texture mapped object is too dark

Usually the texture is used as the diffuse material for the object. It is timed with the diffuse light to get the diffuse part of the lighted object color.

If the object looks too dark, you can increase the luminance of the diffuse light. If the luminance of the diffuse light is already 1, you may want to increase the luminance of your texture.


OpenGL ES 1.1 how to choose proper value for ambient/diffuse/specular color for light and material

Usually the color of a lighted object is summation of three parts: ambient, diffuse and specular.

The ambient part is the ambient light color times the object ambient material color. It does not depend on light position nor eye position.

The diffuse part is the diffuse light color times the object diffuse material color times a factor. It depends on light position but not eye position.

The specular part is the specular light color times the object specular material color times a factor. It depends on both light position and eye position.

There could be an emission part, which is similar to ambient part but does not need a light.

To view the contribution of the three parts to the final object color, you can enable just one type of light or material and disable other types of light or material and see the rendered object.

Since the three parts are summed together, you cannot let them all have strength 1, otherwise the color of the object becomes too bright like a photo with over exposure. You need to give each part a weight so that their summation does not exceed 1 in most positions.

The diffuse part provides most of the visual cue to the shape of the object. Therefore I usually give it a weight of 0.7, that is, diffuse light illuminance times diffuse material illuminance is around 0.7.

 You may want some ambient color if you do not want to have dark part of the object. However, too much ambient part gives your object a washed out feeling, so you do not want too much of it. A weight of 0.3 seems to be a good choice.

The specular part gives a shiny spot on your object. Usually a weight of 0.1 is good choice.  There is another parameter called shininess to control how much this shiny spot spreads out. A value of about 100 gives you a small bright spot whereas a value of 10 gives you less bright shiny patches.



Thursday, 9 May 2013

iOS: cannot find In-App-Purchase product in sandbox app store

You should be able to see In-App-Purchase products in sandbox app store even before you submit your application for review. Changes made in iTunes connect about In-App-Purchase should be immediately seen in sandbox app store.

One cause of problem is your IAP product ID is not unique. IAP product ID needs to be unique in the app store, not just unique in your app. A product ID like "Upgrade" won't work. You need to make it really unique by using reverse domain name like "com.mycompany.mypapp.myprod".

Another requirement is that your app bundle ID needs to match what you use in iTunes Connect. You need to first create a new bundle ID supporting IAP in iOS developer's portal then use it to create a new app in iTunes Connect.

If you change your bundle ID in Xcode, you need to delete the old app in iPhone simulator manually, otherwise Xcode may get confused and run the old app, which will confuse you since all your changes seem to have no effect.

Monday, 6 May 2013

iOS: Using lazy loading to improve application loading time

If your application needs to load some large resource and do some lengthy processing before it can display something, you need to do those in a thread other than the main UI thread. Otherwise your user will see your default launch image for a long time and may become impatient.

This is called lazy loading. However it introduces complexity into your application since now some resources may be not ready when you display your content.

If you display content by polling changes (e.g. OpenGL ES doFrame), your resource processing threads need to let the display thread know content has changed and the display thread needs to check if a resource is ready and then decide how to display.

Otherwise, the resource processing threads need to update the view by sending message or notification to the view controller.

Sunday, 5 May 2013

iOS: OpenGL ES frame is not updated for changes made in another thread

It is common to use display link in iOS to set a frame rate for OpenGL ES and use a function doFrame to update frame regularly.

-(void) doFrame {

  if (_needUpdate) {      // line A
    if ( // condition is satisfied) {
      // draw the scene
      _needUpdate = false;  // line B
    }
  }

}

In another thread, you do the following

//change the scene
_needUpdate = true;  // line C

so that the scene will be redrawn in doFrame.

However there is a bug with this approach. If execution time between line A and line B is long, there is high chance that line C happens between line A and line B and has no effect. The symptom is that frame is not updated for changes made in another thread.

One simple workaround is to move line B up and make the execution time between line A and line B short. Use a counter instead of boolean for _needUpdate could be another solution.





Saturday, 4 May 2013

Workaround about sorting English ordinal numbers or Roman numbers

You may want to sort texts containing English ordinal numbers or Roman numbers by their numerical order instead of dictionary order. For example

1st word
2nd word
3rd word
4th word

Richard I
Richard II
Richard III
Richard IV

One simple workaround for this is to encode them as simple numbers in the text, e.g.

#T001 word
#T002 word
#T003 word
#T004 word

Richard #R01
Richard #R02
Richard #R03
Richard #R04

then they can be sorted by dictionary order. When you need to display them, convert them to ordinal number or Roman number.

Binary file read by std::ifstream is corrupted

By default, std::ifstream is constructed with text mode. On windows, it will convert new line character which may corrupt the binary file.

The fix is to use std::ifstream::binary as the second parameter when construct ifstream for binary file.