NDKサンプルのhello-gl2をビルドして実行してみる
今回は前回の続きでNDKを導入してみる。
Android NDK | Android Developersから「Linux 32/64-bit (x86)」をダウンロードして展開する。(今回は~/android-ndk-r8b/)
ndk-buildにパスを通す。
> export PATH=~/android-ndk-r8b:${PATH}
サンプルのhello-gl2をndk-buildする。
> cd ~/android-ndk-r8b/samples/hello-gl2
> ndk-build
libgl2jni.soが生成された。
Eclipseを起動して、[File]-[import]を選択し「Android」-「Existing Android Code Into Workspace」でRoot Directoryに"~/android-ndk-r8b/samples/hello-gl2"を指定してインポートする。([Help]-[Install New Software...]から「NDK Plugins」がインストールできるがapkを作成するだけならまだ不要)
前回同様に[Run As]からapkをし、生成された~/android-ndk-r8b/samples/hello-gl2/bin/com.android.gl2jni.GL2JNIActivity.apkを実機で確認すると三角形と画面全体のフェードのリピートが確認できた。
Ubuntuでandroid開発環境
ここら辺を参考にUbuntu12.04上にandroid開発環境を構築する。
とりあえずはhello, world!が出ればいいということでJavaはdefault(OpenJDK)でやってみる。
まず、Eclipseをインストール。
$ sudo apt-get install eclipse
ここでは3.7.2がインストールされた。
ADTのインストール。
Eclipseを起動して「Help」 -> 「Install New Software…」を選択。
「Add…」ボタンをクリックし、「Location」に
https://dl-ssl.google.com/android/eclipse/
と入力してOKをクリック。
「Developer Tools」が選べるようになるので選択してインストール。
(途中出てきたSecurity WarningはOKを選択。)
インストールが終了すると再起動を促されるので「Restart Now」をクリックして再起動。
Eclipseを再起動すると「Welcome to Android Development」ダイアログがでる。
今回は動作確認をバージョン2.3.6の実機で行うので「Install Android 2.2, a version which is supported by ~93% phones and tablets」をチェック入れてインストール。
インストールが終わったら早速ビルドしてみる。
- [File]-[New]-[Project...]を選択
- 「Android」の「Android Application Project」を選択。
- Application Nameを「Hello」と入力して「Next」ボタンをクリック。
- 以下、デフォルトで設定していくと、「Install Dependencies」といわれたので「Install/Upgrade」ボタンを押してインストール。
- 「Finish」ボタンが押せるようになるのでクリックして終了。
「Project Explorer」から「Hello」プロジェクトを右クリック。
[Run As]-[Android Application]としてapkを生成させる。エミュレーターなどのtarget設定していないため「Android AVD Error」ダイアログが出てVirtual Deviceを作成するか聞かれるがここでは「No」を選択しキャンセル。
~/workspace/Hello/bin/Hello.apkを実機にコピー。(ここではDropbox(ubuntu,android)を使用。)
インストールして実行。(Androidのアプリケーション設定で「提供元不明のアプリ」をチェックする必要がある。)
とりあえず"Hello, world!"は出た。
SDLとOpenGLでhello, world(Windows版)
さて、前回の続きで今回はWindows+SDL+OpenGLでhello, world。
環境は、
まず、GLEWを用意。
ここからWindows 32-bit版をダウンロードして展開。今回はC:\libs\glew-1.9.0に展開。
次にSDLを用意。
ここからをSDL-devel-1.2.15-VC.zipダウンロード。やはり、C:\libs\SDL-1.2.15に展開。
このまま使ってもいいのだけれど、前回の#includeのファイルパスそのまま使うためにレイアウトを変更する。
> md C:\libs\SDL-1.2.15\include\SDL
> move C:\libs\SDL-1.2.15\include\*.h C:\libs\SDL-1.2.15\include\SDL
スタートメニューから「Microsoft Visual C++ 2008 Express Edition」>「Visual Studio Tools」>「Visual Studio 2008 コマンド プロンプト」を選んで起動。
前回のhello.cをhello.cppとして作成。(C89では通らないため。今回はC:\Users\simpgに)
同じディレクトリにCMakeLists.txtを作成。
[CMakeLists.txt]
set(CMAKE_EXE_LINKER_FLAGS "/NODEFAULTLIB:\"msvcrt.lib\" /MACHINE:x86")
include_directories(C:\\libs\\SDL-1.2.15\\include C:\\libs\\glew-1.9.0\\include)
link_directories(C:\\libs\\SDL-1.2.15\\lib\\x86 C:\\libs\\glew-1.9.0\\lib)
link_libraries(hello SDLmain SDL glew32 opengl32)
add_executable(hello hello.cpp)
cmake、nmakeでビルド。
> cd \Users\simpg
> cmake -G "NMake Makefiles"
> nmake
実行のために必要なDLLをカレントにコピーしてから実行。
> copy C:\libs\SDL-1.2.15\lib\x86\SDL.dll
> copy C:\libs\glew-1.9.0\bin\glew32.dll
> hello.exe
無事表示できた。
SDLとOpenGLでhello, world
テスト環境は、Ubuntu12.04。
$ sudo apt-get install libsdl1.2-dev libglew1.6-dev
glut用のコードをSDL用に修正。(記事の最後のhello.c)
ビルドして実行。
$ gcc hello.c -lGLEW -lSDL -o hello
$ ./hello
問題なし。
emscriptenでもやってみる。
$ emscripten/emcc hello.c -o hello.html
(Chrome20,Firefox13で確認。見た目はglut版とまったく一緒。。。表示を確認するにはブラウザの設定が「WebGL有効」である必要があります。)
(2012/08/11追記:どうやらemscriptenのSDL_Delayは期待した動作をしてくれないみたい。)
[hello.c]
#ifdef EMSCRIPTEN
#define GL_GLEXT_PROTOTYPES
#define EGL_EGLEXT_PROTOTYPES
#else // glew
#include
#endif // EMSCRIPTEN#include
#define NO_SDL_GLEXT
#include#include
#define TEX_W (128)
typedef struct
{
GLuint programObject;
GLuint vertexShader, fragmentShader;
GLuint textureId;
} glhandle;static const char s_vShaderStr[] =
"attribute vec4 a_position; \n"
"attribute vec2 a_texCoord; \n"
"varying vec2 v_texCoord; \n"
"void main() \n"
"{ \n"
" gl_Position = a_position; \n"
" v_texCoord = a_texCoord; \n"
"} \n";
static const char s_fShaderStr[] =
"#ifdef GL_ES\n"
"precision mediump float; \n"
"#endif\n"
"varying vec2 v_texCoord; \n"
"uniform sampler2D s_texture; \n"
"void main() \n"
"{ \n"
" gl_FragColor = texture2D( s_texture, v_texCoord );\n"
"} \n";
static const unsigned char s_acDotImg[8][12] =
{
0x63,0x3f,0x30,0x30,0x3e,0x00,0x00,0x63,0x3e,0x7e,0x30,0x7c,
0x63,0x30,0x30,0x30,0x63,0x00,0x00,0x63,0x63,0x63,0x30,0x66,
0x63,0x30,0x30,0x30,0x63,0x00,0x00,0x6b,0x63,0x63,0x30,0x63,
0x7f,0x3e,0x30,0x30,0x63,0x00,0x00,0x7f,0x63,0x67,0x30,0x63,
0x63,0x30,0x30,0x30,0x63,0x30,0x00,0x7f,0x63,0x7c,0x30,0x63,
0x63,0x30,0x30,0x30,0x63,0x10,0x00,0x77,0x63,0x6e,0x30,0x66,
0x63,0x3f,0x3f,0x3f,0x3e,0x20,0x00,0x63,0x3e,0x67,0x3f,0x7c,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
};static const GLfloat s_vertices[] = {
-1.0f, 1.0f, 0.0f, // Position 0
0.0f, 0.0f, // TexCoord 0
-1.0f, -1.0f, 0.0f,
0.0f, 0.0625f,
1.0f, -1.0f, 0.0f,
0.75f, 0.0625f,
1.0f, 1.0f, 0.0f,
0.75f, 0.0f,
};
static const GLushort s_indices[] = { 0, 1, 3, 2 };static GLuint load_shader( GLenum type, const char *src )
{
GLuint shader;shader = glCreateShader( type );
glShaderSource( shader, 1, &src, NULL );
glCompileShader( shader );return shader;
}static GLuint setup_tex()
{
int i, j, k;
GLuint textureId;
GLubyte pixels[TEX_W*TEX_W * 3]; // ちょっと大きいけどglPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
glGenTextures( 1, &textureId );
glBindTexture( GL_TEXTURE_2D, textureId );// ドットイメージテクスチャ化
for( i = 0; i < 8; i++ )
{
for( j = 0; j < 12; j++ )
{
for( k = 0; k < 8; k++ )
{
GLubyte val = ( (s_acDotImg[i][j] & (1<<(7-k))) ? 0xff : 0 );
int index = (i*128+j*8+k)*3;
pixels[index+0] = val;
pixels[index+1] = val;
pixels[index+2] = val;
}
}
}glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, TEX_W, TEX_W, 0, GL_RGB, GL_UNSIGNED_BYTE, pixels );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
glActiveTexture( GL_TEXTURE0 );
glBindTexture( GL_TEXTURE_2D, textureId );return textureId;
}static void setup_vtx( glhandle *handle, GLuint positionLoc, GLuint texCoordLoc, GLuint samplerLoc )
{
GLuint s_vertexPosObject, s_indexObject;
glGenBuffers(1, &s_vertexPosObject);
glBindBuffer(GL_ARRAY_BUFFER, s_vertexPosObject );
glBufferData(GL_ARRAY_BUFFER, sizeof(s_vertices), s_vertices, GL_STATIC_DRAW );glGenBuffers(1, &s_indexObject);
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, s_indexObject );
glBufferData( GL_ELEMENT_ARRAY_BUFFER, sizeof(s_indices), s_indices, GL_STATIC_DRAW );glBindBuffer(GL_ARRAY_BUFFER, s_vertexPosObject);
glVertexAttribPointer( positionLoc, 3, GL_FLOAT, GL_FALSE, 5 * 4, 0 );
glVertexAttribPointer( texCoordLoc, 2, GL_FLOAT, GL_FALSE, 5 * 4, (const GLvoid *)(3 * 4) );
glEnableVertexAttribArray( positionLoc );
glEnableVertexAttribArray( texCoordLoc );glUniform1i( samplerLoc, 0 );
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, s_indexObject );
}static void initialize( glhandle *handle )
{
GLuint positionLoc, texCoordLoc, samplerLoc;handle->vertexShader = load_shader( GL_VERTEX_SHADER, s_vShaderStr );
handle->fragmentShader = load_shader( GL_FRAGMENT_SHADER, s_fShaderStr );handle->programObject = glCreateProgram();
glAttachShader( handle->programObject, handle->vertexShader );
glAttachShader( handle->programObject, handle->fragmentShader );
glLinkProgram( handle->programObject );
glUseProgram( handle->programObject );positionLoc = glGetAttribLocation( handle->programObject, "a_position" );
texCoordLoc = glGetAttribLocation( handle->programObject, "a_texCoord" );
samplerLoc = glGetUniformLocation( handle->programObject, "s_texture" );handle->textureId = setup_tex();
setup_vtx(handle, positionLoc, texCoordLoc, samplerLoc);
}static void release( glhandle *handle )
{
glDeleteTextures(1, &handle->textureId);
glDeleteShader(handle->fragmentShader);
glDeleteShader(handle->vertexShader);
glDeleteProgram(handle->programObject);
}static void display()
{
glClear(GL_COLOR_BUFFER_BIT);glDrawElements( GL_TRIANGLE_STRIP, sizeof(s_indices)/sizeof(s_indices[0]), GL_UNSIGNED_SHORT, 0 );
SDL_GL_SwapBuffers();
}int main(int argc, char *argv[])
{
glhandle handle;SDL_Init(SDL_INIT_VIDEO);
SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
SDL_SetVideoMode(96*2, 8*2, 32, SDL_OPENGL);
#ifndef EMSCRIPTEN
glewInit();
#endifinitialize(&handle);
display();
SDL_Event ev;
int bExit = 0;
while(bExit == 0)
{
while(SDL_PollEvent(&ev))
{
if(ev.type == SDL_QUIT)
{
bExit = 1;
break;
}
}
SDL_Delay(20);
}
SDL_Quit();release(&handle);
return 0;
}
Ubuntuでboost
Ubuntu12.04にboostをapt-getでインストール。
$ sudo apt-get install libboost-dev build-essential
BOOST_VERSIONは104601となっている。
[hello.cpp]
#includeビルド。
#includeint main()
{
std::cout << boost::format("%s\n") % "hello, world";
return 0;
}
$ gcc hello.cpp -lstdc++ -o hello
実行
$ ./hello
hello, world無事表示された。
Ubuntu+eclipse+CDTでhello, world
まず、eclipseをインストール。環境はUbuntu12.04。
$ sudo apt-get install eclipse
eclipse起動。(日本語にするのが面倒なので英語のまま)
[Help]-[About Eclipse Platform]メニューを選択すると「Version: 3.7.2」と表示されている。
[Help]-[Install New Software...]メニューを選択。
「Work with」のコンボボックスから「Indigo Update Site-http://download.eclipse.org/releases/indigo」を選択する。
「Programming Languages」-「C/C++ Development Tools」にチェックを入れ、「Next」ボタンをクリック、以下指示に従ってインストール。
再起動を促すダイアログが出るので「Restart」ボタンで再起動。
[File]-[New]-[Project...]メニューを選択。
「C/C++」-「C Project」を選択して「Next」ボタンをクリック。
「Project name」に「hello」と入力。
「Executable」-「Hello World ANSI C Project」を選択し「Finish」ボタンをクリックしてプロジェクト作成。
[Project]-[Build Project]メニューを選択してビルド。
[Run]-[Run]メニューを選択して実行。
Consoleビューに
!!!Hello World!!!と表示された。
MinGW(+CMake)でhello, world
Windows上でもちょっとしたコードはコマンドラインのほうが便利じゃね?ということでMinGW(+CMake)をWindowsXPにインストールしてみる。
まずは、MinGWとCMakeをダウンロード。
こことここからmingw-get-inst-20120426.exeとcmake-2.8.8-win32-x86.exeをダウンロード。
どちらもインストーラーなので指示に従いインストール。
基本デフォルトのままだが、MinGWのインストーラーのデフォルトでは"C++ Compiler"が選択されていないのでチェックを入れて追加した。(今回の手順では本来必要ないが、定番なので"MinGW Developer Toolkit"もチェックを入れて追加した。)
CMakeは今回コマンドラインで使うので"Add CMake to the system PATH for current users"にチェックを入れる。
いつもの。
[hello.cpp]
#include
int main()
{
printf("hello, world\n");
return 0;
}
CMake用にCMakeLists.txtを作成。
[CMakeLists.txt]
add_executable(hello hello.cpp)
>PATH=C:\MinGW\bin;%PATH%
>cmake -G "MinGW Makefiles"
>mingw32-make
実行。
>hello.exe
無事
hello, worldと表示された。