class CustomViewer {
companion object {
init {
Utils.init()
}
}
private lateinit var choreographer: Choreographer
private lateinit var modelViewer: ModelViewer
fun loadEntity() {
choreographer = Choreographer.getInstance()
}
fun setSurfaceView(mSurfaceView: SurfaceView) {
modelViewer = ModelViewer(mSurfaceView)
mSurfaceView.setOnTouchListener(modelViewer)
modelViewer.scene.skybox = Skybox.Builder().build(modelViewer.engine)
modelViewer.scene.skybox?.setColor(1.0f, 1.0f, 1.0f, 1.0f) //White color
}
fun loadGlb(context: Context, name: String) {
val buffer = readAsset(context, "models/${name}.glb")
modelViewer.apply {
loadModelGlb(buffer)
transformToUnitCube()
}
}
fun loadGlb(context: Context, dirName: String, name: String) {
val buffer = readAsset(context, "models/${dirName}/${name}.glb")
modelViewer.apply {
loadModelGlb(buffer)
transformToUnitCube()
}
}
fun loadGltf(context: Context, name: String) {
val buffer = context.assets.open("models/${name}.gltf").use { input ->
val bytes = ByteArray(input.available())
input.read(bytes)
ByteBuffer.wrap(bytes)
}
modelViewer.apply {
loadModelGltf(buffer) { uri -> readAsset(context, "models/$uri") }
transformToUnitCube()
}
}
fun loadGltf(context: Context, dirName: String, name: String) {
val buffer = context.assets.open("models/${dirName}/${name}.gltf").use { input ->
val bytes = ByteArray(input.available())
input.read(bytes)
ByteBuffer.wrap(bytes)
}
modelViewer.apply {
loadModelGltf(buffer) { uri -> readAsset(context, "models/${dirName}/$uri") }
transformToUnitCube()
}
}
fun loadIndirectLight(context: Context, ibl: String) {
// Create the indirect light source and add it to the scene.
val buffer = readAsset(context, "environments/venetian_crossroads_2k/${ibl}_ibl.ktx")
KTXLoader.createIndirectLight(modelViewer.engine, buffer).apply {
intensity = 50_000f
modelViewer.scene.indirectLight = this
}
}
fun loadEnviroment(context: Context, ibl: String) {
// Create the sky box and add it to the scene.
val buffer = readAsset(context, "environments/venetian_crossroads_2k/${ibl}_skybox.ktx")
KTXLoader.createSkybox(modelViewer.engine, buffer).apply {
modelViewer.scene.skybox = this
}
}
private fun readAsset(context: Context, assetName: String): ByteBuffer {
val input = context.assets.open(assetName)
val bytes = ByteArray(input.available())
input.read(bytes)
return ByteBuffer.wrap(bytes)
}
private val frameCallback = object : Choreographer.FrameCallback {
private val startTime = System.nanoTime()
override fun doFrame(currentTime: Long) {
val seconds = (currentTime - startTime).toDouble() / 1_000_000_000
choreographer.postFrameCallback(this)
modelViewer.animator?.apply {
if (animationCount > 0) {
applyAnimation(0, seconds.toFloat())
}
updateBoneMatrices()
}
modelViewer.render(currentTime)
}
}
fun onResume() {
choreographer.postFrameCallback(frameCallback)
}
fun onPause() {
choreographer.removeFrameCallback(frameCallback)
}
fun onDestroy() {
choreographer.removeFrameCallback(frameCallback)
}
}