1
0
Fork 0
mirror of https://github.com/bjornbytes/lovr.git synced 2024-07-07 06:43:34 +00:00
lovr/src/lovr/graphics.c

687 lines
19 KiB
C
Raw Normal View History

2016-11-19 09:28:01 +00:00
#include "lovr/graphics.h"
#include "lovr/types/buffer.h"
#include "lovr/types/model.h"
#include "lovr/types/shader.h"
#include "lovr/types/skybox.h"
#include "lovr/types/texture.h"
#include "lovr/types/transform.h"
2016-11-19 09:28:01 +00:00
#include "graphics/graphics.h"
2016-11-26 07:15:04 +00:00
#include "loaders/model.h"
2016-11-26 07:54:45 +00:00
#include "loaders/texture.h"
2016-11-19 09:28:01 +00:00
#include "filesystem/filesystem.h"
2016-10-29 22:17:49 +00:00
#include <math.h>
2016-08-10 06:28:17 +00:00
2016-11-08 07:16:33 +00:00
static void luax_readvertices(lua_State* L, int index, vec_float_t* points) {
int isTable = lua_istable(L, index);
if (!isTable && !lua_isnumber(L, index)) {
luaL_error(L, "Expected number or table, got '%s'", lua_typename(L, lua_type(L, 1)));
return;
}
2016-11-23 04:43:22 +00:00
int count = isTable ? lua_objlen(L, index) : lua_gettop(L) - index + 1;
2016-11-08 07:16:33 +00:00
if (count % 3 != 0) {
vec_deinit(points);
luaL_error(L, "Number of coordinates must be a multiple of 3, got '%d'", count);
return;
}
vec_reserve(points, count);
if (isTable) {
for (int i = 1; i <= count; i++) {
lua_rawgeti(L, index, i);
vec_push(points, lua_tonumber(L, -1));
lua_pop(L, 1);
}
} else {
for (int i = 0; i < count; i++) {
vec_push(points, lua_tonumber(L, index + i));
}
}
}
2016-08-10 06:28:17 +00:00
const luaL_Reg lovrGraphics[] = {
2016-09-28 03:20:08 +00:00
{ "reset", l_lovrGraphicsReset },
2016-08-10 06:28:17 +00:00
{ "clear", l_lovrGraphicsClear },
{ "present", l_lovrGraphicsPresent },
2016-09-28 04:37:46 +00:00
{ "getBackgroundColor", l_lovrGraphicsGetBackgroundColor },
{ "setBackgroundColor", l_lovrGraphicsSetBackgroundColor },
2016-09-29 03:11:58 +00:00
{ "getColor", l_lovrGraphicsGetColor },
{ "setColor", l_lovrGraphicsSetColor },
2016-09-28 04:32:57 +00:00
{ "getColorMask", l_lovrGraphicsGetColorMask },
{ "setColorMask", l_lovrGraphicsSetColorMask },
2016-09-29 04:47:36 +00:00
{ "getScissor", l_lovrGraphicsGetScissor },
{ "setScissor", l_lovrGraphicsSetScissor },
2016-10-01 20:44:20 +00:00
{ "getShader", l_lovrGraphicsGetShader },
2016-08-10 06:28:17 +00:00
{ "setShader", l_lovrGraphicsSetShader },
2016-09-24 05:11:56 +00:00
{ "setProjection", l_lovrGraphicsSetProjection },
2016-10-01 20:48:31 +00:00
{ "getLineWidth", l_lovrGraphicsGetLineWidth },
{ "setLineWidth", l_lovrGraphicsSetLineWidth },
2016-11-13 01:38:49 +00:00
{ "getPointSize", l_lovrGraphicsGetPointSize },
{ "setPointSize", l_lovrGraphicsSetPointSize },
2016-10-03 19:02:49 +00:00
{ "isCullingEnabled", l_lovrGraphicsIsCullingEnabled },
{ "setCullingEnabled", l_lovrGraphicsSetCullingEnabled },
{ "getPolygonWinding", l_lovrGraphicsGetPolygonWinding },
{ "setPolygonWinding", l_lovrGraphicsSetPolygonWinding },
2016-11-23 04:59:11 +00:00
{ "getDepthTest", l_lovrGraphicsGetDepthTest },
{ "setDepthTest", l_lovrGraphicsSetDepthTest },
2016-11-23 05:07:33 +00:00
{ "isWireframe", l_lovrGraphicsIsWireframe },
{ "setWireframe", l_lovrGraphicsSetWireframe },
2016-09-21 07:55:53 +00:00
{ "push", l_lovrGraphicsPush },
{ "pop", l_lovrGraphicsPop },
2016-09-21 22:26:05 +00:00
{ "origin", l_lovrGraphicsOrigin },
{ "translate", l_lovrGraphicsTranslate },
{ "rotate", l_lovrGraphicsRotate },
{ "scale", l_lovrGraphicsScale },
2017-01-20 03:13:37 +00:00
{ "transform", l_lovrGraphicsTransform },
2016-11-08 07:16:33 +00:00
{ "points", l_lovrGraphicsPoints },
2016-09-30 02:39:25 +00:00
{ "line", l_lovrGraphicsLine },
2016-11-23 04:43:22 +00:00
{ "triangle", l_lovrGraphicsTriangle },
2016-10-04 03:56:45 +00:00
{ "plane", l_lovrGraphicsPlane },
2016-09-30 06:18:51 +00:00
{ "cube", l_lovrGraphicsCube },
{ "getWidth", l_lovrGraphicsGetWidth },
{ "getHeight", l_lovrGraphicsGetHeight },
{ "getDimensions", l_lovrGraphicsGetDimensions },
2016-08-10 06:28:17 +00:00
{ "newModel", l_lovrGraphicsNewModel },
{ "newBuffer", l_lovrGraphicsNewBuffer },
{ "newShader", l_lovrGraphicsNewShader },
2016-10-16 03:11:54 +00:00
{ "newSkybox", l_lovrGraphicsNewSkybox },
2016-11-08 11:14:33 +00:00
{ "newTexture", l_lovrGraphicsNewTexture },
2016-08-10 06:28:17 +00:00
{ NULL, NULL }
};
2016-11-23 05:16:13 +00:00
// Base
2016-08-10 06:28:17 +00:00
int l_lovrGraphicsInit(lua_State* L) {
lua_newtable(L);
luaL_register(L, NULL, lovrGraphics);
2017-01-21 03:46:45 +00:00
luax_registertype(L, "Buffer", lovrBuffer);
luax_registertype(L, "Model", lovrModel);
luax_registertype(L, "Shader", lovrShader);
luax_registertype(L, "Skybox", lovrSkybox);
luax_registertype(L, "Texture", lovrTexture);
map_init(&BufferAttributeTypes);
map_set(&BufferAttributeTypes, "float", BUFFER_FLOAT);
map_set(&BufferAttributeTypes, "byte", BUFFER_BYTE);
2016-11-15 05:31:17 +00:00
map_set(&BufferAttributeTypes, "int", BUFFER_INT);
map_init(&BufferDrawModes);
map_set(&BufferDrawModes, "points", BUFFER_POINTS);
map_set(&BufferDrawModes, "strip", BUFFER_TRIANGLE_STRIP);
map_set(&BufferDrawModes, "triangles", BUFFER_TRIANGLES);
map_set(&BufferDrawModes, "fan", BUFFER_TRIANGLE_FAN);
map_init(&BufferUsages);
map_set(&BufferUsages, "static", BUFFER_STATIC);
map_set(&BufferUsages, "dynamic", BUFFER_DYNAMIC);
map_set(&BufferUsages, "stream", BUFFER_STREAM);
2016-10-01 19:10:38 +00:00
map_init(&DrawModes);
map_set(&DrawModes, "fill", DRAW_MODE_FILL);
map_set(&DrawModes, "line", DRAW_MODE_LINE);
2016-10-03 19:02:49 +00:00
map_init(&PolygonWindings);
map_set(&PolygonWindings, "clockwise", POLYGON_WINDING_CLOCKWISE);
map_set(&PolygonWindings, "counterclockwise", POLYGON_WINDING_COUNTERCLOCKWISE);
2016-11-23 04:59:11 +00:00
map_init(&CompareModes);
map_set(&CompareModes, "equal", COMPARE_EQUAL);
map_set(&CompareModes, "notequal", COMPARE_NOT_EQUAL);
map_set(&CompareModes, "less", COMPARE_LESS);
map_set(&CompareModes, "lequal", COMPARE_LEQUAL);
map_set(&CompareModes, "gequal", COMPARE_GEQUAL);
map_set(&CompareModes, "greater", COMPARE_GREATER);
2016-11-08 22:44:22 +00:00
map_init(&FilterModes);
map_set(&FilterModes, "nearest", FILTER_NEAREST);
map_set(&FilterModes, "linear", FILTER_LINEAR);
map_init(&WrapModes);
map_set(&WrapModes, "clamp", WRAP_CLAMP);
map_set(&WrapModes, "repeat", WRAP_REPEAT);
map_set(&WrapModes, "mirroredrepeat", WRAP_MIRRORED_REPEAT);
map_set(&WrapModes, "clampzero", WRAP_CLAMP_ZERO);
2017-01-12 07:38:28 +00:00
map_init(&TextureProjections);
map_set(&TextureProjections, "2d", PROJECTION_ORTHOGRAPHIC);
map_set(&TextureProjections, "3d", PROJECTION_PERSPECTIVE);
2016-08-10 06:28:17 +00:00
lovrGraphicsInit();
return 1;
}
2016-09-28 03:20:08 +00:00
int l_lovrGraphicsReset(lua_State* L) {
lovrGraphicsReset();
return 0;
}
2016-08-10 06:28:17 +00:00
int l_lovrGraphicsClear(lua_State* L) {
2016-09-17 03:11:11 +00:00
int color = lua_gettop(L) < 1 || lua_toboolean(L, 1);
int depth = lua_gettop(L) < 2 || lua_toboolean(L, 2);
lovrGraphicsClear(color, depth);
2016-08-10 06:28:17 +00:00
return 0;
}
int l_lovrGraphicsPresent(lua_State* L) {
lovrGraphicsPresent();
return 0;
}
2016-11-23 05:16:13 +00:00
// State
2016-09-28 04:37:46 +00:00
int l_lovrGraphicsGetBackgroundColor(lua_State* L) {
2016-08-10 06:28:17 +00:00
float r, g, b, a;
2016-09-28 04:37:46 +00:00
lovrGraphicsGetBackgroundColor(&r, &g, &b, &a);
2016-08-10 06:28:17 +00:00
lua_pushnumber(L, r);
lua_pushnumber(L, g);
lua_pushnumber(L, b);
lua_pushnumber(L, a);
return 4;
}
2016-09-28 04:37:46 +00:00
int l_lovrGraphicsSetBackgroundColor(lua_State* L) {
2016-08-10 06:28:17 +00:00
float r = luaL_checknumber(L, 1);
float g = luaL_checknumber(L, 2);
float b = luaL_checknumber(L, 3);
float a = 255.0;
if (lua_gettop(L) > 3) {
a = luaL_checknumber(L, 4);
}
2016-09-28 04:37:46 +00:00
lovrGraphicsSetBackgroundColor(r, g, b, a);
2016-08-10 06:28:17 +00:00
return 0;
}
2016-09-29 03:11:58 +00:00
int l_lovrGraphicsGetColor(lua_State* L) {
unsigned char r, g, b, a;
lovrGraphicsGetColor(&r, &g, &b, &a);
lua_pushinteger(L, r);
lua_pushinteger(L, g);
lua_pushinteger(L, b);
lua_pushinteger(L, a);
return 4;
}
int l_lovrGraphicsSetColor(lua_State* L) {
2016-11-30 18:53:21 +00:00
unsigned char r, g, b, a;
r = g = b = a = 0xff;
if (lua_gettop(L) == 1 && lua_isnumber(L, 1)) {
unsigned int x = lua_tointeger(L, 1);
r = LOVR_COLOR_R(x);
g = LOVR_COLOR_G(x);
b = LOVR_COLOR_B(x);
a = LOVR_COLOR_A(x);
} else if (lua_istable(L, 1)) {
for (int i = 1; i <= 4; i++) {
lua_rawgeti(L, 1, i);
}
r = luaL_checknumber(L, -4);
g = luaL_checknumber(L, -3);
b = luaL_checknumber(L, -2);
a = lua_gettop(L) > 1 ? luaL_checknumber(L, 2) : luaL_optnumber(L, -1, 255);
lua_pop(L, 4);
} else if (lua_gettop(L) >= 3) {
r = lua_tointeger(L, 1);
g = lua_tointeger(L, 2);
b = lua_tointeger(L, 3);
a = lua_isnoneornil(L, 4) ? 255 : lua_tointeger(L, 4);
2016-09-29 03:11:58 +00:00
}
lovrGraphicsSetColor(r, g, b, a);
return 0;
}
2016-09-28 04:32:57 +00:00
int l_lovrGraphicsGetColorMask(lua_State* L) {
2016-10-03 18:41:31 +00:00
char r, g, b, a;
2016-09-28 04:32:57 +00:00
lovrGraphicsGetColorMask(&r, &g, &b, &a);
lua_pushboolean(L, r);
lua_pushboolean(L, g);
lua_pushboolean(L, b);
lua_pushboolean(L, a);
return 4;
}
int l_lovrGraphicsSetColorMask(lua_State* L) {
if (lua_gettop(L) <= 1 && lua_isnoneornil(L, 1)) {
lovrGraphicsSetColorMask(1, 1, 1, 1);
return 0;
}
2016-10-03 18:41:31 +00:00
char r = lua_toboolean(L, 1);
char g = lua_toboolean(L, 2);
char b = lua_toboolean(L, 3);
char a = lua_toboolean(L, 4);
2016-09-28 04:32:57 +00:00
lovrGraphicsSetColorMask(r, g, b, a);
return 0;
}
2016-09-29 04:47:36 +00:00
int l_lovrGraphicsGetScissor(lua_State* L) {
if (!lovrGraphicsIsScissorEnabled()) {
lua_pushnil(L);
return 1;
}
int x, y, width, height;
lovrGraphicsGetScissor(&x, &y, &width, &height);
lua_pushnumber(L, x);
lua_pushnumber(L, y);
lua_pushnumber(L, width);
lua_pushnumber(L, height);
return 4;
}
int l_lovrGraphicsSetScissor(lua_State* L) {
if (lua_gettop(L) <= 1 && lua_isnoneornil(L, 1)) {
lovrGraphicsSetScissorEnabled(0);
return 0;
}
int x = luaL_checkint(L, 1);
int y = luaL_checkint(L, 2);
int width = luaL_checkint(L, 3);
int height = luaL_checkint(L, 4);
lovrGraphicsSetScissor(x, y, width, height);
lovrGraphicsSetScissorEnabled(1);
return 0;
}
2016-09-14 00:02:23 +00:00
int l_lovrGraphicsGetShader(lua_State* L) {
2016-11-19 08:57:18 +00:00
luax_pushtype(L, Shader, lovrGraphicsGetShader());
2016-09-14 00:02:23 +00:00
return 1;
}
2016-08-10 06:28:17 +00:00
int l_lovrGraphicsSetShader(lua_State* L) {
2016-11-19 08:57:18 +00:00
Shader* shader = lua_isnoneornil(L, 1) ? NULL : luax_checktype(L, 1, Shader);
2016-08-10 06:28:17 +00:00
lovrGraphicsSetShader(shader);
return 0;
}
2016-09-24 05:11:56 +00:00
int l_lovrGraphicsSetProjection(lua_State* L) {
float near = luaL_checknumber(L, 1);
float far = luaL_checknumber(L, 2);
float fov = luaL_checknumber(L, 3);
2016-09-27 06:48:09 +00:00
lovrGraphicsSetProjection(near, far, fov);
2016-09-24 05:11:56 +00:00
return 0;
}
2016-10-01 20:48:31 +00:00
int l_lovrGraphicsGetLineWidth(lua_State* L) {
lua_pushnumber(L, lovrGraphicsGetLineWidth());
return 1;
}
int l_lovrGraphicsSetLineWidth(lua_State* L) {
float width = luaL_optnumber(L, 1, 1.f);
lovrGraphicsSetLineWidth(width);
return 0;
}
2016-11-13 01:38:49 +00:00
int l_lovrGraphicsGetPointSize(lua_State* L) {
lua_pushnumber(L, lovrGraphicsGetPointSize());
return 1;
}
int l_lovrGraphicsSetPointSize(lua_State* L) {
float size = luaL_optnumber(L, 1, 1.f);
lovrGraphicsSetPointSize(size);
return 0;
}
2016-10-03 19:02:49 +00:00
int l_lovrGraphicsIsCullingEnabled(lua_State* L) {
lua_pushboolean(L, lovrGraphicsIsCullingEnabled());
return 1;
}
int l_lovrGraphicsSetCullingEnabled(lua_State* L) {
lovrGraphicsSetCullingEnabled(lua_toboolean(L, 1));
return 0;
}
int l_lovrGraphicsGetPolygonWinding(lua_State* L) {
2017-01-22 01:38:44 +00:00
luax_pushenum(L, &PolygonWindings, lovrGraphicsGetPolygonWinding());
2016-11-08 22:15:37 +00:00
return 1;
2016-10-03 19:02:49 +00:00
}
int l_lovrGraphicsSetPolygonWinding(lua_State* L) {
2016-11-23 04:45:57 +00:00
PolygonWinding* winding = (PolygonWinding*) luax_checkenum(L, 1, &PolygonWindings, "winding direction");
2016-10-03 19:02:49 +00:00
lovrGraphicsSetPolygonWinding(*winding);
return 0;
}
2016-11-23 04:59:11 +00:00
int l_lovrGraphicsGetDepthTest(lua_State* L) {
2017-01-22 01:38:44 +00:00
luax_pushenum(L, &CompareModes, lovrGraphicsGetDepthTest());
2016-11-23 04:59:11 +00:00
return 1;
}
int l_lovrGraphicsSetDepthTest(lua_State* L) {
2016-11-24 23:45:59 +00:00
if (lua_isnoneornil(L, 1)) {
lovrGraphicsSetDepthTest(COMPARE_NONE);
} else {
CompareMode* depthTest = (CompareMode*) luax_checkenum(L, 1, &CompareModes, "compare mode");
lovrGraphicsSetDepthTest(*depthTest);
}
2016-11-23 04:59:11 +00:00
return 0;
}
2016-11-23 05:07:33 +00:00
int l_lovrGraphicsIsWireframe(lua_State* L) {
lua_pushboolean(L, lovrGraphicsIsWireframe());
return 1;
}
int l_lovrGraphicsSetWireframe(lua_State* L) {
lovrGraphicsSetWireframe(lua_toboolean(L, 1));
return 0;
}
2016-11-23 05:16:13 +00:00
int l_lovrGraphicsGetWidth(lua_State* L) {
lua_pushnumber(L, lovrGraphicsGetWidth());
return 1;
}
int l_lovrGraphicsGetHeight(lua_State* L) {
lua_pushnumber(L, lovrGraphicsGetHeight());
return 1;
}
int l_lovrGraphicsGetDimensions(lua_State* L) {
lua_pushnumber(L, lovrGraphicsGetWidth());
lua_pushnumber(L, lovrGraphicsGetHeight());
return 2;
}
// Transforms
2016-09-21 07:55:53 +00:00
int l_lovrGraphicsPush(lua_State* L) {
if (lovrGraphicsPush()) {
return luaL_error(L, "Unbalanced matrix stack (more pushes than pops?)");
}
return 0;
}
int l_lovrGraphicsPop(lua_State* L) {
if (lovrGraphicsPop()) {
return luaL_error(L, "Unbalanced matrix stack (more pops than pushes?)");
}
return 0;
}
2016-09-21 22:26:05 +00:00
int l_lovrGraphicsOrigin(lua_State* L) {
lovrGraphicsOrigin();
return 0;
}
int l_lovrGraphicsTranslate(lua_State* L) {
float x = luaL_checknumber(L, 1);
float y = luaL_checknumber(L, 2);
float z = luaL_checknumber(L, 3);
lovrGraphicsTranslate(x, y, z);
return 0;
}
int l_lovrGraphicsRotate(lua_State* L) {
2016-09-29 06:59:10 +00:00
float angle = luaL_checknumber(L, 1);
float axisX = luaL_checknumber(L, 2);
float axisY = luaL_checknumber(L, 3);
float axisZ = luaL_checknumber(L, 4);
2016-12-02 01:32:39 +00:00
lovrGraphicsRotate(angle, axisX, axisY, axisZ);
return 0;
}
int l_lovrGraphicsScale(lua_State* L) {
float x = luaL_checknumber(L, 1);
float y = luaL_checknumber(L, 2);
float z = luaL_checknumber(L, 3);
lovrGraphicsScale(x, y, z);
return 0;
}
2017-01-20 03:13:37 +00:00
int l_lovrGraphicsTransform(lua_State* L) {
float transform[16];
luax_readtransform(L, 1, transform);
lovrGraphicsMatrixTransform(transform);
return 0;
}
2016-11-23 05:16:13 +00:00
// Primitives
2016-11-08 07:16:33 +00:00
int l_lovrGraphicsPoints(lua_State* L) {
2016-09-30 02:39:25 +00:00
vec_float_t points;
vec_init(&points);
2016-11-08 07:16:33 +00:00
luax_readvertices(L, 1, &points);
lovrGraphicsPoints(points.data, points.length);
vec_deinit(&points);
return 0;
}
2016-09-30 02:39:25 +00:00
2016-11-08 07:16:33 +00:00
int l_lovrGraphicsLine(lua_State* L) {
vec_float_t points;
vec_init(&points);
luax_readvertices(L, 1, &points);
lovrGraphicsLine(points.data, points.length);
2016-09-30 02:39:25 +00:00
vec_deinit(&points);
return 0;
}
2016-11-23 04:43:22 +00:00
int l_lovrGraphicsTriangle(lua_State* L) {
DrawMode* drawMode = (DrawMode*) luax_checkenum(L, 1, &DrawModes, "draw mode");
int top = lua_gettop(L);
if (top != 10) {
return luaL_error(L, "Expected 9 coordinates to make a triangle, got %d values", top - 1);
}
vec_float_t points;
vec_init(&points);
luax_readvertices(L, 2, &points);
lovrGraphicsTriangle(*drawMode, points.data);
vec_deinit(&points);
return 0;
}
2016-10-04 03:56:45 +00:00
int l_lovrGraphicsPlane(lua_State* L) {
2017-01-13 09:59:00 +00:00
Texture* texture = NULL;
DrawMode drawMode;
if (lua_isstring(L, 1)) {
drawMode = *(DrawMode*) luax_checkenum(L, 1, &DrawModes, "draw mode");
} else {
drawMode = DRAW_MODE_FILL;
texture = luax_checktype(L, 1, Texture);
if (lua_gettop(L) == 1) {
lovrGraphicsPlaneFullscreen(texture);
return 0;
}
}
2016-10-04 03:56:45 +00:00
float x = luaL_optnumber(L, 2, 0.f);
float y = luaL_optnumber(L, 3, 0.f);
float z = luaL_optnumber(L, 4, 0.f);
float s = luaL_optnumber(L, 5, 1.f);
float nx = luaL_optnumber(L, 6, 0.f);
float ny = luaL_optnumber(L, 7, 1.f);
float nz = luaL_optnumber(L, 8, 0.f);
2017-01-13 09:59:00 +00:00
lovrGraphicsPlane(drawMode, texture, x, y, z, s, nx, ny, nz);
2016-10-04 03:56:45 +00:00
return 0;
}
2016-09-30 06:18:51 +00:00
int l_lovrGraphicsCube(lua_State* L) {
2017-01-13 09:59:00 +00:00
Texture* texture = NULL;
DrawMode drawMode;
if (lua_isstring(L, 1)) {
drawMode = *(DrawMode*) luax_checkenum(L, 1, &DrawModes, "draw mode");
} else {
drawMode = DRAW_MODE_FILL;
texture = luax_checktype(L, 1, Texture);
}
float transform[16];
luax_readtransform(L, 2, transform);
lovrGraphicsCube(drawMode, texture, transform);
2016-09-30 06:18:51 +00:00
return 0;
}
2016-11-23 05:16:13 +00:00
// Types
2016-08-10 06:28:17 +00:00
int l_lovrGraphicsNewBuffer(lua_State* L) {
int size;
int dataIndex = 0;
int drawModeIndex = 2;
BufferFormat format;
vec_init(&format);
if (lua_isnumber(L, 1)) {
size = lua_tointeger(L, 1);
} else if (lua_istable(L, 1)) {
if (lua_isnumber(L, 2)) {
2016-11-13 10:42:05 +00:00
drawModeIndex++;
luax_checkbufferformat(L, 1, &format);
size = lua_tointeger(L, 2);
dataIndex = 0;
} else if (lua_istable(L, 2)) {
2016-11-13 10:42:05 +00:00
drawModeIndex++;
luax_checkbufferformat(L, 1, &format);
size = lua_objlen(L, 2);
dataIndex = 2;
} else {
size = lua_objlen(L, 1);
dataIndex = 1;
}
} else {
luaL_argerror(L, 1, "table or number expected");
2016-11-08 22:15:37 +00:00
return 0;
}
2016-11-08 22:15:37 +00:00
BufferDrawMode* drawMode = (BufferDrawMode*) luax_optenum(L, drawModeIndex, "fan", &BufferDrawModes, "buffer draw mode");
BufferUsage* usage = (BufferUsage*) luax_optenum(L, drawModeIndex + 1, "dynamic", &BufferUsages, "buffer usage");
Buffer* buffer = lovrBufferCreate(size, format.length ? &format : NULL, *drawMode, *usage);
if (dataIndex) {
BufferFormat format = lovrBufferGetVertexFormat(buffer);
2016-11-21 01:33:19 +00:00
for (size_t i = 0; i < lua_objlen(L, dataIndex); i++) {
lua_rawgeti(L, dataIndex, i + 1);
if (!lua_istable(L, -1)) {
return luaL_error(L, "Vertex information should be specified as a table");
}
2016-11-21 01:33:19 +00:00
int component = 0;
char* vertex = lovrBufferGetScratchVertex(buffer);
for (int j = 0; j < format.length; j++) {
BufferAttribute attribute = format.data[j];
2016-11-20 23:53:36 +00:00
for (int k = 0; k < attribute.count; k++) {
2016-11-21 01:33:19 +00:00
lua_rawgeti(L, -1, ++component);
switch (attribute.type) {
case BUFFER_FLOAT: *((float*) vertex) = luaL_optnumber(L, -1, 0.f); break;
case BUFFER_BYTE: *((unsigned char*) vertex) = luaL_optint(L, -1, 255); break;
case BUFFER_INT: *((int*) vertex) = luaL_optint(L, -1, 0); break;
}
2016-11-21 01:33:19 +00:00
vertex += sizeof(attribute.type);
lua_pop(L, 1);
}
}
2016-11-21 01:33:19 +00:00
lovrBufferSetVertex(buffer, i, lovrBufferGetScratchVertex(buffer));
lua_pop(L, 1);
}
}
vec_deinit(&format);
2016-11-19 08:37:43 +00:00
luax_pushtype(L, Buffer, buffer);
2016-08-10 06:28:17 +00:00
return 1;
}
int l_lovrGraphicsNewModel(lua_State* L) {
const char* path = lua_tostring(L, 1);
int size;
void* data = lovrFilesystemRead(path, &size);
if (!data) {
return luaL_error(L, "Could not load model file '%s'", path);
}
ModelData* modelData = lovrModelDataFromFile(data, size);
2016-11-25 08:49:19 +00:00
luax_pushtype(L, Model, lovrModelCreate(modelData));
free(data);
2016-08-10 06:28:17 +00:00
return 1;
}
int l_lovrGraphicsNewShader(lua_State* L) {
for (int i = 0; i < 2; i++) {
if (lua_isnoneornil(L, i + 1)) continue;
const char* source = luaL_checkstring(L, i + 1);
if (!lovrFilesystemIsFile(source)) continue;
int bytesRead;
char* contents = lovrFilesystemRead(source, &bytesRead);
if (bytesRead <= 0) {
return luaL_error(L, "Could not read shader from file '%s'", source);
}
lua_pushlstring(L, contents, bytesRead);
lua_replace(L, i + 1);
free(contents);
}
const char* vertexSource = lua_tostring(L, 1);
const char* fragmentSource = lua_tostring(L, 2);
2016-11-19 08:57:18 +00:00
luax_pushtype(L, Shader, lovrShaderCreate(vertexSource, fragmentSource));
2016-08-10 06:28:17 +00:00
return 1;
}
2016-10-16 03:11:54 +00:00
int l_lovrGraphicsNewSkybox(lua_State* L) {
2016-11-05 22:57:10 +00:00
void* data[6];
int size[6];
2016-10-16 03:11:54 +00:00
2016-10-24 22:02:23 +00:00
if (lua_istable(L, 1)) {
if (lua_objlen(L, 1) != 6) {
return luaL_argerror(L, 1, "Expected 6 strings or a table containing 6 strings");
}
for (int i = 0; i < 6; i++) {
lua_rawgeti(L, 1, i + 1);
if (!lua_isstring(L, -1)) {
return luaL_argerror(L, 1, "Expected 6 strings or a table containing 6 strings");
}
2016-11-05 22:57:10 +00:00
const char* filename = lua_tostring(L, -1);
data[i] = lovrFilesystemRead(filename, size + i);
2016-10-24 22:02:23 +00:00
lua_pop(L, 1);
}
} else {
for (int i = 0; i < 6; i++) {
2016-11-05 22:57:10 +00:00
const char* filename = luaL_checkstring(L, i + 1);
data[i] = lovrFilesystemRead(filename, size + i);
2016-10-24 22:02:23 +00:00
}
2016-10-16 03:11:54 +00:00
}
2016-11-19 08:57:18 +00:00
luax_pushtype(L, Skybox, lovrSkyboxCreate(data, size));
2016-11-05 22:57:10 +00:00
for (int i = 0; i < 6; i++) {
free(data[i]);
}
2016-10-16 03:11:54 +00:00
return 1;
}
2016-11-08 11:14:33 +00:00
int l_lovrGraphicsNewTexture(lua_State* L) {
2016-11-14 01:28:22 +00:00
Texture* texture;
2017-01-09 06:51:43 +00:00
if (lua_type(L, 1) == LUA_TSTRING) {
const char* path = luaL_checkstring(L, 1);
int size;
void* data = lovrFilesystemRead(path, &size);
if (!data) {
return luaL_error(L, "Could not load texture file '%s'", path);
}
TextureData* textureData = lovrTextureDataFromFile(data, size);
2017-01-12 07:38:28 +00:00
texture = lovrTextureCreate(textureData);
2017-01-09 06:51:43 +00:00
free(data);
} else {
int width = luaL_checknumber(L, 1);
int height = luaL_checknumber(L, 2);
2017-01-12 07:38:28 +00:00
TextureProjection* projection = luax_optenum(L, 3, "2d", &TextureProjections, "projection");
2017-01-15 01:38:25 +00:00
int msaa = luaL_optnumber(L, 4, 0);
2017-01-09 06:51:43 +00:00
TextureData* textureData = lovrTextureDataGetEmpty(width, height);
2017-01-15 01:38:25 +00:00
texture = lovrTextureCreateWithFramebuffer(textureData, *projection, msaa);
2016-11-08 11:14:33 +00:00
}
2016-11-19 08:57:18 +00:00
luax_pushtype(L, Texture, texture);
2016-11-08 11:14:33 +00:00
return 1;
}