void ilG_tex_bind(ilG_tex *self) { if (!self->complete) { il_error("Incomplete texture"); return; } glActiveTexture(GL_TEXTURE0 + self->unit); glBindTexture(self->target, self->object); }
static GLenum getImgType(const ilA_img *img) { switch (img->format) { case ILA_IMG_U8: return GL_UNSIGNED_BYTE; case ILA_IMG_U16: return GL_UNSIGNED_SHORT; case ILA_IMG_F32: return GL_FLOAT; } il_error("Unhandled image format"); return 0; }
static GLenum getImgFormat(const ilA_img *img) { switch (img->channels) { case ILA_IMG_RGBA: return GL_RGBA; case ILA_IMG_RGB: return GL_RGB; case ILA_IMG_RG: return GL_RG; case ILA_IMG_R: return GL_RED; default: il_error("Unhandled colour format"); return 0; } }
il_base *ilA_lookup(const ilA_dir *iface, il_base *dir, const ilA_path *path) { if (!iface) { iface = il_cast(il_typeof(dir), "il.asset.dir"); } if (!iface) { il_error("Parameter is not a directory"); return NULL; } return iface->lookup(dir, path); }
void ilA_delete(const ilA_dir *iface, il_base *dir, const ilA_path *path) { if (!iface) { iface = il_cast(il_typeof(dir), "il.asset.dir"); } if (!iface) { il_error("Parameter is not a directory"); return; } iface->del(dir, path); }
il_base *ilA_create(const ilA_dir *iface, il_base *dir, const ilA_path *path, const ilA_file **res) { if (!iface) { iface = il_cast(il_typeof(dir), "il.asset.dir"); } if (!iface) { il_error("Parameter is not a directory"); return NULL; } return iface->create(dir, path, res); }
static GLenum getImgType(const ilA_img *img) { if (img->fp) { return GL_FLOAT; } switch (img->depth) { case 8: return GL_UNSIGNED_BYTE; case 16: return GL_UNSIGNED_SHORT; case 32: return GL_UNSIGNED_INT; default: il_error("Unhandled bit depth"); return 0; } }
void *ilA_contents(const ilA_file *iface, il_base *file, size_t *size) { il_return_null_on_fail(file); if (!iface) { iface = il_cast(il_typeof(file), "il.asset.file"); } if (!iface) { il_error("Parameter is not a file"); return NULL; } return iface->contents(file, size); }
static void context_message(void *ptr, int type, il_value *v) { switch (type) { case 1: context_add_renderer(ptr, *(ilG_renderer*)il_value_tomvoid(v)); break; case 2: context_del_renderer(ptr, *(ilG_renderer*)il_value_tomvoid(v)); break; default: il_error("No such message %i for %s<%p>", type, ilG_context_renderer.name, ptr); } }
static void heightmap_del_positionable(ilG_heightmap *self, il_positionable pos) { for (unsigned i = 0; i < self->positionables.length-1; i++) { if (pos_eq(self->positionables.data[i], pos)) { self->positionables.data[i] = self->positionables.data[--self->positionables.length]; return; } } if (self->positionables.length > 0 && pos_eq(self->positionables.data[self->positionables.length-1], pos)) { --self->positionables.length; return; } il_error("Heightmap %p does not own positionable %i[%p]", self, pos.id, pos.world); }
static void context_del_renderer(void *ptr, ilG_renderer node) { ilG_context *self = ptr; for (unsigned i = 0; i < self->renderers.length-1; i++) { if (self->renderers.data[i].obj == node.obj) { self->renderers.data[i] = self->renderers.data[--self->renderers.length]; return; } } if (self->renderers.length > 0 && self->renderers.data[self->renderers.length-1].obj == node.obj) { --self->renderers.length; return; } il_error("Renderer %s<%p> does not own %s<%p>", ilG_context_renderer.name, ptr, node.vtable->name, node.obj); }
il_base *ilA_contents_path (const ilA_path *path, size_t *size, void **data, const ilA_file **res) { const ilA_file *iface; il_base *base = ilA_stdiofile(path, ILA_FILE_READ, &iface); if (!base) { char *tostr = ilA_path_tochars(path); il_error("Unable to open file %s", tostr); free(tostr); return NULL; } if (res) { *res = iface; } *data = ilA_contents(iface, base, size); return base; }
ilG_gui_textlayout *ilG_gui_textlayout_new(ilG_context *ctx, const char *lang, enum ilG_gui_textdir direction, const char *script, il_base *font, const ilA_file *tc, double pt, il_string *source) { il_return_null_on_fail(ctx && lang && script && font && source); struct text_globalctx *gctx = il_base_get(&ctx->base, "il.graphics.gui.text.ctx", NULL, NULL); if (!gctx) { gctx = calloc(1, sizeof(struct text_globalctx)); il_return_null_on_fail(!FT_Init_FreeType(&gctx->library)); il_base_set(&ctx->base, "il.graphics.gui.text.ctx", gctx, sizeof(struct text_globalctx), IL_VOID); } ilG_gui_textlayout *l = il_new(&ilG_gui_textlayout_type); l->context = ctx; l->lang = strdup(lang); l->script = strdup(script); l->font = il_ref(font); l->direction = direction; l->pt = pt; l->source = il_string_ref(source); size_t size; void *data = ilA_contents(tc, font, &size); if (!data) { il_error("Could not open font"); return NULL; } il_return_null_on_fail(!FT_New_Memory_Face(gctx->library, data, size, 0, &l->ft_face)); il_return_null_on_fail(!FT_Set_Char_Size(l->ft_face, 0, pt * 64, 0, 0)); l->hb_ft_font = hb_ft_font_create(l->ft_face, NULL); l->buf = hb_buffer_create(); hb_buffer_set_unicode_funcs(l->buf, hb_icu_get_unicode_funcs()); if (direction == ILG_GUI_DEFAULTDIR) { // TODO: find out how to determine this based on script direction = ILG_GUI_LTR; } hb_buffer_set_direction(l->buf, direction + 3); // Hacky solution hb_buffer_set_script(l->buf, hb_script_from_string(script, -1)); hb_buffer_set_language(l->buf, hb_language_from_string(lang, -1)); hb_buffer_add_utf8(l->buf, source->data, source->length, 0, source->length); hb_shape(l->hb_ft_font, l->buf, NULL, 0); l->glyph_info = hb_buffer_get_glyph_infos(l->buf, &l->glyph_count); l->glyph_pos = hb_buffer_get_glyph_positions(l->buf, &l->glyph_count); return l; }
static void tex_data_build(ilG_tex *self, struct ilG_context *context) { (void)context; struct data_ctx *ctx = self->data; glGenTextures(1, &self->object); glBindTexture(self->target, self->object); switch (self->target) { case GL_TEXTURE_1D: case GL_PROXY_TEXTURE_1D: glTexImage1D(self->target, 0, ctx->internal, ctx->width, 0, ctx->format, ctx->type, ctx->data); break; case GL_TEXTURE_2D: case GL_PROXY_TEXTURE_2D: case GL_TEXTURE_1D_ARRAY: case GL_PROXY_TEXTURE_1D_ARRAY: case GL_TEXTURE_RECTANGLE: case GL_PROXY_TEXTURE_RECTANGLE: case GL_TEXTURE_CUBE_MAP_POSITIVE_X: case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: case GL_PROXY_TEXTURE_CUBE_MAP: glTexImage2D(self->target, 0, ctx->internal, ctx->width, ctx->height, 0, ctx->format, ctx->type, ctx->data); break; case GL_TEXTURE_3D: case GL_PROXY_TEXTURE_3D: case GL_TEXTURE_2D_ARRAY: case GL_PROXY_TEXTURE_2D_ARRAY: glTexImage3D(self->target, 0, ctx->internal, ctx->width, ctx->height, ctx->depth, 0, ctx->format, ctx->type, ctx->data); break; default: il_error("Unknown texture format"); return; } free(ctx->data); free(ctx); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); }
void ilG_tex_loaddata(ilG_tex *tex, GLenum target, GLenum internalformat, unsigned width, unsigned height, unsigned depth, GLenum format, GLenum type, void *data) { tex->target = target; glGenTextures(1, &tex->object); glBindTexture(target, tex->object); switch (target) { case GL_TEXTURE_1D: case GL_PROXY_TEXTURE_1D: glTexImage1D(target, 0, internalformat, width, 0, format, type, data); break; case GL_TEXTURE_2D: case GL_PROXY_TEXTURE_2D: case GL_TEXTURE_1D_ARRAY: case GL_PROXY_TEXTURE_1D_ARRAY: case GL_TEXTURE_RECTANGLE: case GL_PROXY_TEXTURE_RECTANGLE: case GL_TEXTURE_CUBE_MAP_POSITIVE_X: case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: case GL_PROXY_TEXTURE_CUBE_MAP: glTexImage2D(target, 0, internalformat, width, height, 0, format, type, data); break; case GL_TEXTURE_3D: case GL_PROXY_TEXTURE_3D: case GL_TEXTURE_2D_ARRAY: case GL_PROXY_TEXTURE_2D_ARRAY: glTexImage3D(target, 0, internalformat, width, height, depth, 0, format, type, data); break; default: il_error("Unknown texture format"); return; } glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); }
int main(int argc, char **argv) { demoLoad(argc, argv); Window window = createWindow("Teapots"); Graphics graphics(window); Graphics::Flags flags; if (!graphics.init(flags)) { return 1; } il_pos pos = il_pos_new(&graphics.space); il_pos_setPosition(&pos, il_vec3_new(0, -4, 0)); Teapot teapot; Teapots drawable(pos.id, teapot); graphics.drawables.push_back(&drawable); char *error; if (!teapot.build(graphics.rm, &error)) { il_error("Teapot: %s", error); free(error); return 1; } il_pos_setPosition(&graphics.space.camera, il_vec3_new(0, 0, 20)); il_pos lightp = il_pos_new(&graphics.space); il_pos_setPosition(&lightp, il_vec3_new(20, 3, 20)); ilG_light lightl; lightl.color = il_vec3_new(.8f*2, .7f*2, .2f*2); lightl.radius = 50; State state; unsigned lightp_id = lightp.id; state.sunlight_locs = &lightp_id; state.sunlight_lights = &lightl; state.sunlight_count = 1; typedef std::chrono::steady_clock clock; typedef std::chrono::duration<double> duration; clock::time_point start = clock::now(); while (1) { SDL_Event ev; while (SDL_PollEvent(&ev)) { switch (ev.type) { case SDL_QUIT: il_log("Stopping"); window.close(); return 0; } } duration delta = clock::now() - start; const double secs = 5.0; const int scale = 20; il_vec3 v; v.x = float(sin(delta.count() * M_PI * 2.0 / secs) * scale); v.y = 0.f; v.z = float(cos(delta.count() * M_PI * 2.0 / secs) * scale); il_quat q = il_quat_fromAxisAngle(0, 1, 0, float(delta.count() * M_PI * 2.0 / secs)); il_pos_setPosition(&graphics.space.camera, v); il_pos_setRotation(&graphics.space.camera, q); graphics.draw(state); } }