- 追加された行はこの色です。
- 削除された行はこの色です。
*第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&);
};
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)~
[[前に戻る>プログラミング]]