1

私の目的は、ここの Android OpenGL ES チュートリアルからの形状作成を一般化することです : http://developer.android.com/training/graphics/opengl/shapes.html

val squareCoords = Array( -0.5f,  0.5f, 0.0f,   // top left
  -0.5f, -0.5f, 0.0f,   // bottom left
  0.5f, -0.5f, 0.0f,   // bottom right
  0.5f,  0.5f, 0.0f ) // top right

val vertexBuffer = ByteBuffer.allocateDirect(
  // (# of coordinate values * 4 bytes per float)
  squareCoords.length * 4)
  .order(ByteOrder.nativeOrder())
  .asFloatBuffer()
  .put(squareCoords)
  .position(0)

そのため、float サイズはハードコーディングされています。しかし、私もいくつかの短い配列を持っています:

val drawOrder = Array[Short] ( 0, 1, 2, 0, 2, 3 ) 
val drawListBuffer = ByteBuffer.allocateDirect(
  // (# of coordinate values * 2 bytes per short)
  drawOrder.length * 2)
.order(ByteOrder.nativeOrder())
.asShortBuffer()
drawListBuffer.put(drawOrder)
drawListBuffer.position(0)

コードは似ていますが、課題の部分は、この場合、適切なメソッド asFloatBuffer()/asShortBuffer() を選択し、適切なプリミティブ値を使用することです。

この問題を解決するために、次のコードを書きました。

import scala.reflect.runtime.universe._

implicit class SByteBuffer[T <: AnyVal : TypeTag] (coords: Array[T]) {
  private val length = coords.length
  def buffer(): Buffer = {

    def allocateBb(mod: Int) = {
      ByteBuffer.allocateDirect(length * mod)
      .order(ByteOrder.nativeOrder())
    }
    val buffer = typeOf[T] match {
      case t if t =:= typeOf[Float] => allocateBb(4).asFloatBuffer().put(coords.asInstanceOf[Array[Float]])
      case t if t =:= typeOf[Short] => allocateBb(2).asShortBuffer().put(coords.asInstanceOf[Array[Short]])
    }
    buffer.position(0) 
  }
} 

val squareCoords = Array( -0.5f,  0.5f, 0.0f,   // top left
  -0.5f, -0.5f, 0.0f,   // bottom left
  0.5f, -0.5f, 0.0f,   // bottom right
  0.5f,  0.5f, 0.0f ) // top right

val vertexBuffer = squareCoords.buffer()

しかし、複雑すぎるようで、コードの繰り返しがあります。このコードをリファクタリングしてより簡潔に見えるようにし、実行時の型チェックをなくす方法についてアドバイスをいただけますか?

4

1 に答える 1

1

サポートするプリミティブ型ごとに個別の暗黙的なクラスを作成する方がよいでしょう。

abstract class ArrayOpsBase[T <: AnyVal] ( val coords: Array[T] ) {
  protected val length = coords.length
  protected def allocateBb(mod: Int) = {
    ByteBuffer.allocateDirect(length * mod)
    .order(ByteOrder.nativeOrder())
  }
  def buffer(): Buffer
}

implicit class FloatArrayBufferOps( coords: Array[Float] ) extends ArrayOpsBase[Float]( coords ) {
  def buffer = allocateBb(4).asFloatBuffer.put( coords ).position( 0 )
}
implicit class ShortArrayBufferOps( coords: Array[Short] ) extends ArrayOpsBase[Short]( coords ) {
  def buffer = allocateBb(2).asShortBuffer.put( coords ).position( 0 )
}
于 2013-03-01T13:55:18.323 に答える