My favorites | Sign in
Project Home Downloads Wiki Issues Source
extending engine features
Featured, Phase-Design, Phase-Implementation
Updated Jun 9, 2011 by kvarkus


This article explains how KRI engine features can be added from the outside. You can find all the extension mechanisms of the engine described here. We will also go step-by-step though a complete example of mesh morphing (shape keys in Blender) being implemented as a separate module.

Modularity features


You would have to modify some exporter code in order to add functionality to this stage. However, the native scene format has a chunk structure (Exporter), so adding new chunks will not break existing data loading procedure (just make sure you have no name collosions in chunk names). Here is an example of a chunk export:

out.begin('t_seq')	# image sequence
out.pack( '3H', user.frames, user.offset, user.start_frame )	# data
out.end()		# finish chunk


Loaders are registered in data managers and keyed by the return type. Here is an example loader of the text files into strings:

public class Text([of string] ):
	public def read(path as string) as string:
		return System.IO.File.ReadAllText(path)
loadText = Text()

Switch chooses an approriate loader based on the filename extension. Here is an application example (from

	swImage	=[of kri.buf.Texture]()
	swImage.ext['.tga'] = image.Targa()
	resMan.register( swImage )	# local data manager


KRI engine has an extension interface. Each extension adds some chunk readers to the native loader upon its construction. These are core extensions added automatically: ExMaterial, ExMesh, ExAnim and ExObject. They can be accessed via engine core: kri.Ant.Inst.loaders.*

Vertex attributes

Entity's store vertex buffer storage, as well as a corresponding mesh, may contain attributes you put in them. They will be accessed only by the shaders with matching input names and types.

Entity tags

You can add custom tags to entities and use them by your own renderers (see Entity).


Material in KRI is a container for meta data (see MetaData). You can have entirely new materials with your own meta-data and renderer techniques accessing them.


KRI engine allows compound renderers. You can find a chain renderer (is an analog to a list) and a job scheduler among the standard ones. All of them allows adding custom renderers (derived from kri.rend.Basic).

A simple renderer may operate on user-defined vertex attributes.

A render technique may use user-created meta blocks of the material to build its shaders.

Example: Morphing


The following code has been added to mesh exporting routine:

	for sk in (shapes.keys if mesh.shape_keys else []):
		# write shape key data


A tag class has been implemented to hold shape key data:

public class Tag( kri.ITag ):
	public final name	as string
	public final data	= kri.vb.Attrib()
	public relative	as Tag		= null
	private dirty	as bool		= false
	private val		as single	= 1f
	public Value	as single:
		get: return val
		set: dirty=true; val=value
	public def constructor(s as string):
		name = s


An extension class has been implemented. It should be registered by a user who wishes to load morph data.

public class Extra( kri.IExtension ):
	private def racShape(pl as, v as single, i as byte):
		keys = (pl as kri.Entity).enuTags[of Tag]()
		keys[i-1].Value = v
	# implementing IExtension
	def kri.IExtension.attach(nt as kri.load.Native) as void:
		nt.readers['v_shape']	= pv_shape	# register loader
		anil = kri.Ant.Inst.loaders.animations	# register animation channel
		anil.anid['v.value']	= kri.load.ExAnim.Rac(getReal,racShape)
	# shape chunk loader
	public def pv_shape(r as kri.load.Reader) as bool:
		e = r.geData[of kri.Entity]()	# get current entity
		if not (e and e.mesh):	return false
		tag = Tag( r.getString() )	# create a shape key tag
		tag.Value = r.getReal()		# read tag data
		ar = kri.load.ExMesh.GetArray[of Vector3]( e.mesh.nVert, r.getVector ),false)		# fill tag data
		kri.Help.enrich(, 3, 'vertex' )
		e.tags.Add(tag)			# add to the entity
		return true


The Update renderer does all the hard work of interpolating between shape keys in a shader. Refer to the actual source for details (support/morph).

public class Update( kri.rend.Basic ):
	public def constructor():
		pass # make shader
	public override def process(con as as void:
		for ent in kri.Scene.Current.entities:
			keys = ent.enuTags[of Tag]()
			# 1. check validity of the keys and the entity
			# 2. assign vertex attributes
			# 3. draw the mesh with transform feedback


There is a custom animation class designed to shift morphing coefficients. This animation should be played with an active update renderer in order to see the effect on the object.

public class Anim( kri.ani.Loop ):
	public final k0	as Tag
	public final k1	as Tag
	public def constructor(e as kri.Entity, s0 as string, s1 as string):
		assert s0 and s1 and s0!=s1
		k0 = k1 = null
		for key in e.enuTags[of Tag]():
			k0 = key	if == s0
			k1 = key	if == s1
		assert k0 and k1
	protected override def onRate(rate as double) as void:
		k0.Value = 1.0 - rate
		k1.Value = rate


This is a part of a typical user code that takes an advantage of the Morph module:

using win = kri.Window('kri.conf',0):
	# read the scene
	win.core.extensions.Add(support.morph.Extra())	# register an extension
	ln = kri.load.Native()
	at ='res/test_hair.scene')		
	ent = at.scene.entities[0]
	# add renderer
	view = kri.ViewScreen()
	rchain = kri.rend.Chain() = rchain
	win.views.Add( view )
	rchain.renders.Add( support.morph.Update() )
	# add an animation
	win.core.anim = al = kri.ani.Scheduler()
	morphNative = true	# programmable action
	morphExport = false	# exporter data curve
	if morphNative:
		amorph = support.morph.Anim(ent,'Basis','Key 1')
		amorph.lTime = 10.0
		al.add( amorph )
	elif morphExport:
		al.add('Action') )
	# main loop

Sign in to add a comment
Powered by Google Project Hosting