ã¾ããã
æ ªå¼ä¼ç¤¾ã¹ãã¼ã¹ãªã¼ Androidã¨ã³ã¸ãã¢ã®ãµãã¾ã¡ã§ãã æ®æ®µã¯å¼ç¤¾ãµã¼ãã¹ã®ãã¼ã«ã§ããAndroidã¢ããªãSpacely Photo Taskããéçºãã¦ãã¾ãã ç¾å¨ãå¾è¿°ããããã©ãç»åã®360°Viewerããã£ããã£ã¼ããåç»ãçæããéçºã«åãçµãã§ããã æ¬è¨äºã§ã¯éçºã§å¾ãç¥è¦ãå ã«ãGLSurfaceViewã®æ´»ç¨æ¹æ³ãä¸é¨ãç´¹ä»ãã¾ãã
Android x OpenGLãªãGLSurfaceView
GLSurfaceViewã¨ã¯ãOpenGL ESããµãã¼ããã¦ãããAndroidã®3Dæç»ãè¡ãããã®Viewã§ããæç»ã«ã¯GPUãæ´»ç¨ãã¦ãããã¨ã§ã¡ã¤ã³ã¹ã¬ããã®è² è·ã軽æ¸ã§ããé«éãªãã¬ã¼ã ã¬ã¼ãã§ã®æç»ãå¯è½ã ã¨ããç¹å¾´ãããã¾ãã å¼ç¤¾ã§ã¯ãããã©ãç»åã®360°Viewerã§ä½¿ç¨ãã¦ãã¾ãã
(åè)GLSurfaceViewã使ã£ãããã©ãç»åã®360°Viewer
CustomRendererã§ã®bitmapçæ
ä»å360°Viewerãåç»åããã«ããã£ã¦ã以ä¸ã®ã¹ããããè¨å®ãã¾ããã
- viewerã®è¡¨ç¤ºé åãbitmapã¨ãã¦ãã¬ã¼ã åä½ã§åå¾
- åå¾ããbitmapã®listãç¹ãåããã¦ãvideoã¸å¤æ
æ¬è¨äºã¯ã¹ããã1ã®bitmapsãã©ãä½ã£ããã¨ããé¨åã«ãªãã¾ãã
GLSurfaceViewã¯ã©ã¹ã¯Rendererãæã£ã¦ãã¾ããGLSurfaceViewã¯é常ããã®Interfaceãç¶æ¿ããclassãä½æããsetRendererãå¼ã³åºãã¦RendererãGLSurfaceViewã«æ¸¡ãã¾ãã Rendererã«ããã以ä¸ã®å¶å¾¡ãå¯è½ã§ãã
- onDrawFrame(gl: GL10)ï¼ç¾å¨ã®ãã¬ã¼ã æç»ããã¬ã¼ã æ¯ã«å¼ã°ããã
- onSurfaceChanged(gl: GL10, width: Int, height: Int)ï¼GLSurfaceViewã®è¡¨ç¤ºãµã¤ãºãæ´æ°ããããå¼ã°ããã
- onSurfaceCreated(gl: GL10, config: EGLConfig)ï¼GLSurfaceViewä½ææã«å¼ã°ããã
GL10ãæ´»ç¨ã§ããããªã®ã§ã以ä¸ã®ããã«æ¸ãã¾ããã
override fun onSurfaceCreated(gl: GL10, config: EGLConfig) {  super.onSurfaceCreated(gl, config)  this.gl = gl } override fun onSurfaceChanged(gl: GL10, width: Int, height: Int) {  super.onSurfaceChanged(gl, width, height)  this.width = width  this.height = height  val buffer = ByteBuffer.allocateDirect(width * height * 4)  buffer.order(ByteOrder.nativeOrder())  this.buffer = buffer.asIntBuffer() } override fun onDrawFrame(gl: GL10) {  super.onDrawFrame(gl)  createBitmap() } private fun createBitmap() {  gl?.let {   val intArray = IntArray(width * height)   buffer.position(0)   it.glReadPixels(0, 0, width, height, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, buffer)   buffer.get(intArray)       val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)   buffer.position(0)   bitmap.copyPixelsFromBuffer(buffer)   buffer.clear()       listener.setBitmap(bitmap)  } }
GL10ãä¿æããã¦ãã·ã³ãã«ã«bitmapãçæããããã¨ãã§ãã¾ããã çµæã¯ä»¥ä¸ã®ã¨ããã§ãã
çãã課é¡ã¨å¯¾å¦æ³
çæç©ããã以ä¸3ã¤ã®èª²é¡ãèãã¾ããã
ç»åãä¸ä¸å転ãã¦ãã
 GLSurfaceViewããbitmapãåå¾ããã¨ãä¸ããä¸ã«åãã£ã¦pixelãåå¾ããã®ã§ããã®ã¾ã¾ã ã¨ä¸ä¸å転ã«ãªãããã§ããMatrixã使ã£ã¦bitmapãå¤æãããå¿ è¦ãããã¾ããã
val matrix = Matrix() matrix.setScale(1f, -1f) //Y軸ãå転ããã val flippedBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.width, bitmap.height, matrix, true) //æã£ã¦ããbitmapãå¤æãã
縦横æ¯ããã¾ãåæ ããã¦ããªã
 æ±ãGL10ã«å¯¾ãã¦é©åã«é«ãã¨æ¨ªå¹ ãæå®ããªãã¨ãæ£æ¹å½¢ã«ãªã£ã¦ãã¾ãããã§ããglViewPortãsetããå¿ è¦ãããã¾ããã
gl.glViewport(0, 0, width, height)
ãã¬ã¼ã ã¬ã¼ããå¶éã§ãã¦ããªã
 ä»ã®ã¾ã¾ã ã¨éå°ã«bitmapãçæãã¦ã¡ã¢ãªãå§è¿«ããããªãã®ã§ã30fps~45fpsç¨åº¦ã«å¶éããå¿ è¦ãããã¾ããã
val currentTime = System.currentTimeMillis() val elapsedTime = currentTime - lastCalledPreviewTime if (elapsedTime >= 1000 / fps) { // 1000msãããä½åå¼ã¶ããå¶é  lastCalledPreviewTime = currentTime  //do something }
ä¿®æ£
ä¸è¨è§£æ¶æ¡ãåæ ããçµæãã以ä¸ã®ã¨ããã§ãã
override fun onSurfaceCreated(gl: GL10, config: EGLConfig) {  super.onSurfaceCreated(gl, config)  this.gl = gl } override fun onSurfaceChanged(gl: GL10, width: Int, height: Int) {  super.onSurfaceChanged(gl, width, height)  gl.glViewport(0, 0, width, height) //表示é å  this.width = width  this.height = height  val buffer = ByteBuffer.allocateDirect(width * height * 4)  buffer.order(ByteOrder.nativeOrder())  this.buffer = buffer.asIntBuffer() } override fun onDrawFrame(gl: GL10) {  super.onDrawFrame(gl)  val currentTime = System.currentTimeMillis()  val elapsedTime = currentTime - lastCalledPreviewTime  if (elapsedTime >= 1000 / fps) { // ãã¬ã¼ã ã¬ã¼ãå¶é   lastCalledPreviewTime = currentTime   createBitmap()  } } private fun createBitmap() {  gl?.let {   val intArray = IntArray(width * height)   buffer.position(0)   it.glReadPixels(0, 0, width, height, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, buffer)   buffer.get(intArray)       val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)   buffer.position(0)   bitmap.copyPixelsFromBuffer(buffer)   buffer.clear()   val matrix = Matrix()   matrix.setScale(1f, -1f) //ä¸ä¸å転   val flippedBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.width, bitmap.height, matrix, true)   listener.setBitmap(flippedBitmap)  } }
æå¾ ããçµæãå¾ããã¨ãã§ãã¾ããã
æå¾ã«
spacelyã§ã¯ä¸ç·ã«åãã¦ãã ããæ¹ã大åéä¸ã§ãã