*第5回目 CocoaでOpenGL [#y9620237]
 第2回目CocoaでOpenGLで作ったプログラムにテクスチャ表示を追加してみます。
**プログラム作成 [#w45c8a08]
***image.hpp [#cdc3fcf6]
 class Image
 {
 public:
 	Image(void);
 	~Image(void);
 	void Release(void);
 	bool Load(char* name, char* type);
 	int GetWidth(void);
 	int GetHeight(void);
 	unsigned char* GetBuffer(void);
 private:
 	unsigned char* buffer;
 	int width;
 	int height;
 	int size;
 private:
 	Image(Image&);
 	Image& operator = (Image&);
 };
#author("2018-06-18T16:11:35+09:00","default:kuran","kuran")

 C++形式でImageクラスを作ります。
***image.mm [#a5a0ccaa]
 #import <Cocoa/Cocoa.h>
 #import "image.hpp"
 
 Image::Image(void)
 :buffer(0), width(0), height(0)
 {
 }
 
 Image::~Image(void)
 {
 	Release();
 }
 
 void Image::Release(void)
 {
 	if(buffer)
 	{
 		delete [] buffer;
 		buffer = 0;
 		width = 0;
 		height = 0;
 	}
 }
 
 bool Image::Load(char* name, char* type)
 {
 	Release();
 	NSImage* image;
 	NSBitmapImageRep* image_rep;
 	NSBundle *bundle;
 	NSString *filepath;
 	bundle = [NSBundle mainBundle];
 	filepath = [bundle pathForResource:[NSString stringWithCString:name] ofType:[NSString stringWithCString:type]];
 	image = [[[NSImage alloc] initWithContentsOfFile: filepath] autorelease];
 	image_rep = [[NSBitmapImageRep alloc] initWithData : [image TIFFRepresentation]];
 	width = static_cast<int>([image_rep pixelsWide]);
 	height = static_cast<int>([image_rep pixelsHigh]);
 	buffer = new unsigned char[width * height * 4];
 	memcpy(buffer, static_cast<unsigned char*>([image_rep bitmapData]), width * height * 4);
 	[image_rep release];
 	return true;
 }
 
 int Image::GetWidth(void)
 {
 	return width;
 }
 
 int Image::GetHeight(void)
 {
 	return height;
 }
 
 unsigned char* Image::GetBuffer(void)
 {
 	return buffer;
 }

 拡張子は.mmですがクラス自体はC++形式です、内部ではObjectiveC形式の関数を呼び出しています。
 このImageクラスはC++で使用することができます。
 バッファのサイズ計算の手を抜いているため画像の読み込みは
 アルファ情報付きのフルカラー(32ビット)のみ読み込むことが可能です。
**プログラム修正 [#ae00a8e7]
***render.hpp [#bdf4b974]
 #ifndef RENDER_HPP
 #define RENDER_HPP
 
 #ifdef __cplusplus
 extern "C"
 {
 #endif
 
 void Render_Initialize(void);
 void Render_Draw(void);
 void Render_Update(void);
 
 #ifdef __cplusplus
 }
 #endif
 
 #endif

 これは前回と同じ。
***render.cpp [#reb5e49e]
 #include <stdio.h>
 #include <math.h>
 #include <OpenGL/OpenGL.h>
 #include <OpenGL/gl.h>
 #include <OpenGL/glu.h>
 #include "image.hpp"
 #include "render.hpp"
 
 static int anime = 0;
 static int animespeed = 0;
 static GLuint texturenumber[2];
 static float TextureWidth[2];
 static float TextureHeight[2];
 
 void Render_Initialize(void)
 {
 	int i;
 	float fovy;
 	float depth;
 	// OpenGL setup
 	glLoadIdentity();
 	gluPerspective(30.0f, 640.0f / 480.0f, 1.0f, 10000.0f);
 	fovy = 30.0f * 3.1415928f / 180.0f;
 	depth = 480.0f / tanf(fovy / 2.0f) / 2.0f;
 	gluLookAt(0.0f, 0.0f, depth, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);
 	glPolygonMode(GL_FRONT, GL_FILL);
 	glPolygonMode(GL_BACK, GL_FILL);
 	glDisable(GL_CULL_FACE);
 	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
 	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 	glEnable(GL_BLEND);
 	glEnable(GL_TEXTURE_2D);
 	// Texture load
 	glGenTextures(2, texturenumber);
 	Image image;
 	for(i = 0; i < 2; i ++)
 	{
 		if(i == 0)
 		{
 			image.Load("fighter1", "png");
 		}
 		else
 		{
 			image.Load("fighter2", "png");
 		}
 		TextureWidth[i] = static_cast<float>(image.GetWidth());
 		TextureHeight[i] = static_cast<float>(image.GetHeight());
 		glBindTexture(GL_TEXTURE_2D, texturenumber[i]);
 		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.GetWidth(), image.GetHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, image.GetBuffer());
 		glBindTexture(GL_TEXTURE_2D, 0);
 	}
 }
 
 void DrawRectangle(int texture, float x1, float y1, float x2, float y2, float z, float texture_x, float texture_y, float texture_width, float texture_height)
 {
 	float s1;
 	float t1;
 	float s2;
 	float t2;
 	s1 = (texture_x - 0.5f) / TextureWidth[texture];
 	t1 = (texture_y - 0.5f) / TextureHeight[texture];
 	s2 = (texture_x + texture_width - 0.5f) / TextureWidth[texture];
 	t2 = (texture_y + texture_height - 0.5f) / TextureHeight[texture];
 	glPushMatrix();
  	glRotatef(0.0f, 0.0f, 0.0f, 1.0f);
 	glBindTexture(GL_TEXTURE_2D, texturenumber[texture]);
 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 	glBegin(GL_QUADS);
 	glColor3d(1.0f, 1.0f, 1.0f);
 	glTexCoord2f(s1, t1);
 	glVertex3f(x1, y1, z);
 	glTexCoord2f(s2, t1);
 	glVertex3f(x2, y1, z);
 	glTexCoord2f(s2, t2);
 	glVertex3f(x2, y2, z);
 	glTexCoord2f(s1, t2);
 	glVertex3f(x1, y2, z);
 	glEnd();
 	glPopMatrix();
 }
 
 void Render_Draw(void)
 {
 	int anime_table[8] = {0, 1, 2, 3, 4, 3, 2, 1};
 	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
 	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 	DrawRectangle(0, -128.0f, 0.0f, -128.0f + 48.0f, -48.0f, 0.0f, static_cast<float>(anime_table[anime]) * 48.0f, 0.0f, 48.0f, 48.0f);
 	DrawRectangle(1, 128.0f, 0.0f, 128.0f + 48.0f, -48.0f, 0.0f, static_cast<float>(anime_table[anime]) * 48.0f, 0.0f, 48.0f, 48.0f);
 	glFlush();
 }
 
 void Render_Update(void)
 {
 	animespeed ++;
 	if(animespeed > 30)
 	{
 		anime ++;
 		if(anime > 7)
 		{
 			anime = 0;
 		}
 		animespeed = 0;
 	}
 }

 Render_InitializeではOpenGLの初期化、2枚のテクスチャの読み込みをしています。
 Render_Drawでは画面の左右にテクスチャを表示しています。
 左はfighter1.png、右はfighter2.pngを表示。
 各テクスチャは256x64の大きさで48x48のキャラクタが描かれています。
 それをアニメーション表示しています。
 DrawRectangleはテクスチャの一部を切り取り画面に表示する関数です。
 MacBookの場合はなぜか
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 の2行を省略するとテクスチャが表示されなくなります。謎。
 Render_Updateはアニメーションのコマ数を制御しています。
**実行結果 [#t58c3369]
#ref(OpenGLSample_20090601.jpg)~
**ダウンロード [#o3efd960]
#ref(http://www.ripple.gr.jp/~kuran_kuran/bin/download/OpenGLSample_20090601.zip)~

[[前に戻る>プログラミング]]


トップ   編集 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS