GameApi Builder tool and meshpage.org

Tero Pulkkinen (terop@kotiposti.net)

23.2.2025

Abstract

GameApi Builder tool and meshpage.org are technologies that allow display of 3d models in multiple platforms, including linux, win32, web, android. The tools are based on small scripting language built with single primitive: function call, and passing parameters to predefined functions. Input of the tools are gltf/glb files, .obj files or .stl files, and output of the tools are script.txt files, html5 .zip files and android apk files. Using these techniques, we build a complete 3d engine subsystem with advanced tech features including opengl instancing, 3d models, voxels, volumes, textures, gltf materials, gltf animations.

1 history

The project started in 2013, when we started using sdl2, libfreetype to build a 3d engine. We first built some simple game called gameapigame, where we develop opengl based sprite technology. Then we started doing 3d model routines, including FaceCollection type as mesh representation. How it differs from normal mesh data structure, is that it only publishes interface of a mesh, it doesn’t need to store the mesh data inside the same object, if it can fetch the data from somewhere else. Bitmaps and voxels also have similar kind of interface.

Significant development that took several years was the frame rate improvement actions. Getting frame rates working was done by splitting the operations to Prepare() and execute() operations, where prepare() would be called just once, and contains heavy operations, while execute is perframe operation executed many times and is light to execute so to get 60Hz frequence for frame updates.

Another significant development was the building of the algorithm library. We now have 600 separate algorithms that can be chosen from the builder tool and the algorithms are working together with the FaceCollection and Bitmap types to implement various algorithms needed for 3d modelling and displaying.

Significant development effort was done to implement 70 test cases for the library, we have games, demos, 3d models, and animations available which test all aspects of the library.

Yet another significant development was the creation of GLTF rendering using tinygltf library. tinygltf allowed reading the gltf/glb file formats, but it didn’t have rendering capability builtin, and that needed to be done with our engine’s primitives.

There is also optimization slot done after gltf development, and some half year was spent on optimizing the rendering pipeline after gltf was implemented. We maanged to reduce loading time of the engine from 20-30 seconds to mere 1-2 seconds.

Final development focused on artificial intelligence integration.

2 Technical Details

template<class C>
class Bitmap : public CollectInterface
{
public:
  virtual void Prepare()=0;
  virtual int SizeX() const=0;
  virtual int SizeY() const=0;
  virtual C Map(int x, int y) const=0;
};

This contains the main part of bitmap type. It publishes size of the bitmap and a mapping function which fetches each pixel from the bitmap. C type can be either unsigned char, Color, int or something else. This is the standard getpixel() style interface for bitmaps.

The FaceCollection type is slightly more complicated:

class FaceCollection : public CollectInterface
{
public:
  virtual ~FaceCollection() { }
  virtual void Prepare()=0;
  virtual int NumFaces() const = 0;
  virtual int NumPoints(int face) const=0;
  virtual Point FacePoint(int face, int point) const=0;
  virtual Vector PointNormal(int face, int point) const=0;
  virtual float Attrib(int face, int point, int id) const=0;
  virtual int AttribI(int face, int point, int id) const=0;
  virtual unsigned int Color(int face, int point) const=0;
  virtual Point2d TexCoord(int face, int point) const=0;
  virtual float TexCoord3(int face, int point) const=0;

  virtual VEC4 Joints(int face, int point) const=0;
  virtual VEC4 Weights(int face, int point) const=0;
};

this allows triangle meshes, quad meshes, polygon meshes, or any combination of them. Before rendering, the code fetches the data from the interface and push backs it to 3 separate c++ vectors, one for triangles, one for quads and one for polygons. Then 3 draw calls to opengl can render the model, one for GL TRIANGLES, one for GL QUADS and one for GL TRIANGLE STRIP.

3 script files

script files look like this:

TF I0=ev.mainloop_api.gltf_loadKK(http://meshpage.org/assets/bottledcar/,
                        http://meshpage.org/assets/bottledcar/scene.gltf);
P I333=ev.mainloop_api.gltf_mesh_all_p(ev,I0);
BM I1=ev.bitmap_api.newbitmap(100,100,ff888888);
BM I2=ev.bitmap_api.scale_bitmap_fullscreen(ev,I1);
ML I3=ev.sprite_api.vertex_array_render(ev,I2);
MN I997=ev.move_api.mn_empty();
MN I998=ev.move_api.scale2(I997,1.5,1.5,1.5);
ML I999=ev.move_api.move_ml(ev,I3,I998,1,10);
ML I4=ev.sprite_api.turn_to_2d(ev,I999,0.0,0.0,800.0,600.0);
ML I5=ev.mainloop_api.gltf_mesh_all(ev,I0,1.0,0,1,1,1,0.0,ff888888);
ML I7=ev.mainloop_api.async_gltf(I5,I0);
ML I400=ev.mainloop_api.mouse_roll_zoom2(ev,I7);
ML I6=ev.mainloop_api.turn_to_meters_default(ev,I400,I333);
ML I8=ev.mainloop_api.touch_rotate(ev,I6,true,true,0.01,0.01);
MN I9=ev.move_api.mn_empty();
MN I10=ev.move_api.scale2(I9,1,1,1);
ML I11=ev.move_api.move_ml(ev,I8,I10,1,10.0);
ML I12=ev.mainloop_api.array_ml(ev,std::vector<ML>{I4,I11});
ML I13=ev.mainloop_api.perspective(ev,I12,80.0,10.1,60000.0);
RUN I14=ev.blocker_api.game_window2(ev,I13,false,false,0.0,100000.0);

It’s like c++ code, but it’s actually a script that is parsed during execution. BM type in the script maps directly to Bitmap<Color>∗ pointer to polymorphic interface mentioned earlier.

the BM type is actually defined in c++ as:

struct BM { int id; };

where id points to an index in certain std::vector stored in EnvImpl.

4 EnvImpl

5 List of functions supported

• BitmapApi 1. new

2. new bm

3. new fb

4. new bb

5. bm png bm

6. stable diffusion 7. bm expr

8. load

9. save png

10. save png arr

11. save raw

12. save gif anim

13. bm url

14. bm fetch

15. bm fetch2

16. bm gltf

17. bm debug

18. bm atlas x

19. bm atlas y

20. bm atlas xy

21. bm cubemap

22. bm invcubemap 23. edge fix

24. border

25. add shape border 26. bm choose color 27. sub

28. alt

29. compose x

30. compose y 31. blit

32. blitFB

33. blitBB

34. bm scale

35. bm scale2

36. bm fullscreen

37. interpolate

38. bm color

39. bm plus

40. bm medianfilter

41. repeat

42. flip x

43. flip y

44. rot90

45. indicator

46. fractal mountain

47. lightmap noise vec

48. gradient

49. circ gradient

50. chessboard

51. mandelbrot

52. blur

53. floodfill

54. floodfill color

55. floodfill color inv

56. gray to black

57. baked shadow

58. bm bumpmap

59. bm memoize

60. bm world from bitmap 61. bm persistent cache 62. cbm empty

63. cbm from bitmap

64. cbm to bitmap 65. cbm bicubic 66. cbm sample 67. cbm rotate 68. s spherical 69. s bitmap

70. s sample

71. cfb c

72. cfb x

73. cfb y

74. cfb add

75. cfb mul

76. cfb sqrt

77. cfb sin

78. cfb cos

79. cfb tan

80. cfb sample 81. cfb equalizer 82. cbb sample

• BoolBitmapApi • FloatBitmapApi