阅读 86

OpenGL ES 案例:分别用OpenGL ES 和CoreAnimation实现立方体旋转

上一篇博客里分享了 OpenGL ES 简单案例:GLKit 加载图片, 在此基础上我们实现一个立方体贴图+旋转。

先看一下效果吧:


一、使用 OpenGL ES 实现立方体旋转

 立方体每个面贴图和上个案例 OpenGL ES 简单案例:GLKit 加载图片 是完全一样的,这里就不再介绍了,在此基础上我们需要设置立方体的顶点数据,然后在-(void)glkView:(GLKView *)view drawInRect:(CGRect)rect不断的更新模型视图变换矩阵就OK了。

实现流程图


设置顶点数据

立方体六个面的顶点数组:

GLfloat vertexData[] = {
       -0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
       0.5f, -0.5f, -0.5f, 1.0f, 0.0f,
       0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
       0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
       -0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
       -0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
       
       -0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
       0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
       0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
       0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
       -0.5f, 0.5f, 0.5f, 0.0f, 1.0f,
       -0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
       
       -0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
       -0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
       -0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
       -0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
       -0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
       -0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
       
       0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
       0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
       0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
       0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
       0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
       0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
       
       -0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
       0.5f, -0.5f, -0.5f, 1.0f, 1.0f,
       0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
       0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
       -0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
       -0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
       
       -0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
       0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
       0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
       0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
       -0.5f, 0.5f, 0.5f, 0.0f, 0.0f,
       -0.5f, 0.5f, -0.5f, 0.0f, 1.0f
   };


复制代码

updaterRenderSence

    //设置视图矩阵变换的的角度
    _angle =(_angle +_time)%360;
    GLKMatrix4 modelViewMatrix =GLKMatrix4Translate(GLKMatrix4Identity, 0, 0, -4.0);
    modelViewMatrix =GLKMatrix4Rotate(modelViewMatrix, GLKMathDegreesToRadians(_angle), 0.5, 0.5, 0.5);
    // 更新模型视图矩阵
    cEffect.transform.modelviewMatrix =modelViewMatrix;复制代码

GLKViewDelegate

循环调用 updaterRenderSence

-(void)glkView:(GLKView *)view drawInRect:(CGRect)rect{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
    glEnable(GL_DEPTH_TEST);
    
    //旋转
    [self updaterRenderSence];
    
    [cEffect prepareToDraw];
    
    glDrawArrays(GL_TRIANGLES, 0, 36);
    
}复制代码


二、使用Core Animation实现立方体旋转

使用 Core Animation 实现立方体旋转可能大家就更熟悉了,就是使用CATransform3D 实现3D变换,把立方体放在父视图中,使用superView.layer.subLayerTranform 实现对子视图的统一变换。

具体实现代码如下:

#import "ViewController.h"
#import <OpenGLES/ES3/gl.h>
#import <OpenGLES/ES3/glext.h>

@interface ViewController ()

@property (nonatomic, strong) UIView *contentView;

@end

@implementation ViewController

#pragma mark - life cyle 1、控制器生命周期
- (void)viewDidLoad {
    [super viewDidLoad];
    self.contentView =[[UIView alloc]initWithFrame:self.view.bounds];
    self.contentView.backgroundColor =UIColor.redColor;
    [self.view addSubview:self.contentView];
    
    //添加立方体各个面
    CATransform3D tranform =CATransform3DMakeTranslation(0, 0, 100);
    [self addFace:0 tranform:tranform];
    
    tranform =CATransform3DMakeTranslation(100, 0, 0);
    tranform =CATransform3DRotate(tranform, M_PI_2, 0, 1, 0);
    [self addFace:1 tranform:tranform];
    
    tranform =CATransform3DMakeTranslation(0, -100, 0);
    tranform =CATransform3DRotate(tranform, M_PI_2, 1, 0, 0);
    [self addFace:2 tranform:tranform];
    
    tranform =CATransform3DMakeTranslation(0, 100, 0);
    tranform =CATransform3DRotate(tranform, -M_PI_2, 1, 0, 0);
    [self addFace:3 tranform:tranform];
    
    tranform =CATransform3DMakeTranslation(-100, 0, 0);
    tranform =CATransform3DRotate(tranform, -M_PI_2, 0, 1, 0);
    [self addFace:4 tranform:tranform];
    
    tranform =CATransform3DMakeTranslation(0, 0, -100);
    tranform =CATransform3DRotate(tranform, M_PI, 0, 1, 0);
    [self addFace:5 tranform:tranform];
    
    __block NSInteger angle =0;
    
    NSTimer *timer =[NSTimer scheduledTimerWithTimeInterval:1.0/60.0 repeats:YES block:^(NSTimer * _Nonnull timer) {
        angle =(angle + 2)%360;
        self.contentView.layer.sublayerTransform =CATransform3DMakeRotation(M_PI/180.0f * angle, 0.4, 0.5, 0.6);
    }];
    [[NSRunLoop mainRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];

}

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
}

- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    
}

#pragma mark - 2、不同业务处理之间的方法以
-(void)addFace:(NSInteger)index tranform:(CATransform3D)tranform{
    NSString *filePath =[[NSBundle mainBundle]pathForResource:@"james" ofType:@"jpeg"];
    UIImageView *imageView =[[UIImageView alloc]initWithFrame:CGRectMake(0, 0, 200, 200)];
    imageView.image =[UIImage imageWithContentsOfFile:filePath];
    [self.contentView addSubview:imageView];
    imageView.center=self.contentView.center;
    imageView.layer.transform =tranform;
}

#pragma mark - Network 3、网络请求

#pragma mark - Action Event 4、响应事件

#pragma mark - Call back 5、回调事件

#pragma mark - Delegate 6、代理、数据源

#pragma mark - interface 7、UI处理

#pragma mark - lazy loading 8、懒加载

@end复制代码

运行效果和上面GLKit实现是一样的。

CATransform3D

CoreAnimation 内容很多,大家感兴趣可以翻阅官方文档或相关博客。这里简单分享一下 CATransform3D 相关的知识。

CATransform3DQuartzCore下声明的一个结构体,文档对它的描述:

The transform matrix is used to rotate, scale, translate, skew, and project the layer content. Functions are provided for creating, concatenating, and modifying CATransform3D data.

它是用来对一个layer的内容进行旋转、缩放、平移、扭转变化的变形矩阵,它提供了一些创建、叠加和修改(layer的)CATransform3D数据的函数。

项目中我们使用CATransform3D 可以实现图形的旋转 缩放 平移 动画 矩阵 绘制 图层 转换 形变。

CATransform3D的结构体

/* Homogeneous three-dimensional transforms. */

struct CATransform3D
{
  CGFloat m11, m12, m13, m14;
  CGFloat m21, m22, m23, m24;
  CGFloat m31, m32, m33, m34;
  CGFloat m41, m42, m43, m44;
};

typedef struct CA_BOXABLE CATransform3D CATransform3D;


复制代码

从API中我们可以看到CATransform3D定义了一个 4*4的矩阵,参数含义如下:

m11:x轴方向进行缩放

m12:和m21一起决定z轴的旋转

m13:和m31一起决定y轴的旋转

m14:

m21:和m12一起决定z轴的旋转

m22:y轴方向进行缩放

m23:和m32一起决定x轴的旋转

m24:

m31:和m13一起决定y轴的旋转

m32:和m23一起决定x轴的旋转

m33:z轴方向进行缩放

m34:透视效果m34= -1/D,D越小,透视效果越明显,必须在有旋转效果的前提下,才会看到透视效果

m41:x轴方向进行平移

m42:y轴方向进行平移

m43:z轴方向进行平移

m44:初始为1


CATransform3D 中的属性和方法

//初始化一个transform3D对象,不做任何变换
const CATransform3D CATransform3DIdentity;
//判断一个transform3D对象是否是初始化的对象
bool CATransform3DIsIdentity (CATransform3D t);
//比较两个transform3D对象是否相同
bool CATransform3DEqualToTransform (CATransform3D a, CATransform3D b);
//将两个 transform3D对象变换属性进行叠加,返回一个新的transform3D对象
CATransform3D CATransform3DConcat (CATransform3D a, CATransform3D b);复制代码

平移变换

//返回一个平移变换的transform3D对象 tx,ty,tz对应x,y,z轴的平移
CATransform3D CATransform3DMakeTranslation (CGFloat tx, CGFloat ty, CGFloat tz);
//在某个transform3D变换的基础上进行平移变换,t是上一个transform3D,其他参数同上
CATransform3D CATransform3DTranslate (CATransform3D t, CGFloat tx, CGFloat ty, CGFloat tz);复制代码

缩放变换

//x,y,z分别对应x轴,y轴,z轴的缩放比例
CATransform3D CATransform3DMakeScale (CGFloat sx, CGFloat sy, CGFloat sz);
//在一个transform3D变换的基础上进行缩放变换,其他参数同上
CATransform3D CATransform3DScale (CATransform3D t, CGFloat sx, CGFloat sy, CGFloat sz);复制代码

旋转变换

//angle参数是旋转的角度,为弧度制 0-2π
//x,y,z决定了旋转围绕的中轴,取值为-1——1之间,例如(1,0,0),则是绕x轴旋转(0.5,0.5,0),则是绕x轴与y轴中
//间45度为轴旋转,依次进行计算
CATransform3D CATransform3DMakeRotation (CGFloat angle, CGFloat x, CGFloat y, CGFloat z);
//在一个transform3D的基础上进行旋转变换,其他参数如上
CATransform3D CATransform3DRotate (CATransform3D t, CGFloat angle, CGFloat x, CGFloat y, CGFloat z);复制代码

旋转翻转变换

//将一个旋转的效果进行翻转 
CATransform3D CATransform3DInvert (CATransform3D t);复制代码

CATransform3D与CGAffineTransform的转换

CGAffineTransform是UIKit框架中一个用于变换的矩阵,其作用与CATransform类似,只是其可以直接作用于View,而不用作用于layer,这两个矩阵也可以进行转换,方法如下:
//将一个CGAffinrTransform转化为CATransform3D
CATransform3D CATransform3DMakeAffineTransform (CGAffineTransform m);
//判断一个CATransform3D是否可以转换为CAAffineTransform
bool CATransform3DIsAffine (CATransform3D t);
//将CATransform3D转换为CGAffineTransform
CGAffineTransform CATransform3DGetAffineTransform (CATransform3D t);复制代码


附Demo地址:

Github完整Demo 

03-OpenGL-ES-立方体贴图+旋转

04-CoreAnimation-立方体旋转


文章分类
iOS
文章标签