2012年4月28日 星期六

OpenGL: 基本幾何圖形之一

since: 2012/04/27
update: 2012/04/28

reference:
OpenGL: A Primer, 3/e

基本幾何圖形之一: 點


A. 說明:

     1. 延續之前文章: I touchs: OpenGL: General Strucure專案.

     2. 將繪圖函式額外獨立成 .h.cpp 檔案.

------------------------------------------------------------------------------

B. 新增給繪圖函式使用的檔案:
     1. Xcode > File > New > File...
         > Mac OS X > C and C++ > Header File > Next
              Save As: draw.h
              Targets: OpenGLStart checked
              > Create

     2. Xcode > File > New > File...
         > Mac OS X > C and C++ > C++ File > Next
              Save As: draw.cpp
              Targets: OpenGLStart checked
              > Create

     3. 開啓 draw.h 檔案, 修改如下:
//@update
/*
#ifndef OpenGLStart_draw_h
#define OpenGLStart_draw_h

#endif
*/

     4. 開啓 draw.cpp 檔案, 修改如下:
//#include <iostream>
//@add
#include <OpenGL/OpenGL.h>
#include <GLUT/GLUT.h>

     5. 開啓 main.cpp 檔案, 修改如下:
#include <OpenGL/OpenGL.h>
#include <GLUT/GLUT.h>
#include "draw.h"
....

------------------------------------------------------------------------------

C. 畫點
     1. 開啓 draw.h 檔案, 修改如下:
//@add: drawing
void drawPoints(); // 畫點

     2. 開啓 draw.cpp 檔案, 修改如下:
....
//@add: drawing
//
// 畫點
void drawPoints()
{
    // Clear the buffer
    glClear(GL_COLOR_BUFFER_BIT);
   
    //@add: Set the color for this polygon (Red)
    //
    //state: current drawing color
    //glColor3f(1.0, 0.0, 0.0);
   
    //@add: sets the point size state variable
    //
    // default: 1.0
    // p.s. glPointSize() 只能在 glBegin() 與 glEnd() 區間之外設定.  
    glPointSize(10.0);
   
    // Let us begin drawing some points
    //glBegin(GL_POLYGON);
    glBegin(GL_POINTS);
   
    // Specify the points
    glColor3f(1.0, 1.0, 1.0); // Set the color state: white
    glVertex2f(-0.5, -0.5);
   
    glColor3f(1.0, 0.0, 0.0); // Set the color state: red
    glVertex2f(-0.5, 0.5);
   
    glColor3f(0.0, 1.0, 0.0); // Set the color state: green
    glVertex2f(0.5, 0.5);
   
    glColor3f(0.0, 0.0, 1.0); // Set the color state: blue
    glVertex2f(0.5, -0.5);
   
    // Ok we are done specifying points
    glEnd();
   
    // Write this out to the screen
    glFlush();
}

     3. 開啓 main.cpp 檔案, 修改如下:
....
int main(int argc, char * argv[])
{
....
    // Set the callback function, will be called as needed
    //glutDisplayFunc(display);
    glutDisplayFunc(drawPoints); // 畫點
....
}

     4. 編譯並執行:


2012年4月27日 星期五

OpenGL: General Strucure

since: 2012/04/27
update: 2012/04/28

reference:
1. OpenGL: A Primer, 3/e
2. 投影的分類(Classification) - 3D2D projection


A. 說明:

     延續 I touchs: Beginning OpenGL on Mac OS X 這篇文章的專案, 來調整成
     OpenGL 常用的程式結構.

-------------------------------------------------------------------------------------

B. 開啓 main.cpp 檔案, 修改如下:
....
//@add: Let us create a function to initialize everything
void init()
{
    // This determines the background color, in this case: gray
    // state: current clear color
    glClearColor(0.5, 0.5, 0.5, 1.0); // R, G, B, A
   
    // Determines which matrix to apply operations to.
    // value: GL_PROJECTION or GL_MODELVIEW
    glMatrixMode(GL_PROJECTION); // default vlew
   
    // Loads the Identity matrix
    glLoadIdentity();
   
    // 正投影(Orthographic Projection)
    //
    // The gluOrtho2D function defines a 2-D orthographic projection matrix.
    //
    // Set the size and projection of the buffer
    // (x left, x right, y bottom, y top)
    // corner => (left, bottom), (right, top)
    gluOrtho2D(-1.0, 1.0, -1.0, 1.0); // default
}

void display()
{
    // Clear the buffer
    glClear(GL_COLOR_BUFFER_BIT);
   
    //@add: Set the color for this polygon (Red)
    //
    //state: current drawing color
    glColor3f(1.0, 0.0, 0.0);
   
    // Let us begin drawing some points
    glBegin(GL_POLYGON);
   
    // Specify the points
    glVertex2f(-0.5, -0.5);
    glVertex2f(-0.5, 0.5);
    glVertex2f(0.5, 0.5);
    glVertex2f(0.5, -0.5);
   
    // Ok we are done specifying points
    glEnd();
   
    // Write this out to the screen
    glFlush();
}

int main(int argc, char * argv[])
{
    // insert code here...
    //std::cout << "Hello, World!\n";
   
    //@add for OpenGL
    //
    // Init glut
    glutInit(&argc, argv);
   
    //@add: Specify the Display Mode
    //
    // this one means there is a single buffer
    // and uses RGB to specify colors (default)
    glutInitDisplayMode(GLUT_RGB|GLUT_SINGLE); 
   
    //@add: Set the window size
    glutInitWindowSize(640, 480);
   
    //@add: Where do we want to place the window initially?
    glutInitWindowPosition(100,100);
   
    // Name the window and create it:
    //
    // default position: upper-left corner
    // default size: 300 x 300 pixels
    glutCreateWindow("Hello OpenGL");
   
    // Set the callback function, will be called as needed
    glutDisplayFunc(display);
   
    //@add: Initialize the window
    init();
   
    // Start the main loop running, nothing after this
    // will execute for all eternity (right now)
    glutMainLoop();
   
    //@update: will not be executed
    //return 0;
}

-------------------------------------------------------------------------------------

C. 編譯並執行:

2012年4月23日 星期一

Beginning OpenGL on Mac OS X

since: 2012/04/23
update: 2012/04/27


A. 說
明:

      在繼續學習 OpenGL ES 前, 想先對 OpenGL 多瞭解一些, 這裡的學習記錄,
      可能會多次的更新與修正, 僅供參考.

------------------------------------------------------------------------------------------

B. 環境:
     1. MacBook Pro (13-inch, Mid 2009)
     2. Mac OS X 10.7.3
     3. Xcode 4.3.2
     4. 檢測目前的環境:
          OpenGL Extensions Viewer
     說明: 可以看到目前這台電腦支援的 OpenGL 版本為:
               完全支援: 1.1 ~ 2.1
               部分支援: 3.0 ~ 3.3
               全不支援: 4.0 ~ 4.2

------------------------------------------------------------------------------------------

C. 新增專案:
     1. Xcode > File > New > Project... > Mac OS X > Application >
         Command Line Tool > Next
       Product Name: OpenGLStart
       Company Identifier: com.blogspot
       Type: C++
       Use Automatic Reference Counting: checked
       > Next > Create

     2. 新增 Framework:
       OpenGL
        - OpenGL is the premier environment for developing portable,
           interactive 2D and 3D graphics applications.

       GLUT
        - OpenGL Utility Toolkit

------------------------------------------------------------------------------------------

D. 開啓 main.cpp 檔案, 修改如下:
//This is just for basic io, you really DON'T need it
//#include <iostream>

//@add
#include <OpenGL/OpenGL.h> // OpenGL Library
#include <GLUT/GLUT.h> // GLUT Library, will make you life easier

//@add
void display()
{
    // Clear the buffer
    glClear(GL_COLOR_BUFFER_BIT);
   
    // Let us begin drawing some points
    glBegin(GL_POLYGON);
   
    // Specify the points
    glVertex2f(-0.5, -0.5);
    glVertex2f(-0.5, 0.5);
    glVertex2f(0.5, 0.5);
    glVertex2f(0.5, -0.5);
   
    // Ok we are done specifying points
    glEnd();
   
    // Write this out to the screen
    glFlush();
}

//int main(int argc, const char * argv[])
//@update: just remove "const"
int main(int argc, char * argv[])
{
    // insert code here...
    //std::cout << "Hello, World!\n";
   
    //@add for OpenGL
    //
    // Init glut
    glutInit(&argc, argv);
   
    // Name the window and create it
    //
    // default position: upper-left corner
    // default size: 300 x 300 pixels

    glutCreateWindow("Hello OpenGL");
   
    // Set the callback function, will be called as needed
    glutDisplayFunc(display);
   
    // Start the main loop running,
    // nothing after this will execute for all eternity (right now)

    glutMainLoop();
   
    //@ will not be executed (update: 2012/04/26)
    //return 0;
}

------------------------------------------------------------------------------------------

E. 編譯並執行:


------------------------------------------------------------------------------------------

F. 備註:
     1. MeshLab 軟體.
         可用來讀取與編輯鬆散的 3D 三角形面的網狀模型.
         (unstructured 3D triangular meshes)
         p.s. 可以從 The Stanford 3D Scanning Repository 下載 3D 模型檔.
      (bunny\reconstruction\bun_zipper.ply)
      看看可愛的 Bunny ~

------------------------------------------------------------------------------------------

     2. Nate Robins - OpenGL - Tutors
         a. 下載:
              Tutors source code package (tutors-src.zip 920KB)

         b. 解壓縮後, 開啓 tutors.xcodeproj 
              將右上方的 "active scheme" 選為 shapeslightmaterial, 然後執行. 

         c. 執行結果
             shapes:

             lightmaterial:

2012年4月19日 星期四

Filter4Cam 實作: 16. 調整濾鏡表單位置之二

since: 2012/04/19
update: 2012/04/20


A. 調整濾鏡表單水平擺放的位置

      1. 開啓 ViewController.m 檔案, 修改如下:
....
- (UITableView *)filterListTableView
{  
    if (_filterListTableView == nil) {
        ....
        //@update: Tune UI
        /*
        _filterListTableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, kOverlayTableViewRowHeight) style:UITableViewStyleGrouped];
        */
        //@update: Tune for Orientation
        _filterListTableView = [[UITableView alloc] init];
    }
   
    return _filterListTableView;
}
....
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{   
    //@update
    // 設備垂直擺放
    if (interfaceOrientation == UIDeviceOrientationPortrait)
    {
        //@update: Tune UI
        [self.filterLensImageView setFrame:CGRectMake(20, 120, 280, 280)];
       
        //@update: Tune for Orientation
        self.filterListTableView.transform = CGAffineTransformMakeRotation(-M_PI * 2.0);

        [self.filterListTableView setFrame:CGRectMake(0, 0, self.view.frame.size.width, kOverlayTableViewRowHeight)];
    }
    // 設備垂直 180 度擺放
    else if (interfaceOrientation == UIDeviceOrientationPortraitUpsideDown) {
        //@update: Tune UI
        [self.filterLensImageView setFrame:CGRectMake(20, 120, 280, 280)];
       
        //@update: Tune for Orientation
        self.filterListTableView.transform = CGAffineTransformMakeRotation(-M_PI * 2.0);

        [self.filterListTableView setFrame:CGRectMake(0, 0, self.view.frame.size.width, kOverlayTableViewRowHeight)];
    }
    // 設備水平向右擺放
    else if (interfaceOrientation == UIDeviceOrientationLandscapeRight) {
        //@update: Tune UI
        [self.filterLensImageView setFrame:CGRectMake(120, 20, 280, 280)];
       
        //@update: Tune for Orientation
        self.filterListTableView.transform = CGAffineTransformMakeRotation(M_PI * 0.5);

        [self.filterListTableView setFrame:CGRectMake(0, 0, kOverlayTableViewRowHeight, self.view.frame.size.width)];
    }
    // 設備水平向左擺放
    else if (interfaceOrientation == UIDeviceOrientationLandscapeLeft) {
        //@update: Tune UI
        [self.filterLensImageView setFrame:CGRectMake(120, 20, 280, 280)];
       
        //@update: Tune for Orientation
        self.filterListTableView.transform = CGAffineTransformMakeRotation(M_PI * 0.5);

        [self.filterListTableView setFrame:CGRectMake(0, 0, kOverlayTableViewRowHeight, self.view.frame.size.width)];
    }
    // 其它 (UIDeviceOrientationFaceUp, UIDeviceOrientationFaceDown, UIDeviceOrientationUnknown)
    else {
        //@update: Tune UI
        [self.filterLensImageView setFrame:CGRectMake(120, 20, 280, 280)];
       
        //@update: Tune for Orientation
        self.filterListTableView.transform = CGAffineTransformMakeRotation(M_PI * 0.5);

        [self.filterListTableView setFrame:CGRectMake(0, 0, self.view.frame.size.width, kOverlayTableViewRowHeight)];
    }
   
    return YES;
}
....

      2. 編譯並執行

--------------------------------------------------------------------------------

B. 調整濾鏡表單水平擺放的 FilterCell

      1. 新增一個類別來放置 global 變數
          a. Xcode > File > New > File...
              > iOS > Cocoa Touch > Objective-C class > Next
            Class: GlobalDataClass
            Subclass of: NSObject
           > Next > Create

           b. 開啓 GlobalDataClass.h 檔案, 修改如下:
#import <Foundation/Foundation.h>

@interface GlobalDataClass : NSObject
{
    //@add: array for storage filterCells
    NSMutableArray *filterCellArray;

}

//@add
@property (nonatomic, strong) NSMutableArray *filterCellArray;

//@add
+ (GlobalDataClass *)getInstance;

@end

          c. 開啓 GlobalDataClass.m 檔案, 修改如下:
#import "GlobalDataClass.h"

@implementation GlobalDataClass

//@add
@synthesize filterCellArray = _filterCellArray;

//@add
+ (GlobalDataClass *)getInstance
{
    static GlobalDataClass *instance = nil;
   
    @synchronized(self)
    {
        if(!instance)
        {
            instance = [[GlobalDataClass alloc] init];
        }
    }  
   
    return instance;
}

@end

---------------------------------------------------------------------------

      2. 開啓 HorizontalTableCell.h 檔案, 修改如下:
#import <UIKit/UIKit.h>
//@add
#import "ConstantDefined.h"
#import "FilterCell.h"

//@add
#import "GlobalDataClass.h"
....

---------------------------------------------------------------------------

      3. 開啓 HorizontalTableCell.m 檔案, 修改如下:
....
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
....
    //@title text: we don't need to load that, just read it from our array of filters. 
    cell.titleLabel.text = [currentFilter objectForKey:@"Title"];
   
    //@add for storage filterCells
    //
    // 當沒有找到相同的 titleLabel.text 時, 才將新的 filterCell 存入 Array 裡.

    GlobalDataClass *dataObj = [GlobalDataClass getInstance];

    BOOL saveCell = YES;
    for (FilterCell* filterCell in dataObj.filterCellArray) {
        if ([filterCell.titleLabel.text isEqualToString:cell.titleLabel.text])
        {
            saveCell = NO;
            break;
        }
    }
    if (saveCell) {
        [dataObj.filterCellArray addObject:cell];
    }
    NSLog(@"dataObj.filterCellArray.count = %d", dataObj.filterCellArray.count);
   
    return cell;
}
....
(update: 2012/04/20)

備註:
1. 當找到相同titleLabel.text 時, 如果刪除舊的 filterCell, 程式在執行時,
    於拖拉"濾鏡表單" 時會 crash 掉.

2. 如果一律將 filterCell 儲存起來, 程式在執行時, 於每次拖拉"濾鏡表單" 時,
    都會將新產生的 filterCell (即使 titleLabel.text 名稱相同)存入 Array 裡. 

---------------------------------------------------------------------------

      4. 開啓 ViewController.h 檔案, 修改如下:
....
//@add
#import "Filter4CamHelper.h"
#import "ConstantDefined.h"
#import "HorizontalTableCell.h"
#import "GlobalDataClass.h"
....

---------------------------------------------------------------------------

      5. 開啓 ViewController.m 檔案, 修改如下:
....
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    //@add
    GlobalDataClass *dataObj = [GlobalDataClass getInstance];
    CGFloat filterCellRotationAngle; // filterCell Rotation Angle
   
    //@update
    // 設備垂直擺放
    if (interfaceOrientation == UIDeviceOrientationPortrait)
    {
        //[self.filterLensImageView setFrame:CGRectMake(20, 80, 280, 280)];
        //@update: Tune UI
        [self.filterLensImageView setFrame:CGRectMake(20, 120, 280, 280)];
       
        //@update: Tune for Orientation
        self.filterListTableView.transform = CGAffineTransformMakeRotation(-M_PI * 2.0);
        [self.filterListTableView setFrame:CGRectMake(0, 0, self.view.frame.size.width, kOverlayTableViewRowHeight)];
       
        //@add
        filterCellRotationAngle = M_PI * 0.5;
    }
    // 設備垂直 180 度擺放
    else if (interfaceOrientation == UIDeviceOrientationPortraitUpsideDown) {       
        //[self.filterLensImageView setFrame:CGRectMake(20, 80, 280, 280)];
        //@update: Tune UI
        [self.filterLensImageView setFrame:CGRectMake(20, 120, 280, 280)];
       
        //@update: Tune for Orientation
        self.filterListTableView.transform = CGAffineTransformMakeRotation(-M_PI * 2.0);
        [self.filterListTableView setFrame:CGRectMake(0, 0, self.view.frame.size.width, kOverlayTableViewRowHeight)];
       
        //@add
        filterCellRotationAngle = M_PI * 0.5;
    }
    // 設備水平向右擺放
    else if (interfaceOrientation == UIDeviceOrientationLandscapeRight) {       
        //[self.filterLensImageView setFrame:CGRectMake(80, 20, 280, 280)];
        //@update: Tune UI
        [self.filterLensImageView setFrame:CGRectMake(120, 20, 280, 280)];
       
        //@update: Tune for Orientation
        self.filterListTableView.transform = CGAffineTransformMakeRotation(M_PI * 0.5);
        [self.filterListTableView setFrame:CGRectMake(0, 0, kOverlayTableViewRowHeight, self.view.frame.size.width)];
       
        //@add
        filterCellRotationAngle = 0.0;
    }
    // 設備水平向左擺放
    else if (interfaceOrientation == UIDeviceOrientationLandscapeLeft) {       
        //[self.filterLensImageView setFrame:CGRectMake(80, 20, 280, 280)];
        //@update: Tune UI
        [self.filterLensImageView setFrame:CGRectMake(120, 20, 280, 280)];
       
        //@update: Tune for Orientation
        self.filterListTableView.transform = CGAffineTransformMakeRotation(M_PI * 0.5);
        [self.filterListTableView setFrame:CGRectMake(0, 0, kOverlayTableViewRowHeight, self.view.frame.size.width)];
       
        //@add
        filterCellRotationAngle = 0.0;
    }
    // 其它 (UIDeviceOrientationFaceUp, UIDeviceOrientationFaceDown, UIDeviceOrientationUnknown)
    else {
        //[self.filterLensImageView setFrame:CGRectMake(80, 20, 280, 280)];
        //@update: Tune UI
        [self.filterLensImageView setFrame:CGRectMake(120, 20, 280, 280)];
       
        //@update: Tune for Orientation
        self.filterListTableView.transform = CGAffineTransformMakeRotation(M_PI * 0.5);
        [self.filterListTableView setFrame:CGRectMake(0, 0, self.view.frame.size.width, kOverlayTableViewRowHeight)];
       
        //@add
        filterCellRotationAngle = M_PI * 0.5;
    }
   
    //@add
    if (dataObj.filterCellArray.count > 0) {
        for (FilterCell* filterCell in dataObj.filterCellArray) {
            filterCell.transform = CGAffineTransformMakeRotation(filterCellRotationAngle);
        }
    }
   
    return YES;
}
....

---------------------------------------------------------------------------

      6. 編譯並執行:

2012年4月18日 星期三

Filter4Cam 實作: 15. 調整濾鏡表單位置之一

since: 2012/04/18
update: 2012/04/18


A. 說明:
     目前當 iOS 設備垂直擺放時, 濾鏡表單位於螢幕的最下方, 預留的拍攝按鈕位置會在
     螢幕的最上方,  雖然這樣方便選取濾鏡, 但是在按下拍攝按鈕的過程中, 手容易遮到
     螢幕的部分視線, 因此決定將濾鏡表單位置移至螢幕最上方. 

-------------------------------------------------------------------------------

B. 開啓 ViewController.m 檔案, 修改如下:
....
- (UITableView *)filterListTableView
{  
    if (_filterListTableView == nil) {
        //_filterListTableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 380, self.view.frame.size.width, 100) style:UITableViewStyleGrouped];
       
        //@update: kOverlayTableViewRowHeight = 106
        /*
        _filterListTableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 374, self.view.frame.size.width, kOverlayTableViewRowHeight) style:UITableViewStyleGrouped];
        */
        //@update: Tune UI
        _filterListTableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, kOverlayTableViewRowHeight) style:UITableViewStyleGrouped];
    }
   
    return _filterListTableView;
}
....
- (void)cameraOverlay
{  
    //@update: comment it
    //[self.filterLensImageView setFrame:CGRectMake(20, 80, 280, 280)];
    [self.view addSubview:self.filterLensImageView];
....
}

....
- (void)filterOrientationTransform:(CIImage *)sourceImage
{
    UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
   
    // 設備垂直擺放
    if (orientation == UIDeviceOrientationPortrait)
    {
        //@add
        self.isPreviousOrientationLandscape = NO;
       
        /*
        [self.coreImageContext drawImage:sourceImage inRect:CGRectMake(23.5, 123.5, 274, 274)
                                fromRect:CGRectMake(23, -517.5, 274, 274)];
         */
        //@update: Tune UI
        [self.coreImageContext drawImage:sourceImage inRect:CGRectMake(23.5, 83.5, 274, 274)
                                // x 越小, 濾鏡越向右; y 負越多, 濾鏡越向上
                                fromRect:CGRectMake(23, -557.5, 274, 274)];
    }
    // 設備垂直 180 度擺放
    else if (orientation == UIDeviceOrientationPortraitUpsideDown) {
       
        //@add
        self.isPreviousOrientationLandscape = NO;
       
        /*
        [self.coreImageContext drawImage:sourceImage inRect:CGRectMake(23.5, 123.5, 274, 274)
                                fromRect:CGRectMake(-458.5, 123, 274, 274)];
         */
        //@update: Tune UI
        [self.coreImageContext drawImage:sourceImage inRect:CGRectMake(23.5, 83.5, 274, 274)
                                // x 負越多, 濾鏡越向左; y 越多, 濾鏡越向上
                                fromRect:CGRectMake(-458.5, 83, 274, 274)];
    }
    // 設備水平向右擺放
    else if (orientation == UIDeviceOrientationLandscapeRight) {

        //@add
        self.isPreviousOrientationLandscape = YES;
       
        /*
        [self.coreImageContext drawImage:sourceImage inRect:CGRectMake(83.5, 23.5, 274, 274)
                                fromRect:CGRectMake(-557, -457.5, 274, 274)];
         */
        //@update: Tune UI
        [self.coreImageContext drawImage:sourceImage inRect:CGRectMake(123.5, 23.5, 274, 274)
                                // x 負越多, 濾鏡越向右; y 負越多, 濾鏡越向上
                                fromRect:CGRectMake(-517, -457.5, 274, 274)];
    }
    // 設備水平向左擺放(最穩定)
    else if (orientation == UIDeviceOrientationLandscapeLeft) {

        //@add
        self.isPreviousOrientationLandscape = YES;
       
        /*
        [self.coreImageContext drawImage:sourceImage inRect:CGRectMake(83.5, 23.5, 274, 274)
                                fromRect:CGRectMake(83.5, 23.5, 274, 274)];
        */
        //@update: Tune UI
        [self.coreImageContext drawImage:sourceImage inRect:CGRectMake(123.5, 23.5, 274, 274)
                                // x 越大, 濾鏡越向左; y 越多, 濾鏡越向上
                                fromRect:CGRectMake(123.5, 23.5, 274, 274)];
    }
    // 其它 (UIDeviceOrientationFaceUp, UIDeviceOrientationFaceDown, UIDeviceOrientationUnknown)
    else {   
       
        //@在此不記錄上一次設備的方向
       
        //@add:上一次設備為水平擺放
        if (self.isPreviousOrientationLandscape == YES) {

            /*
            [self.coreImageContext drawImage:sourceImage inRect:CGRectMake(83.5, 23.5, 274, 274)
                                    fromRect:CGRectMake(83.5, 23.5, 274, 274)];
             */
            //@update: Tune UI
            [self.coreImageContext drawImage:sourceImage inRect:CGRectMake(123.5, 23.5, 274, 274)
                                    // x 越大, 濾鏡越向左; y 越多, 濾鏡越向上
                                    fromRect:CGRectMake(123.5, 23.5, 274, 274)];
        }
        //@add:上一次設備為垂直擺放
        else {

            /*
            [self.coreImageContext drawImage:sourceImage inRect:CGRectMake(23.5, 123.5, 274, 274)
                                    fromRect:CGRectMake(23.5, 123.5, 274, 274)];
             */
            //@update: Tune UI
            [self.coreImageContext drawImage:sourceImage inRect:CGRectMake(23.5, 83.5, 274, 274)
                                    // x 越大, 濾鏡越向左; y 越多, 濾鏡越向上
                                    fromRect:CGRectMake(23.5, 83.5, 274, 274)];
        }
    }
}
....
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{   
    //@update
    // 設備垂直擺放
    if (interfaceOrientation == UIDeviceOrientationPortrait)
    {
        //[self.filterLensImageView setFrame:CGRectMake(20, 80, 280, 280)];
        //@update: Tune UI
        [self.filterLensImageView setFrame:CGRectMake(20, 120, 280, 280)];
    }
    // 設備垂直 180 度擺放
    else if (interfaceOrientation == UIDeviceOrientationPortraitUpsideDown) {
        //[self.filterLensImageView setFrame:CGRectMake(20, 80, 280, 280)];
        //@update: Tune UI
        [self.filterLensImageView setFrame:CGRectMake(20, 120, 280, 280)];
    }
    // 設備水平向右擺放
    else if (interfaceOrientation == UIDeviceOrientationLandscapeRight) {
        //[self.filterLensImageView setFrame:CGRectMake(80, 20, 280, 280)];
        //@update: Tune UI
        [self.filterLensImageView setFrame:CGRectMake(120, 20, 280, 280)];
    }
    // 設備水平向左擺放
    else if (interfaceOrientation == UIDeviceOrientationLandscapeLeft) {
        //[self.filterLensImageView setFrame:CGRectMake(80, 20, 280, 280)];
        //@update: Tune UI
        [self.filterLensImageView setFrame:CGRectMake(120, 20, 280, 280)];
    }
    // 其它 (UIDeviceOrientationFaceUp, UIDeviceOrientationFaceDown, UIDeviceOrientationUnknown)
    else {
        //[self.filterLensImageView setFrame:CGRectMake(80, 20, 280, 280)];
        //@update: Tune UI
        [self.filterLensImageView setFrame:CGRectMake(120, 20, 280, 280)];
    }
   
    return YES;
}
....

-------------------------------------------------------------------------------

C. 編譯並執行
     垂直擺放
     水平擺放(需要再調整)

2012年4月17日 星期二

OpenGL ES 入門: 六. 紋理及紋理映射之二

since: 2012/04/16
update: 2012/04/17

reference:
1. 原文:
iPhone Development: OpenGL ES From the Ground Up, Part 6: Textures and Texture Mapping

2. 翻譯:
從零開始學習OpenGL ES之六 – 紋理及紋理映射

紋理及紋理映射: 更多的映射, 平鋪和箝位

A. 更多的映射方式
      1. 上個例子中這個圖像都被映射到繪製的正方形上. 那是因為設定的紋理坐標
          所決定的. 我們可以改變坐標陣列僅使用來源圖像中心部分.

          開啓 ViewController.m 檔案, 修改如下:
....
// 紋理映射
- (void)TextureMapping
{
.... 
    static const Vertex3D vertices[] = {
        {-1.0,  1.0, -0.0},
        { 1.0,  1.0, -0.0},
        {-1.0, -1.0, -0.0},
        { 1.0, -1.0, -0.0}
    };
   
    static const Vector3D normals[] = {
        {0.0, 0.0, 1.0},
        {0.0, 0.0, 1.0},
        {0.0, 0.0, 1.0},
        {0.0, 0.0, 1.0}
    };
   
    // Feel free to comment these texture coordinates out and use one
    // of the ones below instead, or play around with your own values.
    /*
    static const GLfloat texCoords[] = {
        0.0, 1.0,
        1.0, 1.0,
        0.0, 0.0,
        1.0, 0.0
    };
    */
   
    static const GLfloat texCoords[] = {
        0.25, 0.75,
        0.75, 0.75,
        0.25, 0.25,
        0.75, 0.25
    };   
   
    glLoadIdentity();
    glTranslatef(0.0, 0.0, -3.0);
    glRotatef(rot, 1.0, 1.0, 1.0); 
....
}
....

      編譯並執行:
      銀幕上只顯示了紋理的中心部分.

      2. 類似地, 如果我們只希望顯示紋理的左下部:
          開啓 ViewController.m 檔案, 修改如下:
....
// 紋理映射
- (void)TextureMapping
{
.... 
    static const Vertex3D vertices[] = {
        {-1.0,  1.0, -0.0},
        { 1.0,  1.0, -0.0},
        {-1.0, -1.0, -0.0},
        { 1.0, -1.0, -0.0}
    };
   
    static const Vector3D normals[] = {
        {0.0, 0.0, 1.0},
        {0.0, 0.0, 1.0},
        {0.0, 0.0, 1.0},
        {0.0, 0.0, 1.0}
    };
   
    // Feel free to comment these texture coordinates out and use one
    // of the ones below instead, or play around with your own values.    
    // 顯示完整的紋理
    /*
    static const GLfloat texCoords[] = {
        0.0, 1.0,
        1.0, 1.0,
        0.0, 0.0,
        1.0, 0.0
    };
    */
    
    // 顯示紋理的中心部分
    /*
    static const GLfloat texCoords[] = {
        0.25, 0.75,
        0.75, 0.75,
        0.25, 0.25,
        0.75, 0.25
    };    
    */
  
    // 顯示紋理的左下部
    static const GLfloat texCoords[] = {
        0.0, 0.5,
        0.5, 0.5,
        0.0, 0.0,
        0.5, 0.0
    };
   
    glLoadIdentity();
    glTranslatef(0.0, 0.0, -3.0);
    glRotatef(rot, 1.0, 1.0, 1.0); 
....
}
....

      編譯並執行:

--------------------------------------------------------------------------------

B. 還有更多的方式
      1. 說明:
          我們可以通過非常規方式的映射來扭曲紋理.
 
      2. 開啓 ViewController.m 檔案, 修改如下:
....
- (void)TextureMapping
{
    NSLog(@"ViewController => TextureMapping");
   
    //@update for more mapping
    //static GLfloat rot = 0.0;
   
    glColor4f(0.0, 0.0, 0.0, 0.0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
   
    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_NORMAL_ARRAY);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
   
    /*
    static const Vertex3D vertices[] = {
        {-1.0,  1.0, -0.0},
        { 1.0,  1.0, -0.0},
        {-1.0, -1.0, -0.0},
        { 1.0, -1.0, -0.0}
    };
   
    static const Vector3D normals[] = {
        {0.0, 0.0, 1.0},
        {0.0, 0.0, 1.0},
        {0.0, 0.0, 1.0},
        {0.0, 0.0, 1.0}
    };
    */
    //@update for more mapping
    static const Vertex3D vertices[] = {
        {-1.0,  1.0, -0.0},
        { 1.0,  1.0, -0.0},
        { 0.0, -1.0, -0.0},
       
    };
    static const Vector3D normals[] = {
        {0.0, 0.0, 1.0},
        {0.0, 0.0, 1.0},
        {0.0, 0.0, 1.0},
    };
   
    // Feel free to comment these texture coordinates out and use one
    // of the ones below instead, or play around with your own values.   
    // 顯示完整的紋理
    /*
    static const GLfloat texCoords[] = {
        0.0, 1.0,
        1.0, 1.0,
        0.0, 0.0,
        1.0, 0.0
    };
    */
   
    // 顯示紋理的中心部分
    /*
    static const GLfloat texCoords[] = {
        0.25, 0.75,
        0.75, 0.75,
        0.25, 0.25,
        0.75, 0.25
    };   
    */
   
    // 顯示紋理的左下部
    /*
    static const GLfloat texCoords[] = {
        0.0, 0.5,
        0.5, 0.5,
        0.0, 0.0,
        0.5, 0.0
    };
    */
    //@update for more mapping
    static const GLfloat texCoords[] = {
        0.0, 1.0,
        1.0, 0.0,
        0.0, 0.0,
    };
     
    glLoadIdentity();
    glTranslatef(0.0, 0.0, -3.0);
    //@update for more mapping
    //glRotatef(rot, 1.0, 1.0, 1.0);
   
    //@update for more mapping
    glBindTexture(GL_TEXTURE_2D, texture[0]);
   
    glVertexPointer(3, GL_FLOAT, 0, vertices);
    glNormalPointer(GL_FLOAT, 0, normals);
    glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
   
    //glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
    //@update for more mapping
    glDrawArrays(GL_TRIANGLES, 0, 3);

    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_NORMAL_ARRAY);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
   
    //@update for more mapping
    /*
    static NSTimeInterval lastDrawTime;
    if (lastDrawTime)
    {
        NSTimeInterval timeSinceLastDraw = [NSDate timeIntervalSinceReferenceDate] - lastDrawTime;
        rot +=  60 * timeSinceLastDraw;               
    }
    lastDrawTime = [NSDate timeIntervalSinceReferenceDate];
     */
}
....

      3. 編譯並執行:
          紋理正方形左下角的弧形花紋現在處於三角形的底部了.
          (紋理上的任何一點都可以映射到多邊形的任何一點)

--------------------------------------------------------------------------------

C. 平鋪(貼磚)和箝位
      1. 說明:
          我們的紋理坐標系統在兩個軸上都是從 0.01.0, 如果設置超出此範圍的值時,
          根據視圖的設置方式有兩種選擇
: 平鋪 Tiling (也叫重複)或箝位 Clamping.

      2. 平鋪(也叫重複)
           a. 開啓 ViewController.m 檔案, 修改如下:
....
-(void)setupView:(GLView *)view
{
....
    // Configuring the Image
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
   
    //@add for Tiling
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
....
}
....
- (void)TextureMapping
{
    NSLog(@"ViewController => TextureMapping");
   
    static GLfloat rot = 0.0;
   
    glColor4f(0.0, 0.0, 0.0, 0.0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
   
    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_NORMAL_ARRAY);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
   
    static const Vertex3D vertices[] = {
        {-1.0,  1.0, -0.0},
        { 1.0,  1.0, -0.0},
        {-1.0, -1.0, -0.0},
        { 1.0, -1.0, -0.0}
    };
   
    static const Vector3D normals[] = {
        {0.0, 0.0, 1.0},
        {0.0, 0.0, 1.0},
        {0.0, 0.0, 1.0},
        {0.0, 0.0, 1.0}
    };
   
    // Feel free to comment these texture coordinates out and use one
    // of the ones below instead, or play around with your own values.   
    // 顯示完整的紋理
    /*
    static const GLfloat texCoords[] = {
        0.0, 1.0,
        1.0, 1.0,
        0.0, 0.0,
        1.0, 0.0
    };
    */
   
    // 顯示紋理的中心部分
    /*
    static const GLfloat texCoords[] = {
        0.25, 0.75,
        0.75, 0.75,
        0.25, 0.25,
        0.75, 0.25
    };   
    */
   
    // 顯示紋理的左下部
    /*
    static const GLfloat texCoords[] = {
        0.0, 0.5,
        0.5, 0.5,
        0.0, 0.0,
        0.5, 0.0
    };
    */
   
    //@update for Tiling
    static const GLfloat texCoords[] = {
        0.0, 2.0,
        2.0, 2.0,
        0.0, 0.0,
        2.0, 0.0
    };
   
    glLoadIdentity();
    glTranslatef(0.0, 0.0, -3.0);
    glRotatef(rot, 1.0, 1.0, 1.0);
   
    glVertexPointer(3, GL_FLOAT, 0, vertices);
    glNormalPointer(GL_FLOAT, 0, normals);
    glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
   
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
   
    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_NORMAL_ARRAY);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
   
    static NSTimeInterval lastDrawTime;
    if (lastDrawTime)
    {
        NSTimeInterval timeSinceLastDraw = [NSDate timeIntervalSinceReferenceDate] - lastDrawTime;
        rot +=  60 * timeSinceLastDraw;               
    }
    lastDrawTime = [NSDate timeIntervalSinceReferenceDate];
}
....

           b. 編譯並執行:

      3. 箝位
           a. 說明
               讓 OpenGL ES 簡單地將超過 1.0 的值限制為1.0, 任何低於 0.0 的值限制為 0.0.
               這實際會引起邊緣像素重複, 從而產生奇怪的效果
.

           b. 開啓 ViewController.m 檔案, 修改如下:
....
-(void)setupView:(GLView *)view
{
....
    // Configuring the Image
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
   
    //@add for Tiling
    /*
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    */

    //@add for Clamping
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
....
}
....

           c. 編譯並執行: