java - java/scala 中的原始对象大小和 'as<SomePrimitive>Buffer() 方法调用

标签 java scala dynamic reflection primitive-types

我的目标是概括 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()

但是看起来太复杂了,而且有代码重复。 您能否建议如何重构此代码以使其看起来更简洁并可能摆脱运行时类型检查?

最佳答案

您可能最好为您想要支持的每个基本类型创建单独的隐式类:

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 )
}

关于java - java/scala 中的原始对象大小和 'as<SomePrimitive>Buffer() 方法调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15158777/

相关文章:

java - 我如何从中间自动填充编辑文本?

java - Android Java CRC 十六进制输入

java - 为什么即使对于不相等的字符串,equalsignorecase 也会返回 true

scala - 结合Akka,Spray和嵌入式Jetty

c - 静态库和动态库有什么区别

PHP+AJAX+MYSQL 最后一个表单条目在 MySql 中创建一个新列

java.sql.SQLException : Invalid operation: wasNull() called with no data retrieved . 但我 'am' 检查它是否为空

scala - post 方法渲染 403 forbidden 页面而不是执行 post 方法代码

java - 为什么我的 PlayFramework 应用程序出现很长的超时?

asp.net-mvc - asp.net mvc多参数请求动态图片?