Integrating Zernikalos
Learn how to initialize the engine, load resources, and implement your first scene on Android, iOS, and Web.
1. Engine & View Setup
The first step is to prepare the surface where the engine will render. Each platform uses its own native view.
Zernikalos provides a custom ZernikalosView (which wraps a GLSurfaceView). Add it to your layout:
<zernikalos.ui.ZernikalosView
android:id="@+id/render_surface"
android:layout_width="match_parent"
android:layout_height="match_parent" />Then, initialize the engine in your Activity:
val engine = Zernikalos()
val renderSurface = findViewById<ZernikalosView>(R.id.render_surface)2. Core Concepts
Before diving into code, here are the three pillars of a Zernikalos application:
Loading Resources (.zko)
All 3D assets (models, textures, animations) must be bundled into a .zko file using the Nest App.
Place your .zko files in the src/main/assets/ directory of your Android project.
The ZContext
The ZContext is passed to all lifecycle methods. It gives you access to the active scene, the activeCamera, and the underlying rendering state.
Lifecycle Methods
You control the engine via the ZSceneStateHandler interface:
onReady: Called once when the engine is initialized. Ideal for loading models.onUpdate: Called every frame. Use this for game logic and forZActionPlayer.update()when playing skeletal clips (see Playing skeletal animations).onResize: Called when the view dimensions change.onRender: Called every frame for the final draw pass.
3. Basic State Handler Snippets
These snippets show the minimal logic required to get the engine running.
engine.initialize(renderSurface, object : ZSceneStateHandler {
override fun onReady(context: ZContext, done: () -> Unit) {
val bytes = assets.open("model.zko").use { it.readBytes() }
val zko = loadFromProto(bytes)
val scene = ZScene()
scene.addChild(zko.root)
context.scene = scene
done()
}
override fun onUpdate(context: ZContext, done: () -> Unit) = done()
})4. Complete Samples
Finally, here are full, copy-pasteable examples for each platform including camera setup and a basic rotation.
import android.os.Bundle
import androidx.activity.ComponentActivity
import kotlinx.coroutines.*
import zernikalos.*
import zernikalos.context.ZContext
import zernikalos.loader.loadFromProto
import zernikalos.objects.*
import zernikalos.scenestatehandler.ZSceneStateHandler
import zernikalos.search.findFirstCamera
import zernikalos.ui.ZernikalosView
class MainActivity : ComponentActivity() {
private val scope = CoroutineScope(Job() + Dispatchers.Main)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val renderSurface = ZernikalosView(this)
setContentView(renderSurface)
val engine = Zernikalos()
engine.initialize(renderSurface, object : ZSceneStateHandler {
private var rootGroup: ZGroup? = null
override fun onReady(context: ZContext, done: () -> Unit) {
scope.launch {
val bytes = assets.open("scene.zko").use { it.readBytes() }
val zko = loadFromProto(bytes)
rootGroup = zko.root as? ZGroup
val scene = ZScene()
val camera = ZCamera()
scene.addChild(camera)
scene.addChild(zko.root)
context.scene = scene
context.activeCamera = findFirstCamera(scene)
done()
}
}
override fun onUpdate(context: ZContext, done: () -> Unit) {
rootGroup?.transform?.rotate(0.1f, 0f, 1f, 0f)
done()
}
})
}
}What's next
- Loading a model (.zko) — assets paths,
loadFromProto/loadFromUrl, andfindFirstModel - Playing skeletal animations —
ZActionPlayer, clips, andonUpdate - Scene & camera — scene graph, default scene, and
activeCamera - Lighting your scene — light types and engine limits