Spriteクラスの全ソースコードです。
package <パッケージ名>; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; import javax.microedition.khronos.opengles.GL10; import android.graphics.Point; import android.graphics.PointF; import android.graphics.Rect; import android.opengl.GLU; import <パッケージ名>.Texture; import <パッケージ名>.Color; // スプライト public class Sprite { // 描画パラメータクラス public class DrawParam { public DrawParam( Texture image ) { m_Image = image; m_Pos = new PointF(); m_RotationZ = 0.0f; m_Scale = new PointF( 1.0f, 1.0f ); m_ImageRect = new Rect(); m_ImageCenter = new PointF(); m_Color = Color.White(); } public Texture m_Image; public PointF m_Pos; public float m_RotationZ; public PointF m_Scale; public Rect m_ImageRect; public PointF m_ImageCenter; public Color m_Color; } // コンストラクタ public Sprite( DrawDevice drawDevice ) { m_DrawDevice = drawDevice; // 頂点情報バッファ作成 { m_VertexPos = new BufferSet(); m_ImageRect = new BufferSet(); m_VertexColor = new BufferSet(); { m_VertexPos.Create( VERTEX_NUM * VERTEX_POS_ELEMENT_NUM ); m_ImageRect.Create( VERTEX_NUM * IMAGE_POS_ELEMENT_NUM ); m_VertexColor.Create( VERTEX_NUM * VERTEX_COLOR_ELEMET_NUM ); } } m_DrawScaleRate = 1.0f; m_StatusBarHeight = 0; m_DrawOffset = new Point( 0, 0 ); m_CameraModeOffset = new PointF( 0.0f, 0.0f ); m_ScaleColor = Color.White(); m_DrawColor = Color.White(); m_bScreenMode = true; m_PrevDrawColor = new Color( 0.0f, 0.0f, 0.0f, 0.0f ); SetLookPos( new PointF( 0.0f, 0.0f )); } // スクリーン変換行列更新 public void UpdateScreenMatrix( GL10 gl, int width, int height, int statusBarHeight ) { final float drawWidth = DrawDevice.DRAW_WIDTH; final float drawHeight = DrawDevice.DRAW_HEIGHT; { // 拡大率更新 final float widthScale = width / drawWidth; final float heightScale = height / drawHeight; m_DrawScaleRate = Math.min( widthScale, heightScale ); } final int viewWidth = ( int )( drawWidth * m_DrawScaleRate ); final int viewHeight = ( int )( drawHeight * m_DrawScaleRate ); { // 描画オフセット更新 m_DrawOffset.x = ( int )( width * 0.5f - viewWidth * 0.5f ); m_DrawOffset.y = ( int )( height * 0.5f - viewHeight * 0.5f ); } gl.glViewport( m_DrawOffset.x, m_DrawOffset.y, viewWidth, viewHeight ); //gl.glScissor( m_DrawOffset.x, m_DrawOffset.y, viewWidth, viewHeight ); //gl.glEnable( GL10.GL_SCISSOR_TEST ); gl.glMatrixMode( GL10.GL_PROJECTION ); gl.glLoadIdentity(); gl.glOrthof( 0.0f, drawWidth, drawHeight, 0.0f, 1.0f, 10.0f ); m_StatusBarHeight = statusBarHeight; } // スクリーン座標を描画座標に変換 public PointF ScreenPosToDrawPos( final PointF pos ) { PointF newPos = new PointF( pos.x, pos.y ); { newPos.x -= m_DrawOffset.x; newPos.y -= m_DrawOffset.y + m_StatusBarHeight; newPos.x /= m_DrawScaleRate; newPos.y /= m_DrawScaleRate; } return newPos; } // 見ている位置設定 public void SetLookPos( PointF lookPos ) { m_CameraModeOffset.x = -lookPos.x + DrawDevice.DRAW_WIDTH * 0.5f; m_CameraModeOffset.y = lookPos.y + DrawDevice.DRAW_HEIGHT * 0.5f; } // スケールカラー設定 public void SetScaleColor( Color color ) { m_ScaleColor.set( color ); } // スクリーンモード設定 public void SetScreenMode( boolean bScreenMode ) { m_bScreenMode = bScreenMode; } // 描画開始 public void Begin() { GL10 gl = m_DrawDevice.GetGl(); // テクスチャ有効化 gl.glActiveTexture( GL10.GL_TEXTURE0 ); // カメラ座標設定 GLU.gluLookAt( gl, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f ); // 頂点情報有効化 gl.glEnableClientState( GL10.GL_VERTEX_ARRAY ); gl.glEnableClientState( GL10.GL_COLOR_ARRAY ); // デフォルトはスクリーンモード SetScreenMode( true ); } // 描画終了 public void End() { } // 描画パラメータ作成 public DrawParam CreateDrawParam( Texture image ) { return new DrawParam( image ); } public DrawParam CreateDrawParamNoTexture() { return new DrawParam( null ); } // 描画 public void Draw( DrawParam param ) { if( !_IsDrawEnable( param )) return; GL10 gl = m_DrawDevice.GetGl(); final Texture image = param.m_Image; final Rect imageRect = param.m_ImageRect; final PointF imageCenter = param.m_ImageCenter; final Color color = param.m_Color; final float imageWidth = image.GetWidth(); final float imageHeight = image.GetHeight(); // 表示用行列設定 _UpdateWorldMatrix( gl, param ); // テクスチャ設定 gl.glEnable( GL10.GL_TEXTURE_2D ); gl.glBindTexture( GL10.GL_TEXTURE_2D, param.m_Image.GetTextureBindID()); // 頂点の位置設定 { final float leftPos = -imageCenter.x; final float topPos = -imageCenter.y; final float rightPos = leftPos + imageRect.width(); final float bottomPos = topPos + imageRect.height(); final float aVerticalPos[] = { leftPos, topPos, rightPos, topPos, leftPos, bottomPos, rightPos, bottomPos, }; m_VertexPos.SetArray( aVerticalPos ); gl.glVertexPointer( VERTEX_POS_ELEMENT_NUM, GL10.GL_FLOAT, 0, m_VertexPos.GetFloatBuffer()); } // テクスチャ領域設定 { final float imageWidthInv = 1.0f / imageWidth; final float imageHeightInv = 1.0f / imageHeight; final float leftImagePos = ( imageRect.left + 0.5f ) * imageWidthInv; final float topImagePos = ( imageRect.top + 0.5f ) * imageHeightInv; final float rightImagePos = ( imageRect.right - 0.5f ) * imageWidthInv; final float bottomImagePos = ( imageRect.bottom - 0.5f ) * imageHeightInv; final float aImageRect[] = { leftImagePos, topImagePos, rightImagePos, topImagePos, leftImagePos, bottomImagePos, rightImagePos, bottomImagePos, }; // テクスチャ座標有効化 gl.glEnableClientState( GL10.GL_TEXTURE_COORD_ARRAY ); m_ImageRect.SetArray( aImageRect ); gl.glTexCoordPointer( IMAGE_POS_ELEMENT_NUM, GL10.GL_FLOAT, 0, m_ImageRect.GetFloatBuffer()); } // 色設定 m_DrawColor.set( m_ScaleColor ); m_DrawColor.Mul( color ); if( !m_PrevDrawColor.equals( m_DrawColor )) { final float colorR = m_DrawColor.GetR(); final float colorG = m_DrawColor.GetG(); final float colorB = m_DrawColor.GetB(); final float colorA = m_DrawColor.GetA(); final float aColor[] = { colorR, colorG, colorB, colorA, colorR, colorG, colorB, colorA, colorR, colorG, colorB, colorA, colorR, colorG, colorB, colorA, }; m_VertexColor.SetArray( aColor ); gl.glColorPointer( VERTEX_COLOR_ELEMET_NUM, GL10.GL_FLOAT, 0, m_VertexColor.GetFloatBuffer()); m_PrevDrawColor.set( m_DrawColor ); } // 描画 gl.glDrawArrays( GL10.GL_TRIANGLE_STRIP, 0, VERTEX_NUM ); } // テクスチャ無し描画 public void DrawNoTexture( DrawParam param ) { if( !_IsDrawEnable( param )) return; GL10 gl = m_DrawDevice.GetGl(); final Rect imageRect = param.m_ImageRect; final PointF imageCenter = param.m_ImageCenter; final Color color = param.m_Color; // 表示用行列設定 _UpdateWorldMatrix( gl, param ); // テクスチャ設定 gl.glDisable( GL10.GL_TEXTURE_2D ); // 頂点の位置設定 { final float leftPos = -imageCenter.x; final float topPos = -imageCenter.y; final float rightPos = leftPos + imageRect.width(); final float bottomPos = topPos + imageRect.height(); final float aVerticalPos[] = { leftPos, topPos, rightPos, topPos, leftPos, bottomPos, rightPos, bottomPos, }; m_VertexPos.SetArray( aVerticalPos ); gl.glVertexPointer( VERTEX_POS_ELEMENT_NUM, GL10.GL_FLOAT, 0, m_VertexPos.GetFloatBuffer()); } // 色設定 m_DrawColor.set( m_ScaleColor ); m_DrawColor.Mul( color ); if( !m_PrevDrawColor.equals( m_DrawColor )) { final float colorR = m_DrawColor.GetR(); final float colorG = m_DrawColor.GetG(); final float colorB = m_DrawColor.GetB(); final float colorA = m_DrawColor.GetA(); final float aColor[] = { colorR, colorG, colorB, colorA, colorR, colorG, colorB, colorA, colorR, colorG, colorB, colorA, colorR, colorG, colorB, colorA, }; m_VertexColor.SetArray( aColor ); gl.glColorPointer( VERTEX_COLOR_ELEMET_NUM, GL10.GL_FLOAT, 0, m_VertexColor.GetFloatBuffer()); m_PrevDrawColor.set( m_DrawColor ); } // テクスチャ座標無効化 gl.glEnableClientState( GL10.GL_TEXTURE_COORD_ARRAY ); // 描画 gl.glDrawArrays( GL10.GL_TRIANGLE_STRIP, 0, VERTEX_NUM ); } // バッファセット private class BufferSet { // コンストラクタ public BufferSet() { m_FloatBuffer = null; } // 作成 public void Create( int arrayNum ) { ByteBuffer byteBuffer = ByteBuffer.allocateDirect( arrayNum * 4 ); { byteBuffer.order( ByteOrder.nativeOrder()); } m_FloatBuffer = byteBuffer.asFloatBuffer(); } // 配列設定 public void SetArray( float[] aValue ) { m_FloatBuffer.put( aValue ); m_FloatBuffer.position( 0 ); } // Floatバッファ取得 public FloatBuffer GetFloatBuffer() { return m_FloatBuffer; } private FloatBuffer m_FloatBuffer; } // ワールドマトリクス更新 private final void _UpdateWorldMatrix( GL10 gl, DrawParam param ) { PointF pos = param.m_Pos; PointF scale = param.m_Scale; if( !m_bScreenMode ) { // 注視点設定モードのときは座標変更 pos.x = pos.x + m_CameraModeOffset.x; pos.y = -pos.y + m_CameraModeOffset.y; } gl.glMatrixMode( GL10.GL_MODELVIEW ); gl.glLoadIdentity(); gl.glTranslatef( pos.x, pos.y, 0.0f ); gl.glRotatef( param.m_RotationZ, 0.0f, 0.0f, 1.0f ); gl.glScalef( scale.x, scale.y, 0.0f ); } // 描画する意味があるか? private final boolean _IsDrawEnable( DrawParam param ) { // アルファが0なら描画する意味無し if( param.m_Color.GetA() == 0.0f ) return false; final Rect imageRect = param.m_ImageRect; final PointF imageCenter = param.m_ImageCenter; final float imageLeft = -imageCenter.x; final float imageTop = -imageCenter.y; final float imageRight = imageRect.width() - imageCenter.x; final float imageBottom = imageRect.height() - imageCenter.y; final PointF scale = param.m_Scale; final float rotZ = param.m_RotationZ; final PointF pos = param.m_Pos; // モデルの位置計算 float drawLeftTopX = imageLeft; float drawLeftTopY = imageTop; float drawLeftBottomX = imageLeft; float drawLeftBottomY = imageBottom; float drawRightTopX = imageRight; float drawRightTopY = imageTop; float drawRightBottomX = imageRight; float drawRightBottomY = imageBottom; { // 拡大率 { drawLeftTopX *= scale.x; drawLeftTopY *= scale.y; drawLeftBottomX *= scale.x; drawLeftBottomY *= scale.y; drawRightTopX *= scale.x; drawRightTopY *= scale.y; drawRightBottomX *= scale.x; drawRightBottomY *= scale.y; } // Z軸回転 if( rotZ != 0.0f ) { final float rad = ( float )Math.toRadians( rotZ ); final float sin = ( float )Math.sin( rad ); final float cos = ( float )Math.cos( rad ); drawLeftTopX = drawLeftTopX * cos - drawLeftTopY * sin; drawLeftTopY = drawLeftTopX * sin + drawLeftTopY * cos; drawLeftBottomX = drawLeftBottomX * cos - drawLeftBottomY * sin; drawLeftBottomY = drawLeftBottomX * sin + drawLeftBottomY * cos; drawRightTopX = drawRightTopX * cos - drawRightTopY * sin; drawRightTopY = drawRightTopX * sin + drawRightTopY * cos; drawRightBottomX = drawRightBottomX * cos - drawRightBottomY * sin; drawRightBottomY = drawRightBottomX * sin + drawRightBottomY * cos; } // 位置計算 { final float posX = pos.x; final float posY = (( m_bScreenMode )? pos.y : -pos.y ); drawLeftTopX += posX; drawLeftTopY += posY; drawLeftBottomX += posX; drawLeftBottomY += posY; drawRightTopX += posX; drawRightTopY += posY; drawRightBottomX += posX; drawRightBottomY += posY; } } // 描画位置計算 // カメラモードのときはカメラ位置の分だけオフセットがある if( !m_bScreenMode ) { drawLeftTopX += m_CameraModeOffset.x; drawLeftTopY += m_CameraModeOffset.y; drawLeftBottomX += m_CameraModeOffset.x; drawLeftBottomY += m_CameraModeOffset.y; drawRightTopX += m_CameraModeOffset.x; drawRightTopY += m_CameraModeOffset.y; drawRightBottomX += m_CameraModeOffset.x; drawRightBottomY += m_CameraModeOffset.y; } // 上下左右の領域計算 final float left = Math.min( Math.min( Math.min( drawLeftTopX, drawLeftBottomX ), drawRightTopX ), drawRightBottomX ); final float top = Math.min( Math.min( Math.min( drawLeftTopY, drawLeftBottomY ), drawRightTopY ), drawRightBottomY ); final float right = Math.max( Math.max( Math.max( drawLeftTopX, drawLeftBottomX ), drawRightTopX ), drawRightBottomX ); final float bottom = Math.max( Math.max( Math.max( drawLeftTopY, drawLeftBottomY ), drawRightTopY ), drawRightBottomY ); // 描画範囲外なら描画する意味無し if(( left > DrawDevice.DRAW_WIDTH ) || ( top > DrawDevice.DRAW_HEIGHT ) || ( right < 0.0f ) || ( bottom < 0.0f )) return false; return true; } final static int VERTEX_NUM = 4; final static int VERTEX_POS_ELEMENT_NUM = 2; final static int IMAGE_POS_ELEMENT_NUM = 2; final static int VERTEX_COLOR_ELEMET_NUM = 4; private DrawDevice m_DrawDevice; private BufferSet m_VertexPos; private BufferSet m_ImageRect; private BufferSet m_VertexColor; private float m_DrawScaleRate; private int m_StatusBarHeight; private Point m_DrawOffset; private PointF m_CameraModeOffset; private Color m_ScaleColor; private Color m_DrawColor; private boolean m_bScreenMode; private Color m_PrevDrawColor; }