我的目标是在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)
因此,浮动大小是硬编码的。 但我也有一些短阵列:
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()
但它看起来太复杂了,并且有代码重复。 您能否建议如何重构此代码以使其更简洁,并可能摆脱运行时类型检查?
答案 0 :(得分: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 )
}