使用openGL图形库绘制,都需要通过openGL接口向图像显卡提交顶点数据,显卡根据提交的数据绘制出相应的图形。

openGL绘制方式有:直接模式,显示列表,顶点数组,顶点索引。

直接模式:最简单,最直接的模式,但是性能是最差的,因为每绘制一个基本图元都需要提交一次数据;

glBegin(GL_TRIANGLE_STRIP);

glColor3ub(255, 0, 0);

glVertex3f(-0.5f, 0.5f, 0.0f);

glColor3ub(0, 255, 0);

glVertex3f(-0.5f, -0.5f, 0.0f);

glColor3ub(0, 0, 255);

glVertex3f(0.5f, 0.5f, 0.0f);

glColor3ub(255, 0, 255);

glVertex3f(0.5f, -0.5f, 0.0f);

glEnd();

上面就是用直接模式绘制一个三角形带的所有openGL命令,如果要绘制无数个三角形,那么函数调用的开销是巨大的,而且这样的写法让顶点数据非常不容易扩展和修改,所以基本上这种模式不可能用在实际的用途中。

显示列表:直接模式在每次绘制的时候,都需要将顶点数组从cpu端重新发送到gpu端,如果每次数据都没有任何变化,这种重复的发送就显得没有意义而且低效。显示列表就是为了解决这个重复发送的性能问题,显示列表相当于把一组绘制命令存储在服务器端(gpu端),每次只需要发送一个调用命令,而不需要重复发送所有顶点数据,就可以执行已经预定好的绘制命令了。虽然显示列表解决了不用重发发送顶点数据的问题,但是缺点也是显而易见的,就是显示列表一旦定义好,就无法被修改,因此显示列表只适用于那些不会被修改的绘制命令。而且显示列表和直接模式依然具有相同的问题,就是函数调用开销和难以扩展和修改。只是相当于命令直接在gpu端执行,减少了从cpu发送gpu的过程而已。

定义一个显示列表:

glNewList (listName, GL_COMPILE);

glColor3f (1.0, 0.0, 0.0);

glBegin (GL_TRIANGLES);

glVertex2f (0.0, 0.0);

glVertex2f (1.0, 0.0);

glVertex2f (0.0, 1.0);

glEnd ();

glTranslatef (1.5, 0.0, 0.0);

glEndList ();

执行一个显示列表:

glCallList (listName);

删除一个显示列表:

glDeleteLists(listName, 1);

顶点数组:由于直接模式的局限性,openGL提供了另一种更加高效的绘制模式,顶点数组。

顶点数组顾名思义就是允许我们将我们的顶点数据放置到一个数组中,一次性提交给显卡进行绘制。这样只需要极少量的函数调用,而且数组全部聚合在一起,也更加容易修改和扩展。

// 先定义顶点位置,颜色数组,纹理数组的顶点相关数据:

GLfloat vertexes[] = {
0.0f, 0.0f, 0.0f, 1.0f,
0.0f, 512, 0.0f, 1.0f,
1024, 512, 0.0f, 1.0f,
1024, 0.0f, 0.0f, 1.0f
};
GLfloat colores[] = {
1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f
};
GLfloat texCoordes[] = {
0.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f,
1.0f, 1.0f
};

// 0,1,2代表着色器的input的location,分别代表顶点位置,顶点颜色,顶点纹理坐标(这里使用的是可编程管线,如果使用固定管线,指定方式也是类似的)

// 为0,1,2指定相应的数据

glEnableVertexAttribArray(0); // 固定管线使用glEnableClientState(GL_VERTEX_ARRAY)
glEnableVertexAttribArray(1); // 固定管线使用glEnableClientState(GL_COLOR_ARRAY)
glEnableVertexAttribArray(2); // 固定管线使用glEnableClientState(GL_TEXTURE_COORD_ARRAY)
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, vertexes); // 固定管线使用glVertexPointer(4, GL_FLOAT, 0, vertexes);
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, colores); // 固定管线使用glColorPointer(4, GL_FLOAT, 0, colores);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 0, texCoordes); // 固定管线使用glTexCoordPointer(2, GL_FLOAT, 0, texCoordes);

// 绘制一个四边形

glDrawArrays(GL_QUADS, 0, 4);

这里将位置,颜色,纹理分为三个数组分别存放,我们也可把所有数据放在一个数组中,称之为交错数组:

GLfloat data[] = {
0.0f, 0.0f, 0.0f, 1.0f,    1.0f, 1.0f, 1.0f, 1.0f,   0.0f, 1.0f,
0.0f, 512, 0.0f, 1.0f,    1.0f, 1.0f, 1.0f, 1.0f,   0.0f, 0.0f,
1024, 512, 0.0f, 1.0f,  1.0f, 1.0f, 1.0f, 1.0f,   1.0f, 0.0f,
1024, 0.0f, 0.0f, 1.0f,  1.0f, 1.0f, 1.0f, 1.0f,   1.0f, 1.0f
};

glEnableVertexAttribArray(0); 
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 10 * sizeof(GLfloat), vertexes); // 第四个参数指的是两个位置数据在数组中间距,第五个参数指的是第一个位置数据在数组中的起始位置
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 10 * sizeof(GLfloat), colores + 4); // 第四个参数指的是两个颜色数据在数组中间距,第五个参数指的是第一个颜色数据在数组中的起始位置
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 10 * sizeof(GLfloat), texCoordes + 8); // 第四个参数指的是两个纹理坐标数据在数组中间距,第五个参数指的是第一个纹理坐标数据在数组中的起始位置

// 绘制一个四边形

glDrawArrays(GL_QUADS, 0, 4);

除此之外,交错无数也可以直接使用:

  glInterleavedArrays (GLenum format, GLsizei stride, const GLvoid *pointer);

进行一次性指定,但是数组中数据的构成规则必须和format指定的规则一致。例如:glInterleavedArrays(GL_V2F,0,data); 表示数据组合规则是仅仅2个浮点数的位置数据

顶点索引:顶点数组已经可以为我们提供了方便指定绘制数据的方式,大幅提升了渲染的性能。但是依然还存在一个问题:如果我们需要绘制一个模型,这个模型由无数三角形片构成,大部分三角形都是连续拼接的没有空隙,所以每相邻的两个三角形可能会有拥有一个或者两个完全相同顶点(位置,颜色,纹理坐标都相同)。如果我们使用顶点数组的数据来构成这个模型,我们将为相邻的两个三角形片分别制定6个顶点数据,其中有可能会出现最多两对完全相同的顶点,而这些顶点其实是可以共享的,但却出现了冗余数据。在模型复杂的情况下,冗余数据也是巨大的。于是openGL为我们指定了一种更加灵活的方式,顶点索引数组,即我们只需要创建好必要的顶点数据,顶点数据在数组中的排列也不受图元绘制方式的限制,理论上可以随意排列。然后用索引去对应每一个顶点数据,绘制图元需要提交顶点数据的时候,直接指定顶点索引即可,因为顶点索引会一一映射到顶点数据,这样就消除了冗余的顶点数据,而且以更加灵活的方式进行渲染。

// 指定顶点数据,注意渲染顺序的迎风面是逆时针还是顺时针,这里绘制4个顶点,分别对应顶点数组中的前4个顶点

GLuint indexes = {0, 1, 2, 3};

// 用顶点索引进行绘制的绘制调用

glDrawElements(GL_QUADS, 4, GL_UNSIGNED_INT, indexes);

VBO: 顶点数组加上顶点索引,似乎已经可以完美解决大部分问题,但是图形渲染对性能的追求是永无止境的。虽然使用顶点数组和顶点索引,我们可以一次性提交所有绘制数据,并只需要调用一次绘制命令。但是在数据很大的情况下,我们依然都要从cpu端向gpu端提交大量数据,如果这些数据又几乎不会发生改变,那么这种操作将是极大的性能浪费。

为了减少这种耗时但又无意义的工作,openGL为我们提供了VBO(顶点缓冲对象)来改善这种问题。

使用VBO,可以将我们的顶点数据存放在图像显卡的内存中,而不需要存放在cpu端的内存中,就不需要在每次绘制时,发送大量顶点数据到gpu端了。

// 生成VBO,并为VBO绑定顶点数据

size_t dataSize = sizeof(GLfloat) * vertexCount * 4; // 在图像显卡中需要分配的内存大小
GLuint vbos[1] = { 0 }; // VBO名字

glGenBuffers(1, vbos); // 生成一个可用的VBO名字
if (vbos[0] > 0) // 如果名字可用
{
vertexVBO = vbos[0];

glBindBuffer(GL_ARRAY_BUFFER, vertexVBO); // 绑定当前的VBO,GL_ARRAY_BUFFER是VBO使用的固定参数

glBufferData(GL_ARRAY_BUFFER, dataSize, vertexes, GL_STATIC_DRAW); // 将位置数据绑定到当前的VBO上,dataSize是需要的内存大小,vertexes是顶点的位置数据

// GL_STATIC_DRAW 是一个性能提示参数,这个参数指示了当前VBO的用途,该参数必须是GL_STREAM_DRAWGL_STATIC_DRAW, or GL_DYNAMIC_DRAW之一。openGL会根据该指示,尽可能将数据放置在性能最优的内存中,可能是显存,AGP内存,或者cpu内存中。

// GL_STATIC_DRAW:数据指定一次,并多次被用于绘制。

// GL_STREAM_DRAW:数据指定一次,最多几次用于绘制。

// GL_DYNAMIC_DRAW:数组多次指定,多次用于绘制。

delete[] vertexes;
m_vertexes = nullptr;

CHECK_GL_ERROR();
}

// 使用VBO进行绘制,和使用顶点数组类似

#define BUFFER_OFFSET(offset) ((GLvoid*)(NULL + offset)) // 数据在缓冲区中的偏移位置,和顶点数组指针位置效果类似

glBindBuffer(GL_ARRAY_BUFFER, vertexVBO); // 绑定位置VBO
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0)); // 指定位置数据
glBindBuffer(GL_ARRAY_BUFFER, colorVBO); // 绑定颜色VBO
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0)); // 指定颜色数据
glBindBuffer(GL_ARRAY_BUFFER, textureVBO); // 绑定纹理VBO
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0)); // 指定纹理数据
glBindBuffer(GL_ARRAY_BUFFER, 0);

glDrawArrays(GL_QUADS, 0, m_vertexCount); // 绘制

IBO: 索引缓冲对象,和VBO一样,只是存储的是索引数组。

glGenBuffers(1, &IBO);
if (sphereIBO > 0)
{
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO); // 参数必须使用GL_ELEMENT_ARRAY_BUFFER
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * indexCount, indexes, GL_STATIC_DRAW);

CHECK_GL_ERROR();

delete[] indexes;
indexes = nullptr;
}

// 绘制

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
glDrawElements(GL_QUADS, indexCount, GL_UNSIGNED_INT, BUFFER_OFFSET(0));
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

VAO: 有了VBO和IBO,已经可以很好的解决问题了,但是使用VAO可以使我们的开发更加灵活。VAO其实就是可以绑定VBO和IBO的一个包装对象,我们把有关联的VBO和IBO一起绑定到一个VAO上,我们每次只需要使用VAO就可以进行绘制了。

// 生成VAO

glGenVertexArrays(1, &VAO); // 生成一个VAO
if (VAO > 0) // 如果VAO可用
{
glBindVertexArray(VAO); // 绑定到当前的VAO

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO); // 绑定一个IBO到当前的VAO上

glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);

glBindBuffer(GL_ARRAY_BUFFER, vertexVBO); // 绑定位置VBO到当前的VAO上
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0)); // 指定位置数据
glBindBuffer(GL_ARRAY_BUFFER, colorVBO); // 绑定颜色VBO到当前的VAO上
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0)); // 指定颜色数据
glBindBuffer(GL_ARRAY_BUFFER, textureVBO); // 绑定纹理VBO到当前的VAO上
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0)); // 指定纹理数据

CHECK_GL_ERROR_DEBUG();
}

// 绘制

glBindVertexArray(VAO);
glDrawElements(GL_QUADS, indexCount, GL_UNSIGNED_INT, BUFFER_OFFSET(0));
glBindVertexArray(0);

下面是基于cocos2d的完整的代码:

Sphere.h:

#ifndef __SPHERE__
#define __SPHERE__ #include "cocos2d.h" USING_NS_CC; class Sphere : public cocos2d::Node
{
public:
static Sphere* create(); virtual ~Sphere(); bool init(); virtual void draw(Renderer *renderer, const Mat4& transform, uint32_t flags); virtual void visit(Renderer *renderer, const Mat4& parentTransform, uint32_t parentFlags); private:
GLProgram* m_program;
GLProgram* m_program_planview;
GLuint m_textureName; GLfloat* m_vertexes;
GLfloat* m_colors;
GLfloat* m_texcoordes;
GLuint* m_indexes;
unsigned int m_vertexCount;
unsigned int m_indexCount; float m_sphereLatitude; // 纬度
float m_sphereLongitude; // 经度
unsigned int m_sphereLatitudeCount;
unsigned int m_sphereLongitudeCount;
unsigned int m_sphereQuadCount; float m_sphereRadius; // 半径
float m_spherePerimeter; // 周长
float m_planViewWidth;
float m_planViewHeight; Mat4 m_sphereTransform;
float m_rotateXAngle;
float m_rotateYAngle;
float m_rotateZAngle;
float m_sphereTranslateX;
float m_sphereTranslateY; float m_planViewTranslateX;
float m_planViewTranslateY; bool m_isContinue;
float m_continueRotateY;
float m_continueRotateX;
float m_decreateDetal; std::thread* m_thread_1;
std::thread* m_thread_2;
bool m_isThread1Done;
bool m_isThread2Done; std::vector<float> m_offsetDataList;
std::vector<float> m_offsetDataListCopy; GLuint m_sphereVAO;
GLuint m_sphereIBO;
GLuint m_sphereVertexVBO;
GLuint m_sphereColorVBO;
GLuint m_sphereTextureVBO; bool initProgram();
bool initVertexData(); void createQuaternion(float rotateX, float rotateY, float rotateZ, Quaternion& quat); void generateVertexesSphere(float radius);
void generateVertexesSphereNew(float radius);
void generateTexture();
void generateVAO();
void generateIBO();
void generateVBO(); void transformSphere(float touchOffsetX, float touchOffsetY); void drawBg(const Mat4& transform);
void drawSphere(const Mat4& transform, GLfloat* vertexes);
void drawPlanView(const Mat4& transform, GLfloat* vertexes); void update(); bool onTouchBegan(Touch* touch, Event* event);
void onTouchMoved(Touch* touch, Event* event);
void onTouchEnded(Touch* touch, Event* event); void onThread1Proc();
void onThread2Proc(); void noticeToTransform(float touchOffsetX, float touchOffsetY);
}; #endif

Sphere.cpp:

#include "SphereNew.h"
#include "math.h"
#include <mutex>
#include <condition_variable>
#include <chrono>
#include <thread>
#include <functional> #define MPI 3.1415926f
#define HMPI (3.1415926f / 2.0f)
#define DMPI (3.1415926f * 2.0f)
#define A_TO_R(angle) (3.1415926f / 180.0f * (float)(angle)) #define TEXTURE_WIDTH 1024
#define TEXTURE_HEIGHT 512 #define BUFFER_OFFSET(offset) ((GLvoid*)(NULL + offset)) const GLchar* ccPositionTextureColor_v = " \
attribute vec4 a_position; \n\
attribute vec2 a_texCoord; \n\
attribute vec4 a_color; \n\
\n\
#ifdef GL_ES \n\
varying lowp vec4 v_fragmentColor; \n\
varying mediump vec2 v_texCoord; \n\
#else \n\
varying vec4 v_fragmentColor; \n\
varying vec2 v_texCoord; \n\
#endif \n\
\n\
void main() \n\
{ \n\
gl_Position = CC_MVPMatrix * a_position; \n\
v_fragmentColor = a_color; \n\
v_texCoord = a_texCoord; \n\
} \n\
"; const GLchar* ccPositionTextureColorForSphere_v = " \
uniform vec2 translate; \n\
uniform float radius; \n\
attribute vec4 a_position; \n\ attribute vec2 a_texCoord; \n\
attribute vec4 a_color; \n\
\n\
#ifdef GL_ES \n\
varying lowp vec4 v_fragmentColor; \n\
varying mediump vec2 v_texCoord; \n\
#else \n\
varying vec4 v_fragmentColor; \n\
varying vec2 v_texCoord; \n\
#endif \n\
const float pi = 3.1415926; \n\
const float hpi = 1.5707963; \n\
\n\
void main() \n\
{ \n\
vec4 _position = CC_MVMatrix * a_position; \n\
float _angle1 = atan(_position.x, _position.z); \n\
float _angle2 = atan(_position.z, _position.y); \n\
float _xOffset = _angle1 * radius; \n\
float _yOffset = _position.y * hpi; \n\
_position.x = _xOffset + translate.x; \n\
_position.y = _yOffset + translate.y; \n\
_position.z = 0.0f; \n\
gl_Position = CC_PMatrix * _position; \n\
\n\
v_fragmentColor = a_color; \n\
v_texCoord = a_texCoord; \n\
} \n\
"; const GLchar* ccPositionTextureColor_f = " \
#ifdef GL_ES \n\
precision lowp float; \n\
#endif \n\
\n\
varying vec4 v_fragmentColor; \n\
varying vec2 v_texCoord; \n\
\n\
void main() \n\
{ \n\
vec4 color = v_fragmentColor * texture2D(CC_Texture0, v_texCoord); \n\
color.a = 1.0; \n\
gl_FragColor = color; \n\
} \n\
"; static std::condition_variable cv_transform;
static std::condition_variable cv_notice;
static std::condition_variable cv_transform_sphere;
static std::condition_variable cv_transform_planview;
static std::mutex mx_transform;
static std::mutex mx_transform_planview;
static std::mutex mx_transform_sphere;
static bool b_transform_sphere = false;
static bool b_transform_planview = false; static float _touchOffsetX = 0.0f;
static float _touchOffsetY = 0.0f;
static float _touchOffsetXCopy = 0.0f;
static float _touchOffsetYCopy = 0.0f;
static Mat4 _sphereTransformationCopy; Sphere* Sphere::create()
{
Sphere *pRet = new(std::nothrow) Sphere(); if (pRet && pRet->init())
{
pRet->autorelease();
return pRet;
}
else
{
delete pRet;
pRet = nullptr;
return nullptr;
}
} bool Sphere::init()
{
if (!this->initProgram())
return false; if (!this->initVertexData())
return false; this->generateVertexesSphereNew(m_sphereRadius);
this->generateTexture();
this->generateVBO();
this->generateIBO();
this->generateVAO(); this->transformSphere(, ); auto eventListener = EventListenerTouchOneByOne::create();
eventListener->setSwallowTouches(true);
eventListener->onTouchBegan = CC_CALLBACK_2(Sphere::onTouchBegan, this);
eventListener->onTouchMoved = CC_CALLBACK_2(Sphere::onTouchMoved, this);
eventListener->onTouchEnded = CC_CALLBACK_2(Sphere::onTouchEnded, this);
CCDirector::sharedDirector()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(eventListener, this); /*
m_isThread1Done = false;
m_isThread2Done = false;
m_thread_1 = new std::thread(std::bind(&Sphere::onThread1Proc, this));
m_thread_2 = new std::thread(std::bind(&Sphere::onThread2Proc, this));
*/
m_thread_1 = nullptr;
m_thread_2 = nullptr; return true;
} bool Sphere::initProgram()
{
bool suc = false; m_program = new CCGLProgram();
if (m_program)
{
if (m_program->initWithVertexShaderByteArray(ccPositionTextureColor_v, ccPositionTextureColor_f))
{
if (m_program->link())
{
m_program->updateUniforms();
suc = true;
}
}
}
if (!suc)
{
delete m_program;
m_program = NULL;
} suc = false; m_program_planview = new CCGLProgram();
if (m_program_planview)
{
if (m_program_planview->initWithVertexShaderByteArray(ccPositionTextureColorForSphere_v, ccPositionTextureColor_f))
{
if (m_program_planview->link())
{
m_program_planview->updateUniforms();
suc = true;
}
}
}
if (!suc)
{
delete m_program_planview;
m_program_planview = NULL;
} return suc;
} bool Sphere::initVertexData()
{
m_vertexes = nullptr;
m_colors = nullptr;
m_texcoordes = nullptr;
m_indexes = nullptr;
m_vertexCount = ;
m_indexCount = ; m_sphereTranslateX = 512.0f;
m_sphereTranslateY = 412.0f;
m_rotateYAngle = 0.0f;
m_rotateXAngle = 0.0f;
m_rotateZAngle = 0.0f; m_planViewTranslateX = 512.0f;
m_planViewTranslateY = 150.0f;
m_planViewWidth = 400.0f;
m_planViewHeight = 200.0f; m_sphereRadius = 100.0f;
m_spherePerimeter = 2.0f * 3.1415926f * m_sphereRadius; m_isContinue = false;
m_continueRotateX = 0.0f;
m_continueRotateY = 0.0f;
m_decreateDetal = 0.01f; m_sphereLatitude = 1.0f;
m_sphereLongitude = 1.0f;
m_sphereLatitudeCount = ceil(180.0f / m_sphereLatitude);
m_sphereLongitudeCount = ceil(360.0f / m_sphereLongitude);
m_sphereQuadCount = m_sphereLatitudeCount * m_sphereLongitudeCount; m_sphereTransform.setIdentity();
//m_sphereTransform.rotateY(A_TO_R(90.0f)); m_sphereVAO = ;
m_sphereIBO = ;
m_sphereVertexVBO = ;
m_sphereColorVBO = ;
m_sphereTextureVBO = ; return true;
} Sphere::~Sphere()
{
if (m_thread_1)
{
m_isThread1Done = true;
m_thread_1->join();
delete m_thread_1;
} if (m_thread_2)
{
m_isThread2Done = true;
b_transform_planview = true;
cv_transform_planview.notify_all();
m_thread_2->join();
delete m_thread_2;
} if (m_vertexes)
delete[] m_vertexes;
if (m_colors)
delete[] m_colors;
if (m_texcoordes)
delete[] m_texcoordes;
if (m_indexes)
delete[] m_indexes; if (m_sphereVertexVBO > )
glDeleteBuffers(, &m_sphereVertexVBO);
if (m_sphereColorVBO > )
glDeleteBuffers(, &m_sphereColorVBO);
if (m_sphereTextureVBO > )
glDeleteBuffers(, &m_sphereTextureVBO);
if (m_sphereIBO > )
glDeleteBuffers(, &m_sphereIBO);
if (m_sphereVAO > )
glDeleteVertexArrays(, &m_sphereVAO);
} void Sphere::generateVertexesSphere(float radius)
{
float rx = 0.0f, ry = 0.0f, rz = 0.0f; m_vertexes = new GLfloat[m_sphereQuadCount * ];
m_colors = new GLfloat[m_sphereQuadCount * ];
m_texcoordes = new GLfloat[m_sphereQuadCount * ];
m_indexes = new GLuint[m_sphereQuadCount * ]; unsigned int offset = * ;
unsigned int textureOffset = * ;
unsigned int stride = m_sphereLatitudeCount / * m_sphereLongitudeCount * offset;
unsigned int textureStride = m_sphereLatitudeCount / * m_sphereLongitudeCount * textureOffset; float unitU = m_sphereLongitude / 360.0f;
float unitV = m_sphereLatitude / 360.0f * ; GLuint vertexIndex = ; for (unsigned int latiIndex = ; latiIndex < m_sphereLatitudeCount / ; ++latiIndex)
{
// 纬度
float latiAngle = m_sphereLatitude * (latiIndex + );
float latiRadian1 = A_TO_R(latiAngle - m_sphereLatitude);
float latiRadian2 = A_TO_R(latiAngle); for (unsigned int longiIndex = ; longiIndex < m_sphereLongitudeCount; ++longiIndex)
{
// 经度
float longiAngle = m_sphereLongitude * (longiIndex + );
float longiRadian1 = A_TO_R(longiAngle - m_sphereLongitude);
float longiRadian2 = A_TO_R(longiAngle); unsigned int index = latiIndex * m_sphereLongitudeCount + longiIndex; // vertex
// 上半球
m_vertexes[index * offset + ] = rx + radius * cos(latiRadian1) * cos(longiRadian1);
m_vertexes[index * offset + ] = ry + radius * sin(latiRadian1);
m_vertexes[index * offset + ] = rz + radius * cos(latiRadian1) *sin(longiRadian1);
m_vertexes[index * offset + ] = 1.0f;
// 上半球
m_vertexes[index * offset + ] = rx + radius * cos(latiRadian1) * cos(longiRadian2);
m_vertexes[index * offset + ] = ry + radius * sin(latiRadian1);
m_vertexes[index * offset + ] = rz + radius * cos(latiRadian1) * sin(longiRadian2);
m_vertexes[index * offset + ] = 1.0f;
// 上半球
m_vertexes[index * offset + ] = rx + radius * cos(latiRadian2) * cos(longiRadian2);
m_vertexes[index * offset + ] = ry + radius * sin(latiRadian2);
m_vertexes[index * offset + ] = rz + radius * cos(latiRadian2) * sin(longiRadian2);
m_vertexes[index * offset + ] = 1.0f;
// 上半球
m_vertexes[index * offset + ] = rx + radius * cos(latiRadian2) * cos(longiRadian1);
m_vertexes[index * offset + ] = ry + radius * sin(latiRadian2);
m_vertexes[index * offset + ] = rz + radius * cos(latiRadian2) * sin(longiRadian1);
m_vertexes[index * offset + ] = 1.0f;
// 下半球
m_vertexes[stride + index * offset + ] = m_vertexes[index * offset + ];
m_vertexes[stride + index * offset + ] = - * m_vertexes[index * offset + ];
m_vertexes[stride + index * offset + ] = m_vertexes[index * offset + ];
m_vertexes[stride + index * offset + ] = 1.0f;
// 下半球
m_vertexes[stride + index * offset + ] = m_vertexes[index * offset + ];
m_vertexes[stride + index * offset + ] = - * m_vertexes[index * offset + ];
m_vertexes[stride + index * offset + ] = m_vertexes[index * offset + ];
m_vertexes[stride + index * offset + ] = 1.0f;
// 下半球
m_vertexes[stride + index * offset + ] = m_vertexes[index * offset + ];
m_vertexes[stride + index * offset + ] = - * m_vertexes[index * offset + ];
m_vertexes[stride + index * offset + ] = m_vertexes[index * offset + ];
m_vertexes[stride + index * offset + ] = 1.0f;
// 下半球
m_vertexes[stride + index * offset + ] = m_vertexes[index * offset + ];
m_vertexes[stride + index * offset + ] = - * m_vertexes[index * offset + ];
m_vertexes[stride + index * offset + ] = m_vertexes[index * offset + ];
m_vertexes[stride + index * offset + ] = 1.0f; // color
//上半球
m_colors[index * offset + ] = 1.0f;
m_colors[index * offset + ] = 1.0f;
m_colors[index * offset + ] = 1.0f;
m_colors[index * offset + ] = 0.6f;
m_colors[index * offset + ] = 1.0f;
m_colors[index * offset + ] = 1.0f;
m_colors[index * offset + ] = 1.0f;
m_colors[index * offset + ] = 0.6f;
m_colors[index * offset + ] = 1.0f;
m_colors[index * offset + ] = 1.0f;
m_colors[index * offset + ] = 1.0f;
m_colors[index * offset + ] = 0.6f;
m_colors[index * offset + ] = 1.0f;
m_colors[index * offset + ] = 1.0f;
m_colors[index * offset + ] = 1.0f;
m_colors[index * offset + ] = 0.6f;
// 下半球
m_colors[stride + index * offset + ] = 1.0f;
m_colors[stride + index * offset + ] = 1.0f;
m_colors[stride + index * offset + ] = 1.0f;
m_colors[stride + index * offset + ] = 0.6f;
m_colors[stride + index * offset + ] = 1.0f;
m_colors[stride + index * offset + ] = 1.0f;
m_colors[stride + index * offset + ] = 1.0f;
m_colors[stride + index * offset + ] = 0.6f;
m_colors[stride + index * offset + ] = 1.0f;
m_colors[stride + index * offset + ] = 1.0f;
m_colors[stride + index * offset + ] = 1.0f;
m_colors[stride + index * offset + ] = 0.6f;
m_colors[stride + index * offset + ] = 1.0f;
m_colors[stride + index * offset + ] = 1.0f;
m_colors[stride + index * offset + ] = 1.0f;
m_colors[stride + index * offset + ] = 0.6f; // texture
float startU = (m_sphereLongitudeCount - longiIndex) * unitU;
float startV = (m_sphereLatitudeCount / - latiIndex) * unitV;
// 上半球
m_texcoordes[index * textureOffset + ] = startU - unitU;
m_texcoordes[index * textureOffset + ] = startV;
m_texcoordes[index * textureOffset + ] = startU;
m_texcoordes[index * textureOffset + ] = startV;
m_texcoordes[index * textureOffset + ] = startU;
m_texcoordes[index * textureOffset + ] = (startV + unitV);
m_texcoordes[index * textureOffset + ] = startU - unitU;
m_texcoordes[index * textureOffset + ] = (startV + unitV);
// 下半球
m_texcoordes[textureStride + index * textureOffset + ] = startU;
m_texcoordes[textureStride + index * textureOffset + ] = 1.0f - (startV + unitV);
m_texcoordes[textureStride + index * textureOffset + ] = startU - unitU;
m_texcoordes[textureStride + index * textureOffset + ] = 1.0f - (startV + unitV);
m_texcoordes[textureStride + index * textureOffset + ] = startU - unitU;;
m_texcoordes[textureStride + index * textureOffset + ] = 1.0f - startV;
m_texcoordes[textureStride + index * textureOffset + ] = startU;
m_texcoordes[textureStride + index * textureOffset + ] = 1.0f - startV; m_indexes[vertexIndex++] = index * offset / ;
m_indexes[vertexIndex++] = index * offset / + ;
m_indexes[vertexIndex++] = index * offset / + ;
m_indexes[vertexIndex++] = index * offset / + ;
m_indexes[vertexIndex++] = (stride + index * offset) / ;
m_indexes[vertexIndex++] = (stride + index * offset) / + ;
m_indexes[vertexIndex++] = (stride + index * offset) / + ;
m_indexes[vertexIndex++] = (stride + index * offset) / + ; m_vertexCount += ;
m_indexCount += ;
}
}
} void Sphere::generateVertexesSphereNew(float radius)
{
unsigned int quadCount = m_sphereLatitudeCount * m_sphereLongitudeCount;
unsigned int vertexCount = (m_sphereLatitudeCount + ) * (m_sphereLongitudeCount + ); m_vertexes = new GLfloat[vertexCount * ];
m_colors = new GLfloat[vertexCount * ];
m_texcoordes = new GLfloat[vertexCount * ];
m_indexes = new GLuint[quadCount * ]; float unitU = m_sphereLongitude / 360.0f;
float unitV = m_sphereLatitude / 180.0f; for (unsigned int latiIndex = ; latiIndex <= m_sphereLatitudeCount; ++latiIndex)
{
// 纬度
float latiAngle = m_sphereLatitude * latiIndex;
float latiRadian = A_TO_R(latiAngle); latiRadian = HMPI - latiRadian; for (unsigned int longiIndex = ; longiIndex <= m_sphereLongitudeCount; ++longiIndex)
{
// 经度
float longiAngle = m_sphereLongitude * longiIndex;
float longiRadian = A_TO_R(longiAngle); unsigned int index = latiIndex * (m_sphereLongitudeCount + ) + longiIndex; m_vertexes[index * ] = m_sphereRadius * cos(latiRadian) * sin(longiRadian);
m_vertexes[index * + ] = m_sphereRadius * sin(latiRadian);
m_vertexes[index * + ] = m_sphereRadius * cos(latiRadian) * cos(longiRadian);
m_vertexes[index * + ] = 1.0f; m_colors[index * ] = 1.0f;
m_colors[index * + ] = 1.0f;
m_colors[index * + ] = 1.0f;
m_colors[index * + ] = 1.0f; m_texcoordes[index * ] = longiIndex * unitU;
m_texcoordes[index * + ] = latiIndex * unitV;
}
}
m_vertexCount = vertexCount; for (unsigned int i = ; i < m_sphereLatitudeCount; ++i)
{
for (unsigned int j = ; j < m_sphereLongitudeCount; ++j)
{
unsigned index = i * m_sphereLongitudeCount + j; m_indexes[index * ] = i * (m_sphereLongitudeCount + ) + j;
m_indexes[index * + ] = i * (m_sphereLongitudeCount + ) + j + ;
m_indexes[index * + ] = (i + ) * (m_sphereLongitudeCount + ) + j + ;
m_indexes[index * + ] = (i + ) * (m_sphereLongitudeCount + ) + j;
}
}
m_indexCount = quadCount * ;
} void Sphere::generateTexture()
{
CCTexture2D* texture = CCTextureCache::sharedTextureCache()->addImage("images/diqiu.jpg");
if (texture)
m_textureName = texture->getName();
else
assert(, "create texture failed");
} void Sphere::generateVAO()
{
glGenVertexArrays(, &m_sphereVAO);
if (m_sphereVAO > )
{
glBindVertexArray(m_sphereVAO); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_sphereIBO); glEnableVertexAttribArray();
glEnableVertexAttribArray();
glEnableVertexAttribArray(); glBindBuffer(GL_ARRAY_BUFFER, m_sphereVertexVBO);
glVertexAttribPointer(, , GL_FLOAT, GL_FALSE, , BUFFER_OFFSET());
glBindBuffer(GL_ARRAY_BUFFER, m_sphereColorVBO);
glVertexAttribPointer(, , GL_FLOAT, GL_FALSE, , BUFFER_OFFSET());
glBindBuffer(GL_ARRAY_BUFFER, m_sphereTextureVBO);
glVertexAttribPointer(, , GL_FLOAT, GL_FALSE, , BUFFER_OFFSET()); CHECK_GL_ERROR_DEBUG();
}
else
{
assert();
} glBindVertexArray();
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, );
glBindBuffer(GL_ARRAY_BUFFER, );
} void Sphere::generateIBO()
{
glGenBuffers(, &m_sphereIBO);
if (m_sphereIBO > )
{
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_sphereIBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * m_indexCount, m_indexes, GL_STATIC_DRAW); CHECK_GL_ERROR_DEBUG(); delete[] m_indexes;
m_indexes = nullptr;
} glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, );
} void Sphere::generateVBO()
{
size_t dataSize = sizeof(GLfloat) * m_vertexCount * ;
GLuint vbos[] = { , , }; glGenBuffers(, vbos);
if (vbos[] > )
{
m_sphereVertexVBO = vbos[]; glBindBuffer(GL_ARRAY_BUFFER, m_sphereVertexVBO);
glBufferData(GL_ARRAY_BUFFER, dataSize, m_vertexes, GL_STATIC_DRAW); delete[] m_vertexes;
m_vertexes = nullptr; CHECK_GL_ERROR_DEBUG();
}
else
{
assert();
}
if (vbos[] > )
{
m_sphereColorVBO = vbos[]; glBindBuffer(GL_ARRAY_BUFFER, m_sphereColorVBO);
glBufferData(GL_ARRAY_BUFFER, dataSize, m_colors, GL_STATIC_DRAW); delete[] m_colors;
m_colors = nullptr; CHECK_GL_ERROR_DEBUG();
}
if (vbos[] > )
{
m_sphereTextureVBO = vbos[]; glBindBuffer(GL_ARRAY_BUFFER, m_sphereTextureVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * m_vertexCount * , m_texcoordes, GL_STATIC_DRAW); delete[] m_texcoordes;
m_texcoordes = nullptr; CHECK_GL_ERROR_DEBUG();
} glBindBuffer(GL_ARRAY_BUFFER, );
} void Sphere::drawBg(const Mat4& transform)
{
CCTexture2D* texture = CCTextureCache::sharedTextureCache()->addImage("images/bg.jpg");
GL::bindTexture2D(texture->getName());
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); // GLProgram* program = CCShaderCache::sharedShaderCache()->getGLProgram(GLProgram::SHADER_NAME_POSITION_TEXTURE);
m_program->use();
m_program->setUniformsForBuiltins(transform); CCSize& size = CCDirector::sharedDirector()->getVisibleSize();
GLfloat vertexes[] = {
0.0f, 0.0f, 0.0f, 1.0f,
0.0f, , 0.0f, 1.0f,
, , 0.0f, 1.0f,
, 0.0f, 0.0f, 1.0f
};
GLfloat colores[] = {
1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f
};
GLfloat texCoordes[] = {
0.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f,
1.0f, 1.0f
}; glEnableVertexAttribArray();
glEnableVertexAttribArray();
glEnableVertexAttribArray();
glVertexAttribPointer(, , GL_FLOAT, GL_FALSE, , vertexes);
glVertexAttribPointer(, , GL_FLOAT, GL_FALSE, , colores);
glVertexAttribPointer(, , GL_FLOAT, GL_FALSE, , texCoordes); glDrawArrays(GL_QUADS, , ); glDisableVertexAttribArray();
glDisableVertexAttribArray();
glDisableVertexAttribArray(); CHECK_GL_ERROR_DEBUG();
} void Sphere::drawSphere(const Mat4& transform, GLfloat* vertexes)
{
GL::bindTexture2D(m_textureName);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); Mat4 _transform;
_transform.setIdentity();
_transform.translate(m_sphereTranslateX, m_sphereTranslateY, 0.0f);
_transform.multiply(m_sphereTransform); m_program->use();
m_program->setUniformsForBuiltins(_transform); CHECK_GL_ERROR_DEBUG(); glEnableVertexAttribArray();
glEnableVertexAttribArray();
glEnableVertexAttribArray(); if (m_sphereVAO == )
{
glBindBuffer(GL_ARRAY_BUFFER, m_sphereVertexVBO);
glVertexAttribPointer(, , GL_FLOAT, GL_FALSE, , BUFFER_OFFSET());
glBindBuffer(GL_ARRAY_BUFFER, m_sphereColorVBO);
glVertexAttribPointer(, , GL_FLOAT, GL_FALSE, , BUFFER_OFFSET());
glBindBuffer(GL_ARRAY_BUFFER, m_sphereTextureVBO);
glVertexAttribPointer(, , GL_FLOAT, GL_FALSE, , BUFFER_OFFSET());
glBindBuffer(GL_ARRAY_BUFFER, ); CHECK_GL_ERROR_DEBUG(); if (m_sphereIBO == )
{
if (m_indexes)
glDrawElements(GL_QUADS, m_indexCount, GL_UNSIGNED_INT, m_indexes);
else
glDrawArrays(GL_QUADS, , m_vertexCount);
}
else
{
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_sphereIBO);
glDrawElements(GL_QUADS, m_indexCount, GL_UNSIGNED_INT, BUFFER_OFFSET());
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, );
}
}
else
{
glBindVertexArray(m_sphereVAO);
glDrawElements(GL_QUADS, m_indexCount, GL_UNSIGNED_INT, BUFFER_OFFSET());
glBindVertexArray();
} glDisableVertexAttribArray();
glDisableVertexAttribArray();
glDisableVertexAttribArray(); CHECK_GL_ERROR_DEBUG();
} void Sphere::drawPlanView(const Mat4& transform, GLfloat* vertexes)
{
GL::bindTexture2D(m_textureName);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); Mat4 _transform;
_transform.setIdentity();
//_transform.translate(m_planViewTranslateX, m_planViewTranslateY, 0.0f);
_transform.multiply(m_sphereTransform); m_program_planview->use();
GLfloat _translate[] = { m_planViewTranslateX, m_planViewTranslateY };
GLuint location_radius = m_program_planview->getUniformLocation("radius");
m_program_planview->setUniformLocationWith1f(location_radius, m_sphereRadius);
GLuint location_translate = m_program_planview->getUniformLocation("translate");
m_program_planview->setUniformLocationWith2f(location_translate, _translate[], _translate[]);
m_program_planview->setUniformsForBuiltins(_transform); /*
m_program->use();
m_program->setUniformsForBuiltins(_transform);
*/ glEnableVertexAttribArray();
glEnableVertexAttribArray();
glEnableVertexAttribArray(); if (m_sphereVAO == )
{
glBindBuffer(GL_ARRAY_BUFFER, m_sphereVertexVBO);
glVertexAttribPointer(, , GL_FLOAT, GL_FALSE, , );
glBindBuffer(GL_ARRAY_BUFFER, m_sphereColorVBO);
glVertexAttribPointer(, , GL_FLOAT, GL_FALSE, , );
glBindBuffer(GL_ARRAY_BUFFER, m_sphereTextureVBO);
glVertexAttribPointer(, , GL_FLOAT, GL_FALSE, , );
glBindBuffer(GL_ARRAY_BUFFER, ); if (m_sphereIBO == )
{
if (m_indexes)
glDrawElements(GL_QUADS, m_indexCount, GL_UNSIGNED_INT, m_indexes);
else
glDrawArrays(GL_QUADS, , m_vertexCount);
}
else
{
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_sphereIBO);
glDrawElements(GL_QUADS, m_indexCount, GL_UNSIGNED_INT, BUFFER_OFFSET());
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, );
}
}
else
{
glBindVertexArray(m_sphereVAO);
glDrawElements(GL_QUADS, m_indexCount, GL_UNSIGNED_INT, BUFFER_OFFSET());
glBindVertexArray();
} glDisableVertexAttribArray();
glDisableVertexAttribArray();
glDisableVertexAttribArray(); CHECK_GL_ERROR_DEBUG();
} void Sphere::draw(Renderer *renderer, const Mat4& transform, uint32_t flags)
{
glEnable(GL_CULL_FACE);
glFrontFace(GL_CW); GL::blendFunc(BlendFunc::ALPHA_NON_PREMULTIPLIED.src, BlendFunc::ALPHA_NON_PREMULTIPLIED.dst); this->drawBg(transform); {
if (mx_transform_sphere.try_lock())
{
this->drawSphere(transform, m_vertexes); mx_transform_sphere.unlock();
}
} {
if (mx_transform_planview.try_lock())
{
this->drawPlanView(transform, m_vertexes); mx_transform_planview.unlock();
}
} glEnableVertexAttribArray();
glEnableVertexAttribArray();
glEnableVertexAttribArray();
} void Sphere::visit(Renderer *renderer, const Mat4& parentTransform, uint32_t parentFlags)
{
this->update(); Node::visit(renderer, parentTransform, parentFlags);
} void Sphere::transformSphere(float touchOffsetX, float touchOffsetY)
{
m_rotateYAngle += touchOffsetX / m_spherePerimeter * 360.0f;
// m_rotateXAngle -= touchOffsetY / m_spherePerimeter * 360.0f;
// m_rotateZAngle -= touchOffsetX / m_spherePerimeter * 360.0f; if (m_rotateYAngle >= 90.0f && m_rotateYAngle <= 270.0f)
m_rotateXAngle += touchOffsetY / m_spherePerimeter * 360.0f;
else
m_rotateXAngle -= touchOffsetY / m_spherePerimeter * 360.0f; if (m_rotateYAngle < 0.0f)
m_rotateYAngle += 360.0f;
if (m_rotateYAngle > 360.0f)
m_rotateYAngle -= 360.0f; if (m_rotateXAngle < 0.0f)
m_rotateXAngle += 360.0f;
if (m_rotateXAngle >= 360.0f)
m_rotateXAngle -= 360.0f; /*
cocos2d::log("m_rotateXAngle:%f", m_rotateXAngle);
cocos2d::log("m_rotateYAngle:%f", m_rotateYAngle);
cocos2d::log("m_rotateZAngle:%f", m_rotateZAngle);
*/ Quaternion quat1;
this->createQuaternion(m_rotateXAngle, , , quat1);
Quaternion quat2;
this->createQuaternion(, m_rotateYAngle, , quat2);
Quaternion quat3;
this->createQuaternion(, , m_rotateZAngle, quat3);
Quaternion quat4;
this->createQuaternion(m_rotateXAngle, m_rotateYAngle, m_rotateZAngle, quat4); m_sphereTransform.setIdentity();
//m_sphereTransform.rotate(quat4);
//m_sphereTransform.rotate(quat3);
//m_sphereTransform.rotate(quat2);
//m_sphereTransform.rotate(quat1);
m_sphereTransform.rotate(quat3);
m_sphereTransform.rotate(quat2);
m_sphereTransform.rotate(quat1); // m_sphereTransform.rotateX(A_TO_R(m_rotateXAngle));
// m_sphereTransform.rotateY(A_TO_R(m_rotateYAngle));
} void Sphere::createQuaternion(float rotateX, float rotateY, float rotateZ, Quaternion& quat)
{
float halfRadx = CC_DEGREES_TO_RADIANS(rotateX / .f), halfRady = CC_DEGREES_TO_RADIANS(rotateY / .f), halfRadz = CC_DEGREES_TO_RADIANS(rotateZ / .f);
float coshalfRadx = cosf(halfRadx), sinhalfRadx = sinf(halfRadx), coshalfRady = cosf(halfRady), sinhalfRady = sinf(halfRady), coshalfRadz = cosf(halfRadz), sinhalfRadz = sinf(halfRadz);
quat.x = sinhalfRadx * coshalfRady * coshalfRadz - coshalfRadx * sinhalfRady * sinhalfRadz;
quat.y = coshalfRadx * sinhalfRady * coshalfRadz + sinhalfRadx * coshalfRady * sinhalfRadz;
quat.z = coshalfRadx * coshalfRady * sinhalfRadz - sinhalfRadx * sinhalfRady * coshalfRadz;
quat.w = coshalfRadx * coshalfRady * coshalfRadz + sinhalfRadx * sinhalfRady * sinhalfRadz;
} void Sphere::update()
{
if (m_isContinue)
{
float _rotateX = fabsf(m_continueRotateX);
float _rotateY = fabsf(m_continueRotateY); _rotateX -= m_decreateDetal;
if (_rotateX < 0.0f)
m_continueRotateX = 0.0f;
else
m_continueRotateX += (m_continueRotateX >= 0.0f) ? (-m_decreateDetal) : m_decreateDetal; _rotateY -= m_decreateDetal;
if (_rotateY < 0.0f)
m_continueRotateY = 0.0f;
else
m_continueRotateY += (m_continueRotateY >= 0.0f) ? (-m_decreateDetal) : m_decreateDetal; if (m_continueRotateX == 0.0f && m_continueRotateY == 0.0f)
{
m_isContinue = false;
}
else
{
this->transformSphere(m_continueRotateY, m_continueRotateX); // this->noticeToTransform(m_continueRotateY, m_continueRotateX);
}
}
} void Sphere::onThread1Proc()
{
do {
if (m_isThread1Done)
break; float x = 0.0f, y = 0.0f;
{
std::lock_guard<std::mutex> lock(mx_transform_sphere); if (b_transform_sphere)
{
x = _touchOffsetXCopy = _touchOffsetX;
y = _touchOffsetYCopy = _touchOffsetY; this->transformSphere(x, y); _sphereTransformationCopy = m_sphereTransform; b_transform_sphere = false;
b_transform_planview = true;
cv_transform_planview.notify_all();
}
else
{
std::this_thread::sleep_for(std::chrono::microseconds());
}
}
}
while ();
} void Sphere::onThread2Proc()
{
do {
if (m_isThread2Done)
break; {
std::unique_lock<std::mutex> lock(mx_transform_planview);
cv_transform_planview.wait(lock, [this](){
return b_transform_planview;
});
b_transform_planview = false;
} {
std::lock_guard<std::mutex> lock(mx_transform_planview);
}
}
while ();
} void Sphere::noticeToTransform(float touchOffsetX, float touchOffsetY)
{
{
std::lock_guard<std::mutex> lock(mx_transform_sphere); _touchOffsetX = touchOffsetX;
_touchOffsetY = touchOffsetY; b_transform_sphere = true;
}
} bool Sphere::onTouchBegan(Touch* touch, Event* event)
{
const cocos2d::Vec2& touchPoint = touch->getLocation(); float _x = touchPoint.x - m_sphereTranslateX, _y = touchPoint.y - m_sphereTranslateY;
float _dis = _x * _x + _y * _y; if (_dis <= m_sphereRadius * m_sphereRadius)
{
m_isContinue = false;
return true;
}
else
{
return false;
}
} void Sphere::onTouchMoved(Touch* touch, Event* event)
{
const cocos2d::Vec2& touchPoint = touch->getLocation();
const cocos2d::Vec2& preTouchPoint = touch->getPreviousLocation();
float touchOffsetX = touchPoint.x - preTouchPoint.x;
float touchOffsetY = touchPoint.y - preTouchPoint.y; this->transformSphere(touchOffsetX, touchOffsetY); // this->noticeToTransform(touchOffsetX, touchOffsetY); m_continueRotateY = touchOffsetX / m_spherePerimeter * 360.0f;
m_continueRotateX = touchOffsetY / m_spherePerimeter * 360.0f;
} void Sphere::onTouchEnded(Touch* touch, Event* event)
{
m_isContinue = true;
}

openGL 提升渲染性能 之 顶点数组 VBO IBO VAO的更多相关文章

  1. React爬坑秘籍(一)——提升渲染性能

    React爬坑秘籍(一)--提升渲染性能 ##前言 来到腾讯实习后,有幸八月份开始了腾讯办公助手PC端的开发.因为办公助手主推的是移动端,所以导师也是大胆的让我们实习生来技术选型并开发,他来做code ...

  2. 3D Computer Grapihcs Using OpenGL - 19 Vertex Array Object(顶点数组对象)

    大部分OpenGL教程都会在一开始就讲解VAO,但是该教程的作者认为这是很不合理的,因为要理解它的作用需要建立在我们此前学过的知识基础上.因此直到教程已经进行了一大半,作者才引入VAO这个概念.在我看 ...

  3. OpenGL(十八) 顶点数组和抗锯齿(反走样)设置

    顶点数组函数可以在一个数组里包含大量的与顶点相关的数据,并且可以减少函数的调用.使用顶点数组需要先启用顶点数组功能,使用glEnableClientState函数启用顶点数组,参数可以是GL_VERT ...

  4. Opengl ES之VBO和VAO

    前言 本文主要介绍了什么是VBO/VAO,为什么需要使用VBO/VAO以及如何使用VBO和VAO. VBO 什么是VBO VBO(vertex Buffer Object):顶点缓冲对象.是在显卡存储 ...

  5. 3D硬件加速提升动画性能 与 z-index属性

    目录 1. chrome Layer borders 2. 层创建标准 3. 例子 总结 1. chrome Layer borders <WebKit技术内幕>第二章介绍了网页的结构,其 ...

  6. WebGL2系列之顶点数组对象

    使用了顶点缓冲技术后,绘制效率有了较大的提升.但是还有一点不尽如人意,那就是顶点的位置坐标.法向量.纹理坐标等不同方面的数据每次使用时需要单独指定,重复了一些不必要的工作.WebGL2提供了一种专门用 ...

  7. VBO、VAO和EBO

    Vertex Buffer Object 对于经历过fixed pipeline的我来讲,VBO的出现对于渲染性能提升让人记忆深刻.完了,暴露年龄了~ //immediate mode glBegin ...

  8. OpenGL中glVertex、显示列表(glCallList)、顶点数组(Vertex array)、VBO及VAO区别

    OpenGL中glVertex.显示列表(glCallList).顶点数组(Vertex array).VBO及VAO区别 1.glVertex 最原始的设置顶点方法,在glBegin和glEnd之间 ...

  9. [转]OpenGL通过VBO实现顶点数组绘制顶点

    #include "stdlib.h" #include <OpenGL/glext.h> #include <GLUT/GLUT.h> #define B ...

随机推荐

  1. 黄聪:使用WORDPRESS自带AJAX方法

    例如给网站每页logo后面的一句名言,点击“换一条”就会ajax动态加载一条,使用了wordpress的自带ajax方法.下面介绍如何使用wordpress自带ajax方法: 1.在header.ph ...

  2. Jedis 连接redis超时

    redis默认不允许远程连接 用vi打开Redis服务器的配置文件redis.conf ~ sudo vi /etc/redis/redis.conf #注释bind #bind 127.0.0.1 ...

  3. 使用 Entity Framework

    ORM 和 EF 当我们要开发一个应用程序,就要考虑怎样展示数据,怎样持久化数据.考虑这个问题时我们所要关心的东西,最重要的莫过于程序的性能.开发的简易性和代码的可维护.可扩展性. 持久化(Persi ...

  4. C#多线程编程(转)

    一.使用线程的理由 1.可以使用线程将代码同其他代码隔离,提高应用程序的可靠性. 2.可以使用线程来简化编码. 3.可以使用线程来实现并发执行. 二.基本知识 1.进程与线程:进程作为操作系统执行程序 ...

  5. kafka模拟客户端发送、接受消息

    producer   消息的生成者,即发布消息 consumer   消息的消费者,即订阅消息 broker     Kafka以集群的方式运行,可以由一个或多个服务组成,服务即broker zook ...

  6. MongoDB 3.0 导入命令

    在MongoDB的bin目录下执行 ./mongoimport -h 192.168.77.129 --db test --collection restaurants --drop --file / ...

  7. PLSQL_性能优化效能跟踪工具SQL Trace分析(案例)

    2014-06-25 Created By BaoXinjian

  8. NodeJS 学习资料

    1. npm 除Node本身提供的API外,现在有不少第三方模块可极大的提高开发效率,npm就是Node的软件包管理器,可以用它安装所需软件包并发布自己为nodejs写的软件包. npm安装node扩 ...

  9. Zend Guard Run-time support missing问题的解决

    Zend Guard不仅可以实现对PHP应用的脚本进行加密保护和对PHP应用的产品进行商业许可证管理,还可以为许多软件生产商.IT服务提供商提供完善的加密和安全的产品发布系统. 虽然现在可以成功加密p ...

  10. 树莓派通过apt方式安装opencv库

    1.安装opencv     开始之前进行必要的更新工作. sudo apt-get update     安装opencv. sudo apt-get install libcv-dev     安 ...