Table of Contents
24. Modules¶
This section has a lot of modules available and where I hope would be useful for you!
Even if you are learning LUA this is a interesting topic.
Have fun!
24.1. What is a Module?¶
Module is like a library that can be loaded using require
and has a single global name containing a table.
All functions and variables are wrapped in to a table which acts as a namespace.
Also, a well behaved module has necessary provisions to return this table on require
.
Module can be an .lua
, .Dll
or .so
extension.
A module can be an external extension for the project or not.
For example, we can consider to build a module that will use some resources from this engine like a vec3, particle system, blend operation , etc.
In another words, a modules can be an extension about what we have.
The next topics will present some modules available.
24.1.1. Creating and using Modules¶
The way for LUA 5.2 create module is described bellow:
First, we will create a file mymodule.lua
with the following content:
local mymodule = {}
function mymodule.foo()
print("Hello World from module!")
end
return mymodule
This is the basic concept of modules.
Now to use this new module in the interactive interpreter:
mymodule = require "mymodule"
mymodule.foo() -- Hello World from module!
For more information you can consult ModulesTutorial.
24.2. Parsing OBJ wavefront¶
Next we will demonstrate how to import from OBJ format using a modules written in LUA.
OBJ (or .OBJ
) is a geometry definition file format first
developed by Wavefront Technologies for its Advanced Visualizer animation package.
The file format is open and has been adopted by other 3D graphics application vendors.
The parser implemented here might NOT be the fully implementation but at least for this example works.
To do that we will use the following module: OBJ_parser.lua
You can download OBJ_parser.lua here
.
The following program will use the OBJ_parser.lua
to parse an OBJ format and
generate a mesh my_mesh.msh
:
--import our module OBJ parser OBJ_parser = require "OBJ_parser" --gray color background mbm.setColor(0.5,0.5,0.5) function saveFrameToMeshFile(fileName,tFrame,bCentralize) --meshDebug is used to create dynamically mesh in the engine. --For mesh it has to have at least one frame to be able to generate the mesh local stride = 3 --stride only can be 3 or 2. it means (x,y,z) or (x,y) local tMesh = meshDebug:new() --new mesh debug to store the information about our mesh local indexFrame = tMesh:addFrame(stride) -- Add one frame with stride 3 (x,y,z) local has_normal = OBJ_parser:has_normal(tFrame) local has_texture = OBJ_parser:has_texture(tFrame) print('Total subset:',#tFrame) print('Normal :',tostring(has_normal)) print('Uv :',tostring(has_texture)) -- Add vertex buffer first for i=1,#tFrame do local tSubset = tFrame[i] --add each subset on frame local indexSubset = tMesh:addSubSet(indexFrame) --add one subset for the first frame -- The table expected is : {{x,y,z,u,v,nx,ny,nz},{x,y,z,u,v,nx,ny,nz},{x,y,z,u,v,nx,ny,nz}, ...} if not tMesh:addVertex(indexFrame,indexSubset,tSubset.tVertex) then print("Error on add vertex buffer") return false end end --Now we add index buffer and apply the texture for indexSubset=1,#tFrame do local tSubset = tFrame[indexSubset] if not tMesh:addIndex(indexFrame,indexSubset,tSubset.tIndex) then print("Error on add index buffer") return false end --get texture (among the choices in the material) local sTexture = OBJ_parser:get_texture_from_material(tSubset.tMaterial) --apply the texture to frame / subset if not tMesh:setTexture(indexFrame,indexSubset,sTexture) then print("Error on set texture!") return false end end tMesh:setType('mesh') -- set it to mesh type --Advanced options (draw mode). we do not need to set it, but it is available --tMesh:setModeDraw('TRIANGLES') -- TRIANGLES (default), TRIANGLE_STRIP, TRIANGLE_FAN, LINES, LINE_LOOP, LINE_STRIP, POINTS --tMesh:setModeCullFace('FRONT') -- FRONT (default), BACK, FRONT_AND_BACK --tMesh:setModeFrontFace('CCW') -- CCW (default), CW, if bCentralize then print('centralizing mesh...') tMesh:centralize() --centralize all subsets before save end if tMesh:save(fileName,not has_normal,not has_texture) then print("Mesh created successfully ") return true else print("Failed to create Mesh!") return false end end function onInitScene() tMesh = mesh:new('3D')-- our object which will load from binary file local bCentralize = true local sFileNameMesh = 'Mech.msh' --output file (msh for mesh 3D) local sFileNameOBJ = 'Mech.obj' --input OBJ file local bResult , tFrame = OBJ_parser:parse_file(sFileNameOBJ) if bResult and saveFrameToMeshFile(sFileNameMesh,tFrame,bCentralize) then tMesh:load(sFileNameMesh) --all coordinate already in place end --set up camera camera3d = mbm.getCamera('3D') camera3d:setPos(0,0,-500) camera3d:setFocus(0,0,0) --needed to rotate our object tMouse = {x=0,y=0,clicked = false} end function onTouchDown(key,x,y) tMouse.clicked = true tMouse.x = x tMouse.y = y end function onTouchMove(key,x,y) if tMouse.clicked then local diff_X = tMouse.x - x local diff_Y = tMouse.y - y tMouse.x = x tMouse.y = y --simple rotation based on mouse tMesh.ay = tMesh.ay + math.rad(diff_X) tMesh.ax = tMesh.ax + math.rad(diff_Y) end end function onTouchUp(key,x,y) tMouse.clicked = false end function onTouchZoom(zoom) --Zoom the 3D object tMesh.sx = tMesh.sx + (0.2 * zoom) if tMesh.sx <= 0.2 then tMesh.sx = 0.2 end tMesh.sy = tMesh.sx tMesh.sz = tMesh.sx end