月度存档: 10 月 2012

opengles中画四边型

opengles中仅支持以下几种模型:

/* BeginMode */
#define GL_POINTS                         0x0000
#define GL_LINES                          0x0001
#define GL_LINE_LOOP                      0x0002
#define GL_LINE_STRIP                     0x0003
#define GL_TRIANGLES                      0x0004
#define GL_TRIANGLE_STRIP                 0x0005
#define GL_TRIANGLE_FAN                   0x0006

所以如果需要画一个四边型,需要借助GL_TRIANGLES_STRIP

static const GLfloat 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 GLfloat texCoords[] =
{ 0.0, 1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0 };

glBindTexture(GL_TEXTURE_2D, 1);
glVertexPointer(3, GL_FLOAT, 0, vertices);
glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

如此即可画出一个四边型

stl_bvector.h expected unqualified-id before ‘(‘ token

解决方案参考:

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=16605

Your code defines min/max as macros. The preprocessor expands this, which 
leaves what used to be std::max(x1, x2) as something that doesn't make 
much sense to the compiler any more. 

Since the standard says that the names min/max are reserved, simply 
remove these #defines from your sources. 

W.

使用cximage及curl下载图片,生成纹理

GLint TextureManager::generateTextureFromPNG(char* url) {
// 下载图片
DownloadResources dr;
initDownloadResource(&dr, url);
download_image(&dr);

CxImage image((BYTE*) dr.memoeryBuff, dr.size, CXIMAGE_FORMAT_PNG);

// TODO:这里能先释放dr的内存吗
if (image.IsValid()) {
logInfo(“load image ok %s:”, url);
} else {
logError(“load image error %s:”, url);
}

int width = image.GetWidth();
int height = image.GetHeight();

GLuint ids[1];
glGenTextures(1, ids);
LOGI(“gl texture id:%d”, ids[0]);
glBindTexture(GL_TEXTURE_2D, ids[0]);

BYTE* glimagedata = NULL;
if (image.AlphaIsValid()) {
long t = width * height * 4;
// 有alpha通道
if (!image.Encode2RGBA(glimagedata, t)) {
LOGE(“image encode 2 rgba error.%s”, image.GetLastError());
}
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA,
GL_UNSIGNED_BYTE, glimagedata);
checkGlError(“generate texture”);
} else {
LOGE(“image is not support alpha.”);
}

image.FreeMemory(glimagedata); //释放内存空间
freeDownloadResource(&dr); // 释放掉下载的文件占用的内存
return ids[0];
}

curl 下载例子

/*
* curlutil.h
*
* curl工具库,用来处理下载图片及其它资源
*
*  Created on: 2012-10-22
*      Author: joycube2
*/

#ifndef CURLUTIL_H_
#define CURLUTIL_H_

#include “curl.h”
#include “all_include.h”
#include “predef.h”
/*
* 内存对象,用来在每次读取到chunk后,暂时保存读到的数据
* 用来封装好,提供给外部调用
*
* samples:
*
* DownloadResources downloadResources;
* initDownloadResource(&downloadResources,url);
* download_image(&downloadResources);
* …
* freeDownloadResource(&downloadResources);
*/
struct DownloadResources {
char* url;
char* memoeryBuff;
size_t size;
};

/*
* 初始化downloadResource对象一些相差的初始化信息
*/
void initDownloadResource(DownloadResources* downloadResources, char* url) {
downloadResources->url = url;
downloadResources->memoeryBuff = NULL;
downloadResources->size = 0;
}

/*
* 释放分配的内存空间
*/
void freeDownloadResource(DownloadResources* downloadResources) {
if (downloadResources->memoeryBuff) {
free(downloadResources->memoeryBuff);
}
}

size_t write_data(char *responseContent, size_t size, size_t nmemb,
void *userdata) {
logDebug(“curl response: size:%d nmemb:%d”, size, nmemb);
size_t realSize = size * nmemb;

struct DownloadResources* mem = (struct DownloadResources*) userdata;

if (mem->size == 0) {
mem->memoeryBuff = (char*) malloc(realSize);
memcpy(mem->memoeryBuff, responseContent, realSize);
} else {
mem->memoeryBuff = (char*) realloc(mem->memoeryBuff,
mem->size + realSize);
memcpy(mem->memoeryBuff + mem->size, responseContent, realSize);
}

mem->size += realSize;

return realSize;
}
/*
* 试试能不能直接给指针
*/
void download_image(DownloadResources* downloadResources) {
logInfo(“download %s”,downloadResources->url);

CURL * curl;
CURLcode res;

curl = curl_easy_init();

if (curl) {
curl_easy_setopt(curl, CURLOPT_URL, downloadResources->url);

curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);

curl_easy_setopt(curl, CURLOPT_WRITEDATA, downloadResources);

res = curl_easy_perform(curl);

curl_easy_cleanup(curl);

if (res != CURLE_OK) {
logError(“failed:%s”, curl_easy_strerror(res));
}
} else {
logError(“failed:%s”, curl_easy_strerror(res));
}
}

#endif /* CURLUTIL_H_ */

ndk下使用动态库及静态库

以libpng为例。

如果使用动态库:

1、新建android工程,创建jni目录,其它步骤不多说了,参考官方的ndk入门就可以了。

将libpng所需源文件放在jni目录下,

并编写Android.mk

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)

LOCAL_CFLAGS :=

LOCAL_MODULE    := png
LOCAL_SRC_FILES :=\
png.c \
pngerror.c \
pngget.c \
pngmem.c \
pngpread.c \
pngread.c \
pngrio.c \
pngrtran.c \
pngrutil.c \
pngset.c \
pngtrans.c \
pngwio.c \
pngwrite.c \
pngwtran.c \
pngwutil.c

LOCAL_LDLIBS := -lz

#include $(BUILD_SHARED_LIBRARY)
include $(BUILD_STATIC_LIBRARY)

编写Application.mk

APP_OPTIM := release
APP_MODULES := libpng

然后编译,执行成功后会生成

libpng.so文件。

好了,动态链接库已经生成。将此文件复制至自己的工程的jni目录下。

Android.mk修改如下:

# See the License for the specific language governing permissions and
# limitations under the License.
#
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := png
LOCAL_SRC_FILES := libpng.so
include ${PREBUILT_SHARED_LIBRARY}

include $(CLEAR_VARS)
LOCAL_MODULE    := libgl2jni
LOCAL_CFLAGS    := -Werror
LOCAL_SHARED_LIBRARIES := png
#LOCAL_STATIC_LIBRARIES := libpng
#LOCAL_C_INCLUDES += $(LOCAL_PATH)/png
LOCAL_SRC_FILES := gl_code.cpp
LOCAL_LDLIBS    := -llog -lGLESv1_CM -lz
include $(BUILD_SHARED_LIBRARY)

在java代码中也别忘记加载动态库:

static {
System.loadLibrary(“stlport_shared”); // 加载stl的动态库
System.loadLibrary(“png”); // 加载gl2库
System.loadLibrary(“gl2jni”); // 加载gl2库
}

因为gl2jni使用了png库,所以要先加载png库,再加载gl2jni库。

为了方便,在google code已经建立好了工程,可位可以直接下载编译:

http://code.google.com/p/android-ndk-libpng/

——————————————————————————————————–

如果使用静态库:

将以上源代码放在项目的jni目录下

修改Android.mk为:

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE    := libgl2jni
LOCAL_CFLAGS    := -Werror
LOCAL_SRC_FILES := gl_code.cpp
LOCAL_STATIC_LIBRARIES := png
#LOCAL_C_INCLUDES += $(LOCAL_PATH)/png
LOCAL_LDLIBS    := -llog -lGLESv1_CM -lz

include $(BUILD_SHARED_LIBRARY)

include $(CLEAR_VARS)

include $(LOCAL_PATH)/png/Android.mk

libpng读取png图片

这是从网上找的代码,但有以下两个缺陷:

1、不支持从内存中解析png图片。

2、生成的图片数据中不包含alpha数据,既使png图中带有alpha数据。

继续查找cximage移植ndk.

unsigned char* readpng(const char* file, png_uint_32* w, png_uint_32* h,
bool* hasAlpha) {
LOGI(“readPng 1”);
FILE* f;
unsigned char sig[8];
png_structp png_ptr;
png_infop info_ptr;
unsigned char* image_data;
int bit_depth;
int color_type;
unsigned int rowbytes;
png_uint_32 i;
png_bytepp row_pointers;
LOGI(“readPng 2”);
if ((f = fopen(file, “rb”)) == NULL)
return NULL;
fread(sig, sizeof(*sig), sizeof(sig), f);
//    if (!png_check_sig(sig, sizeof(*sig))) {
//        fclose(f);
//        return NULL;
//    }
LOGI(“readPng 3”);
if ((png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL,
NULL)) == NULL) {
fclose(f);
return NULL;
}
if ((info_ptr = png_create_info_struct(png_ptr)) == NULL) {
png_destroy_read_struct(&png_ptr, NULL, NULL);
fclose(f);
return NULL;
}
LOGI(“readPng 4”);
if (setjmp(png_jmpbuf(png_ptr))) {
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
fclose(f);
return NULL;
}
LOGI(“readPng 4.1”);
//    png_ptr->io_ptr = (png_voidp) f;
png_init_io(png_ptr, f); // fuck,加上这一句就OK了
png_set_sig_bytes(png_ptr, 8);
LOGI(“readPng 4.2”);
png_read_info(png_ptr, info_ptr);
LOGI(“readPng 4.3”);
png_get_IHDR(png_ptr, info_ptr, w, h, &bit_depth, &color_type, NULL, NULL,
NULL);
LOGI(“readPng 5”);
if (color_type & PNG_COLOR_MASK_ALPHA) {
png_set_strip_alpha(png_ptr);
*hasAlpha = true;
}
if (bit_depth == 16)
png_set_strip_16(png_ptr);
if (color_type == PNG_COLOR_TYPE_GRAY || color_type
== PNG_COLOR_TYPE_GRAY_ALPHA)
png_set_gray_to_rgb(png_ptr);
if (color_type == PNG_COLOR_TYPE_PALETTE)
png_set_palette_to_rgb(png_ptr);
png_read_update_info(png_ptr, info_ptr);

LOGI(“readPng 6”);
rowbytes = png_get_rowbytes(png_ptr, info_ptr);
if ((image_data = (unsigned char *) malloc(*h * rowbytes)) == NULL) {
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
fclose(f);
return NULL;
}
if ((row_pointers = (png_bytepp) malloc(*h * sizeof(png_bytep))) == NULL) {
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
fclose(f);
free(image_data);
return NULL;
}

for (i = 0; i < *h; i++)
row_pointers[*h – 1 – i] = image_data + i * rowbytes;
png_read_image(png_ptr, row_pointers);
free(row_pointers);
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
fclose(f);

//    FILE* f2=fopen(“/sdcard/2.png”, “w”);
//    fwrite(image_data,*h * rowbytes,1,f2);
//    fclose(f2);
return image_data;
}

android&ios

curl库可以用在android ndk及ios上。

所以网络相关的功能,可以使用curl进行开发。

android开发点滴

1、设置为全屏:

在activity中设置:

public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 隐藏title栏
requestWindowFeature(Window.FEATURE_NO_TITLE);
// 隐藏时间、电池栏
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
mView = new GL2JNIView(getApplication());
setContentView(mView);
}

2、glColorPointer

void glColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid * pointer)

第一个参数必须是4。

3、glTexImage2D

http://www.khronos.org/opengles/documentation/opengles1_0/html/glTexImage2D.html

void glTexImage2D(GLenum target,
    GLint level,
    GLint internalformat,
    GLsizei width,
    GLsizei height,
    GLint border,
    GLenum format,
    GLenum type,
    const GLvoid * pixels)
internalformat
Specifies the color components in the texture. Must be same as format.看到了没,internalformat must be same as format.
4、static {
System.loadLibrary(“stlport_shared”); // 加载stl的动态库
System.loadLibrary(“png”); // 加载gl2库
System.loadLibrary(“gl2jni”); // 加载gl2库}
动态库加载时,有顺序限制,如gl2jni需要png库,则需要先加载png库,再加载gl2jni库。如果提前加载gl2jin库则会失败。
5、error: exception handling disabled, use -fexceptions to enable。
错误解决方案:
Application.mk 中添加:APP_CPPFLAGS += -fexceptions
6、C++中要显示给指针赋值为NULL