22/03/2013

OpenGL blend function

Trước đây làm việc OpenGL mà không hiểu mấy về cái hàm gl.glBlendFunc(a,b). Hôm qua có thời gian ngồi xem tài liệu kỹ lại thì ra là thế này. Gọi D là màu của destination (màu đang có), S là màu source (màu ta cần pha với màu đang có), ta có công thức tính màu sau khi pha như sau:
R = a*S+b*D
Lấy ví dụ: 
  • Nếu a= GL_ONE, b=GL_ONE, S=(1,0,0) (màu đỏ), D=(0,0,1) (xanh da trời). Ta sẽ có R=(1,0,1) (màu đỏ tươi)
  • Nếu a=GL_SRC_ALPHA, b= GL_ONE_MINUS_SRC_ALPHA, S=(0.5,1,0,0), D=(1,0,0,1). Ta sẽ có: 
    • Ra = 0.5*0.5+(1-0.5)*1=0.25+0.5 = 0.75
    • Rr = 0.5*1+(1-0.5)*0 = 0.5
    • Rg = 0.5*0+(1-0.5)*0 = 0
    • Rb = 0.5*0+(1-05)*1 = 0.5
                R = (0.75,0.5,0,0.5)



20/03/2013

ARC in Mac OS X 10.6.8

Một ngày vật lộn với việc build app với ARC chạy trên Mac OS X 10.6.8 bằng XCode 4.6.1 (Lưu ý: XCode 4.6 có bug khi build app với ARC  chạy trên Mac OS X 10.6.8). Nếu tạo một Project mới với ARC được bật thì mọi việc OK. Tuy nhiên khi add mấy file mã nguồn vào thì cứ bị lỗi:
Symbol not found: _objc_retain
Thử đủ cách lượm lặt từ Google như:

  • Add -fobjc-arc vào Other linker flags.
  • Sử dụng -weak_library, -weak_framework.
  • Tắt Implicit link to system library option
Cuối cùng cũng tìm ra lời giải. ARC trên 10.6.8 không hỗ trợ các phương thức + (void) initialize+(void) load.


15/03/2013

Kiểm tra một số có là luỹ thừa của 2 hay không nhanh nhất

Thông thường để muốn kiểm tra một số có là luỹ thừa của 2 hay không thì chúng ta đem số này chia cho 2 như sau:

public boolean isPowerOfTwo(int n){
	if( 0 == n|| 1 == n ) return true;
	int x = n / 2;
	int y = n%2;
	if (1 == y) return false;
	return isPowerOfTwo(x);
}
Hoặc chúng ta không cần viết đệ qui như sau:

  public boolean isPowerOfTwo(int n){
    boolean ret;        
	if( 0 == n|| 1 == n ){
    	     ret = false;       
    }else{
        int x = n / 2;
        int y = n%2;
        while ( x > 0){
        	if (1 == y) {
            ret = false;
            break;
 		};
		x = x / 2;
        y = x%2;
	}
	ret = true;
	}
   return ret;
 } 

Sau đây là cách nhanh hơn sử dụng hàm logarit:

public boolean isPowerOfTwo(int n){
	double logn2 = Math.log(n)/Math.log(2);
	int logn2i = (int) (Math.floor(logn2));
	if(logn2-logn2i==0)
		return true;
	else
	return false;
}

Tuy nhiên nếu chúng ta để ý một chút chúng ta sẽ có cách kiểm tra nhanh nhất. Các số là luỹ thừa của 2 đều có 1 chữ số 1 trong biểu diễn nhị phân của chúng. Ví dụ số
1: 000001
2: 000010
4: 000100
8: 001000
16: 010000
32:     100000
Xét số n = 32 ( 100000) và n -1 = 31 (011111) và rõ ràng n&(n-1) = 0.
Ta có giải thuật như sau:

public boolean isPowerOfTwo(int n){
	return ((n!=0) && (n&(n-1))==0);
}

Thật ngắn gọn, đơn giản phải không các bạn!