About LjES ver. 2.01 (2017/12/08)


The new version 2.01 of LjES has been released to adapt to the "Raspbian Stretch" with some new features. "libGLESv2.so" and "libEGL.so" had been renamed to "libbrcmGLESv2.so" and "libbrcmEGL.so" from Jessie to Stretch. LjES ver. 2.01 is backward compatible with LjES ver. 1.00. There is now support for Skeletal Animation and support for importing COLLADA files exported from Blender.

LjES is a small 3D framework for Raspberry Pi built on top of the OpenGL ES 2.0. LjES is written by 100% LuaJIT. The goal of this framework is to make 3D graphics programming easy. The Raspbian Linux disk image contains the LuaJIT-2.0. Installation of any packages is not required to use LjES on a Raspberry Pi.




ljes-2.01.tar.gz (514KB)
GitHub (https://github.com/jun-mizutani/ljes.git )

Commands below will download LjES and run the example application.

  curl -O https://www.mztn.org/rpi/ljes-2.01.tar.gz
  tar zxf ljes-2.01.tar.gz
  cd ljes-2.01
  cd examples
  luajit hand.lua

hand.lua: key binding

Hit [q] key to quit demo, [h] for help, [p] for screenshot.

key action
h Help
q Quit
w Node: rotate +X
s Node: rotate -X
a Node: rotate +Y
d Node: rotate -Y
z Node: rotate +Z
x Node: rotate -Z
e Bone: rotate +X
r Bone: rotate -X
y Bone: rotate +Y
u Bone: rotate -Y
c Bone: rotate +Z
v Bone: rotate -Z
o Hide Mesh
i Show Mesh
m Select Mesh (+1)
n Select Mesh (-1)
j Select Bone (+1)
k Select Bone (-1)
@ Start Animation
1 Start Action (1)
2 Start Action (2)
3 Start Action (3)
4 Start Action (4)
5 Start Action (5)
6 Start Action (0)
9 Show Bones
0 Hide Bones
p Screenshot
t Top Right
b Bottom Right
g Restore Size
f Full Screen

An introduction to LjES-2

LjES-2 is organized as shown in the figure below. A blue part (demo.lua) of the illustration shows a simple framework using the entire LjES. The module demo.lua is intended to be modified to fit your needs. The green parts (bcm.lua, egl.lua, png.lua, gles2.lua, termios.lua, util.lua) are the wrappers for the shared libraries of the Linux system (the red area in the figure). The yellow parts are the class libraries of LjES. These classes are responsible for the matrix calculation, the data transfer between CPU and GPU, shader programming required by OpenGL ES2. The light blue parts are the collada file loader and for the animation.

The class module dependency and the class hierarchy is shown in the figure below.


The examples below are the minimum code required to animate the Collada file and to draw a simple shape using LjES-2.

Collada Animation

The following code is an example to import and to animate the Collada file. LjES-2 only supports the collada file exported from Blender. A mesh in Blender will be converted into a Shape in LjES-2. The maximum number of bones per skeleton is 40 in a Shape. The origin (0, 0, 0) of a mesh object and the origin of an armature have to be matched to embed bones in the correct position.

package.path = "../LjES/?.lua;" .. package.path

local demo = require("demo")

if arg[1] ~= nil then
  collada_file = arg[1]
  print("usage: luajit dae_anim0.lua your_collada.dae")

demo.screen(0, 0)
local aSpace = demo.getSpace()
demo.backgroundColor(0.2, 0.2, 0.4)

-- load collada
local collada = ColladaShape:new()
local collada_text = util.readFile(collada_file)
collada:parse(collada_text ,true)
local shapes = collada:makeShapes(true, true)

-- set object
local node = aSpace:addNode(nil, "node")
for i = 1, #shapes do
  shapes[i]:shaderParameter("color", {0.8, 0.7, 0.6, 1.0})

-- set eye position
local eye = aSpace:addNode(nil, "eye")
local size =  demo.getShapeSize(shapes)
eye:setPosition(size.centerx, size.centery, size.max*2)

-- setup animation

-- call back function
function draw()
  demo.aText:writeAt(2, 24, "[q]  : quit")
  node.shapes[1].anim:play() -- play one frame of animation

-- main loop
demo.loop(draw, true)


You can write an application program which displays the rotating donut with only 20 lines of code. If you modify the line in red, the shape and the motion of the object will change. The other part of the code seldom needs to be changed. In this example, you don't need to use the OpenGL ES2 API nor matrix calculation.

package.path = "../LjES/?.lua;" .. package.path
local demo = require("demo")

demo.screen(0, 0)

local aSpace = demo.getSpace()

local eye = aSpace:addNode(nil, "eye")
eye:setPosition(0, 0, 30)

demo.backgroundColor(0.2, 0.2, 0.4)

local shape = Shape:new()
shape:donut(8, 3, 16, 16)
shape:shaderParameter("color", {0.5, 0.3, 0.0, 1.0})

local node = aSpace:addNode(nil, "node1")
node:setPosition(0, 0, 0)

function draw()

demo.loop(draw, true)

The example will end after about 80 seconds or when you press [q] key. If you hit [p] key, a screen shot will be saved with a file name "ss_date_time.png" at a current directory.

The code is explained in detail here.