procedural.md 4.6 KB

Procedural Model 3D Files

[[TOC]]

Binding with Script Interpreters

Textures and meshes can be generated by scripts, but Model 3D does not specify which scripting language to use. You have to tell by providing an interpreter function by using the M3D_TX_INTERP and M3D_PR_INTERP defines before you include the m3d.h implementation.

To support multiple languages, you have to pass an interpreter function that detects the script's type (either from the extension in the name, or by looking at the script itself, which can be bytecode with magic bytes) and passes it to the right interpreter functions accordingly. Most engines are happy with supporting one scripting engine, and M3D does not want to tell you which one that should be.

Procedural Texture Generation

int (*m3dtxsc_t)(const char *name, const void *script, uint32_t len, m3dtx_t *output);
#define M3D_TX_INTERP mytextureinterp

This function receives a script by the name name and should fill in width, height, format and data in output texture and return error code. Without a texture script interpreter configured, model importer will return M3D_ERR_UNKIMG error code.

These scripts are referenced in the model files in material properties as if they were a normal static texture images.

Procedural Surface Generation

int (*m3dprsc_t)(const char *name, void *script, uint32_t len, m3d_t *model);
#define M3D_PR_INTERP mysurfaceinterp

This function receives a script by the name name and should adjust model->numface, allocate and fill in array elements in model->face. If needed, it can adjust model->numvertex and add elements to the model->vertex array too. Returns error code. Without a surface script interpreter configured, model importer will return M3D_ERR_UNIMPL error code.

These scripts are referenced from "Procedural" chunks, which replace the "Mesh" chunks.

Lua Binding for Model 3D

As a Proof of Concept, the SDK contains m3d_lua.h, which provides Lua language bindings in Model 3D files.

To use it, you have to include the header in the source file which has the m3d implementation:

#include <m3d_lua.h>        /* enable Lua scripts in models */
#define M3D_IMPLEMENTATION
#include <m3d.h>

That's all, now you can load Model 3D files with scripts inside using exactly the same m3d_load API. No need to modify your engine! You'll need to dynamically link with the lua library though.

Texture Generator Lua Scripts

These are pretty simple, can be referenced from materials in "map_" properties. They should return a table with integer values. The first item in the table is the texture's width (used as output->w), the second is the height (output->h), the third is the number of components (output->f, 1 = grayscale, 2 = grayscale with alpha, 3 = rgb, 4 = rgba) and the rest is the pixel data (output->d), width times height items.

Surface Generator Lua Scripts

These are referenced from "Procedural" chunks. They receive a library, which can be used to add triangles to the existing surface. The library's functions are very similar to Wavefront OBJ's statements, but their arguments are calculated and they're called in run-time.

Lua Function OBJ equivalent Description
vertexIndex = m3d.getVertex(color, x, y, z, w) v or vn returns the vertex index for the given coordinates
uvIndex = m3d.getUV(u, v) vt returns the UV index for the given coordinates
m3d.useMaterial(material name) usemtl sets the material given by material name string
m3d.addTriangle(v1, v2, v3) f v v v adds a simple triangle using 3 vertex indices
m3d.addTriangleUV(v1, uv1, v2, uv2, v3, uv3) f v/t v/t v/t adds triangle with UV coordinates
m3d.addTriangleN(v1, n1, v2, n2, v3, n3) f v//n v//n v//n adds triangle with normals
m3d.addTriangleUVN(v1, uv1, n1, v2, uv2, n2, v3, uv3, n3) f v/t/n v/t/n v/t/n adds triangle with UV coordinates and normals