From c4b85342d6f8b5e3a205492a59821ba673def98f Mon Sep 17 00:00:00 2001 From: Michel Pollet Date: Sun, 20 May 2012 21:25:16 +0100 Subject: [PATCH] reprap: c3 update Added tons of stuff to the micro-scene-graph 3D code. Signed-off-by: Michel Pollet --- examples/board_reprap/src/c3/README.md | 42 +++-- examples/board_reprap/src/c3/c3.h | 2 + examples/board_reprap/src/c3/c3cairo.c | 67 +++++++- examples/board_reprap/src/c3/c3cairo.h | 17 +- examples/board_reprap/src/c3/c3context.c | 72 ++++++++ examples/board_reprap/src/c3/c3context.h | 57 +++++++ examples/board_reprap/src/c3/c3driver.h | 44 +++++ .../board_reprap/src/c3/c3driver_context.h | 43 +++++ .../board_reprap/src/c3/c3driver_geometry.h | 40 +++++ .../{c3object_driver.h => c3driver_object.h} | 48 +++--- examples/board_reprap/src/c3/c3geometry.c | 85 ++++++++-- examples/board_reprap/src/c3/c3geometry.h | 45 ++++- examples/board_reprap/src/c3/c3object.c | 67 ++++---- examples/board_reprap/src/c3/c3object.h | 7 +- examples/board_reprap/src/c3/c3pixels.c | 100 +++++++++++ examples/board_reprap/src/c3/c3pixels.h | 94 ++++++++++ examples/board_reprap/src/c3/c3texture.c | 101 +++++++++++ examples/board_reprap/src/c3/c3texture.h | 44 +++++ examples/board_reprap/src/reprap_gl.c | 160 +++++++++++++++--- 19 files changed, 1011 insertions(+), 124 deletions(-) create mode 100644 examples/board_reprap/src/c3/c3context.c create mode 100644 examples/board_reprap/src/c3/c3context.h create mode 100644 examples/board_reprap/src/c3/c3driver.h create mode 100644 examples/board_reprap/src/c3/c3driver_context.h create mode 100644 examples/board_reprap/src/c3/c3driver_geometry.h rename examples/board_reprap/src/c3/{c3object_driver.h => c3driver_object.h} (57%) create mode 100644 examples/board_reprap/src/c3/c3pixels.c create mode 100644 examples/board_reprap/src/c3/c3pixels.h create mode 100644 examples/board_reprap/src/c3/c3texture.c create mode 100644 examples/board_reprap/src/c3/c3texture.h diff --git a/examples/board_reprap/src/c3/README.md b/examples/board_reprap/src/c3/README.md index b1e7090..31207ab 100644 --- a/examples/board_reprap/src/c3/README.md +++ b/examples/board_reprap/src/c3/README.md @@ -19,7 +19,10 @@ and *matrices* (c3mat3, c3mat4) with various tools to manipulate them. * c3quaternion: Quaternion implementation using c3algebra * c3camera/c3arcball: camera manipulation, not perfect -The data structure is as follow: +The basic data structure is as follow: +* *c3context*: + Mostly placeholder for now, hosts a "root" object, can reproject the + objects & geometry, and call the callbacks to draw them. * *c3object*: * Has a list of (sub) c3objects * Has a list of c3transforms (ie matrices) @@ -28,7 +31,8 @@ The data structure is as follow: necessary have geometry and/or sub objects, and don't even need transforms if their vertices are already projected. * *c3geometry*: - * Has a 'type' (lines, quads, triangles..) + * Has a 'type' (raw for simple vertices, texture, triangles etc) + * Has a 'subtype' (mostly can be used to draw GL types) * Has a 'material' (ie color, texture... to be completed) * Has a list of vertices * Has a list of texture coordinates (optional) @@ -37,19 +41,37 @@ The data structure is as follow: * *c3transform*: Is just a sugar coated matrix, with an optional name. +Also there are: +* *c3pixels*: + Is just a wrapper/holder for some pixels, either allocated, or inherited, + it's mostly used for *c3texture* +* *c3texture*: + Associates a *c3geometry* with a *c3pixels* and has a standard Quad + for vertices. The OpenGL drawing is not done there, it's done by the application using + the generic *c3context* driver. +* *c3cairo*: + Placeholder for now, inherits from *c3texture* and will contain a + cairo surface mapped to a GL texture. +* *c3pango*: + A text label, inherits from *c3cairo* + +Draw Drivers "Inheritance" +------------ +Various object uses static tables of callbacks to implement their behaviours +it's kinda cheap c++ inheritance, without the usual bloat. + +There just a couple macros to call the driver chain for a particular function call. +The relevant bits are in c3driver*.h. + +Mostly the code looks for a matching callback in a static table, and call it if found. +If that callback wants, it can also call the inherited object callback too. + Dirtyness --------- -There is a notion of 'dirtyness' in the tree, when you touch c3transform, and/remove +There is a notion of 'dirtyness' in the tree, when you touch a *c3transform*, and/remove objects and geometry, a dirty bit is propagated up the tree of object. This tells the rendering it needs to reproject the dirty bits and repopulate the projected vertice cache. The 'dirty' bit moves both ways, when setting a dirty bit to true, it propagates upward, when you set it to false, it propagates downward in the tree. - -"Inheritance" -------------- -There is a vague notion of inheritance for objects, where you can create more complex -ones and install a 'driver' (ie a function pointer table) that will be called to -perform various things. The skim is still evolving. - diff --git a/examples/board_reprap/src/c3/c3.h b/examples/board_reprap/src/c3/c3.h index 5766c58..410fa3e 100644 --- a/examples/board_reprap/src/c3/c3.h +++ b/examples/board_reprap/src/c3/c3.h @@ -23,8 +23,10 @@ #ifndef __C3_H___ #define __C3_H___ +#include "c3/c3context.h" #include "c3/c3object.h" #include "c3/c3geometry.h" #include "c3/c3transform.h" +#include "c3/c3texture.h" #endif /* __C3_H___ */ diff --git a/examples/board_reprap/src/c3/c3cairo.c b/examples/board_reprap/src/c3/c3cairo.c index 6472b62..88fa4d9 100644 --- a/examples/board_reprap/src/c3/c3cairo.c +++ b/examples/board_reprap/src/c3/c3cairo.c @@ -21,21 +21,80 @@ #include "c3/c3cairo.h" +#include "c3/c3driver_geometry.h" + +void +_c3cairo_dispose( + c3geometry_p g, + const c3driver_geometry_t * d) +{ + c3cairo_p c = (c3cairo_p)g; + + if (c->cr) + cairo_destroy(c->cr); + if (c->surface) + cairo_surface_destroy(c->surface); + C3_DRIVER_INHERITED(g, d, dispose); +} + +static void +_c3cairo_prepare( + c3geometry_p g, + const struct c3driver_geometry_t *d) +{ + C3_DRIVER_INHERITED(g, d, prepare); +} + +const c3driver_geometry_t c3cairo_base_driver = { + .dispose = _c3cairo_dispose, + .prepare = _c3cairo_prepare, +}; +const c3driver_geometry_t c3texture_driver; +const c3driver_geometry_t c3geometry_driver; c3cairo_p c3cairo_new( - c3object_p parent) + struct c3object_t * parent) { c3cairo_p res = malloc(sizeof(*res)); - memset(res, 0, sizeof(*res)); return c3cairo_init(res, parent); } c3cairo_p c3cairo_init( c3cairo_p o, - c3object_p parent) + struct c3object_t * parent) { - c3object_init(&o->object, parent); + memset(o, 0, sizeof(*o)); + c3texture_init(&o->tex, parent); + + static const c3driver_geometry_t * list[] = { + &c3cairo_base_driver, &c3texture_driver, &c3geometry_driver, NULL, + }; + ((c3geometry_p)o)->driver = list; + return o; } + +c3cairo_p +c3cairo_new_offscreen( + struct c3object_t * parent, + int w, int h) +{ + c3cairo_p o = c3cairo_new(parent); + + o->surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, w, h); + o->cr = cairo_create(o->surface); + + c3pixels_init(&o->tex.pixels, w, h, 4, + cairo_image_surface_get_stride(o->surface), + cairo_image_surface_get_data(o->surface)); + + return o; +} + +#if 0 +cairo_surface_destroy(_surface); +else +cairo_surface_finish(_surface); +#endif diff --git a/examples/board_reprap/src/c3/c3cairo.h b/examples/board_reprap/src/c3/c3cairo.h index cecae0e..75082b3 100644 --- a/examples/board_reprap/src/c3/c3cairo.h +++ b/examples/board_reprap/src/c3/c3cairo.h @@ -23,19 +23,28 @@ #ifndef __C3CAIRO_H___ #define __C3CAIRO_H___ -#include "c3/c3object.h" +#include "c3/c3texture.h" +#include "c3/c3pixels.h" +#include typedef struct c3cairo_t { - c3object_t object; + c3texture_t tex; + cairo_t * cr; + cairo_surface_t * surface; } c3cairo_t, *c3cairo_p; c3cairo_p c3cairo_new( - c3object_p parent); + struct c3object_t * parent /* = NULL */); c3cairo_p c3cairo_init( c3cairo_p o, - c3object_p parent); + struct c3object_t * parent /* = NULL */); + +c3cairo_p +c3cairo_new_offscreen( + struct c3object_t * parent /* = NULL */, + int w, int h); #endif /* __C3CAIRO_H___ */ diff --git a/examples/board_reprap/src/c3/c3context.c b/examples/board_reprap/src/c3/c3context.c new file mode 100644 index 0000000..6c28758 --- /dev/null +++ b/examples/board_reprap/src/c3/c3context.c @@ -0,0 +1,72 @@ +/* + c3context.c + + Copyright 2008-2012 Michel Pollet + + This file is part of simavr. + + simavr is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + simavr is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with simavr. If not, see . + */ + + +#include "c3/c3context.h" +#include "c3/c3object.h" +#include "c3/c3driver_context.h" + +c3context_p +c3context_new( + int w, + int h) +{ + c3context_p res = malloc(sizeof(*res)); + return c3context_init(res, w, h); +} + +c3context_p +c3context_init( + c3context_p c, + int w, + int h) +{ + memset(c, 0, sizeof(*c)); + c->size.x = w; + c->size.y = h; + c->root = c3object_new(NULL); + c->root->context = c; + return c; +} + +void +c3context_prepare( + c3context_p c) +{ + if (!c->root || !c->root->dirty) + return; + + c3mat4 m = identity3D(); + c3object_project(c->root, &m); + c3geometry_array_clear(&c->projected); + c3object_get_geometry(c->root, &c->projected); +} + +void +c3context_draw( + c3context_p c) +{ + c3context_prepare(c); + for (int gi = 0; gi < c->projected.count; gi++) { + c3geometry_p g = c->projected.e[gi]; + C3_DRIVER(c, geometry_draw, g); + } +} diff --git a/examples/board_reprap/src/c3/c3context.h b/examples/board_reprap/src/c3/c3context.h new file mode 100644 index 0000000..8d42887 --- /dev/null +++ b/examples/board_reprap/src/c3/c3context.h @@ -0,0 +1,57 @@ +/* + c3context.h + + Copyright 2008-2012 Michel Pollet + + This file is part of simavr. + + simavr is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + simavr is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with simavr. If not, see . + */ + + +#ifndef __C3CONTEXT_H___ +#define __C3CONTEXT_H___ + +#include "c3/c3algebra.h" +#include "c3/c3geometry.h" + + +typedef struct c3context_t { + c3vec2 size; + struct c3object_t * root; + c3geometry_array_t projected; + + const struct c3driver_context_t ** driver; +} c3context_t, *c3context_p; + +c3context_p +c3context_new( + int w, + int h); + +c3context_p +c3context_init( + c3context_p c, + int w, + int h); + +// Reproject geometry for dirty objects +void +c3context_prepare( + c3context_p c); +void +c3context_draw( + c3context_p c); + +#endif /* __C3CONTEXT_H___ */ diff --git a/examples/board_reprap/src/c3/c3driver.h b/examples/board_reprap/src/c3/c3driver.h new file mode 100644 index 0000000..901c32d --- /dev/null +++ b/examples/board_reprap/src/c3/c3driver.h @@ -0,0 +1,44 @@ +/* + c3driver.h + + Copyright 2008-2012 Michel Pollet + + This file is part of simavr. + + simavr is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + simavr is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with simavr. If not, see . + */ + + +#ifndef __C3DRIVER_H___ +#define __C3DRIVER_H___ + +#define C3_DRIVER_CALL(__o, __callback, __args...) { \ + if ((__o) && (__o)->driver) \ + for (int _di = 0; (__o)->driver[_di]; _di++) \ + if ((__o)->driver[_di]->__callback) { \ + (__o)->driver[_di]->__callback(__o, (__o)->driver[_di], ##__args); \ + break; \ + } \ + } +#define C3_DRIVER(__o, __callback, __args...) \ + C3_DRIVER_CALL(__o, __callback, ##__args) +#define C3_DRIVER_INHERITED(__o, __driver, __callback, __args...) { \ + if ((__o) && (__o)->driver) \ + for (int _di = 0; (__o)->driver[_di]; _di++) \ + if ((__o)->driver[_di] == __driver && (__o)->driver[_di+1]) { \ + (__o)->driver[_di+1]->__callback(__o, (__o)->driver[_di+1], ##__args); \ + break; \ + } \ + } +#endif /* __C3DRIVER_H___ */ diff --git a/examples/board_reprap/src/c3/c3driver_context.h b/examples/board_reprap/src/c3/c3driver_context.h new file mode 100644 index 0000000..1a744a7 --- /dev/null +++ b/examples/board_reprap/src/c3/c3driver_context.h @@ -0,0 +1,43 @@ +/* + c3driver_context.h + + Copyright 2008-2012 Michel Pollet + + This file is part of simavr. + + simavr is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + simavr is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with simavr. If not, see . + */ + + +#ifndef __C3DRIVER_CONTEXT_H___ +#define __C3DRIVER_CONTEXT_H___ + +#include "c3/c3driver.h" + +struct c3context_t; +struct c3driver_context_t; +struct c3geometry_t; + +typedef struct c3driver_context_t { + void (*geometry_prepare)( + struct c3context_t * c, + const struct c3driver_context_t *d, + struct c3geometry_t * g); + void (*geometry_draw)( + struct c3context_t * c, + const struct c3driver_context_t *d, + struct c3geometry_t * g); +} c3driver_context_t, *c3driver_context_p; + +#endif /* __C3DRIVER_CONTEXT_H___ */ diff --git a/examples/board_reprap/src/c3/c3driver_geometry.h b/examples/board_reprap/src/c3/c3driver_geometry.h new file mode 100644 index 0000000..5a6d49b --- /dev/null +++ b/examples/board_reprap/src/c3/c3driver_geometry.h @@ -0,0 +1,40 @@ +/* + c3driver_geometry.h + + Copyright 2008-2012 Michel Pollet + + This file is part of simavr. + + simavr is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + simavr is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with simavr. If not, see . + */ + + +#ifndef __C3DRIVER_GEOMETRY_H___ +#define __C3DRIVER_GEOMETRY_H___ + +#include "c3/c3driver.h" + +struct c3geometry_t; + +typedef struct c3driver_geometry_t { + void (*dispose)( + struct c3geometry_t * geometry, + const struct c3driver_geometry_t *d); + void (*prepare)( + struct c3geometry_t * geometry, + const struct c3driver_geometry_t *d); +} c3driver_geometry_t, *c3driver_geometry_p; + + +#endif /* __C3DRIVER_GEOMETRY_H___ */ diff --git a/examples/board_reprap/src/c3/c3object_driver.h b/examples/board_reprap/src/c3/c3driver_object.h similarity index 57% rename from examples/board_reprap/src/c3/c3object_driver.h rename to examples/board_reprap/src/c3/c3driver_object.h index 056ea22..05a11f2 100644 --- a/examples/board_reprap/src/c3/c3object_driver.h +++ b/examples/board_reprap/src/c3/c3driver_object.h @@ -1,5 +1,5 @@ /* - c3object_driver.h + c3driver_object.h Copyright 2008-2012 Michel Pollet @@ -20,54 +20,46 @@ */ -#ifndef __C3OBJECT_DRIVER_H___ -#define __C3OBJECT_DRIVER_H___ +#ifndef __C3DRIVER_OBJECT_H___ +#define __C3DRIVER_OBJECT_H___ + +#include "c3/c3driver.h" -#include "c3/c3geometry.h" struct c3object_t; struct c3geometry_array_t; union c3mat4; -typedef struct c3object_driver_t { - struct c3object_driver_t * next; - struct c3object_t * object; +typedef struct c3driver_object_t { /* * Delete any object related to this object, geometry etc * The object will still exist, just empty */ - void (*clear)(struct c3object_driver_t * d); + void (*clear)( + struct c3object_t * object, + const struct c3driver_object_t * d); /* * Dispose of the remaining memory for an object, detaches it * and frees remaining traces of it */ - void (*dispose)(struct c3object_driver_t * d); + void (*dispose)( + struct c3object_t * object, + const struct c3driver_object_t * d); /* * Adds sub objects geometry and self geometry to array 'out' */ - void (*get_geometry)(struct c3object_driver_t * d, + void (*get_geometry)( + struct c3object_t * object, + const struct c3driver_object_t * d, struct c3geometry_array_t * out); /* * Reproject geometry along matrix 'mat', applies our own * transform and call down the chain for sub-objects */ - void (*project)(struct c3object_driver_t * d, + void (*project)( + struct c3object_t * object, + const struct c3driver_object_t * d, union c3mat4 * mat); -} c3object_driver_t, *c3object_driver_p; - +} c3driver_object_t, *c3driver_object_p; -#define C3O_DRIVER_CALL(__callback, __driver, __args...) { \ - typeof(__driver) __d = __driver;\ - while (__d) {\ - if (__d->__callback) {\ - __d->__callback(__d, ##__args);\ - break;\ - }\ - __d = __d->next;\ - }\ - } -#define C3O_DRIVER(__o, __callback, __args...) \ - C3O_DRIVER_CALL(__callback, __o->driver, ##__args) -#define C3O_DRIVER_INHERITED(__callback, __driver, __args...) \ - C3O_DRIVER_CALL(__callback, __driver->next, ##__args) -#endif /* __C3OBJECT_DRIVER_H___ */ +#endif /* __C3DRIVER_OBJECT_H___ */ diff --git a/examples/board_reprap/src/c3/c3geometry.c b/examples/board_reprap/src/c3/c3geometry.c index c81df63..d1f2994 100644 --- a/examples/board_reprap/src/c3/c3geometry.c +++ b/examples/board_reprap/src/c3/c3geometry.c @@ -21,24 +21,14 @@ #include "c3/c3object.h" +#include "c3/c3context.h" +#include "c3/c3driver_geometry.h" +#include "c3/c3driver_context.h" - -c3geometry_p -c3geometry_new( - int type, - c3object_p o /* = NULL */) -{ - c3geometry_p res = malloc(sizeof(c3geometry_t)); - memset(res, 0, sizeof(*res)); - res->type = type; - res->dirty = 1; - c3object_add_geometry(o, res); - return res; -} - -void -c3geometry_dispose( - c3geometry_p g) +static void +_c3geometry_dispose( + c3geometry_p g, + const struct c3driver_geometry_t *d) { /* * If we're still attached to an object, detach @@ -58,4 +48,65 @@ c3geometry_dispose( c3tex_array_free(&g->textures); c3colorf_array_free(&g->colorf); free(g); +// C3_DRIVER_INHERITED(g, d, dispose); +} + +static void +_c3geometry_prepare( + c3geometry_p g, + const struct c3driver_geometry_t *d) +{ + + if (g->object && g->object->context) + C3_DRIVER(g->object->context, geometry_prepare, g); + g->dirty = 0; +// C3_DRIVER_INHERITED(g, d, prepare); +} + +const c3driver_geometry_t c3geometry_driver = { + .dispose = _c3geometry_dispose, + .prepare = _c3geometry_prepare, +}; + +c3geometry_p +c3geometry_new( + c3geometry_type_t type, + c3object_p o /* = NULL */) +{ + c3geometry_p res = malloc(sizeof(c3geometry_t)); + return c3geometry_init(res, type, o); +} + +c3geometry_p +c3geometry_init( + c3geometry_p g, + c3geometry_type_t type, + struct c3object_t * o /* = NULL */) +{ + memset(g, 0, sizeof(*g)); + static const c3driver_geometry_t * list[] = { + &c3geometry_driver, NULL, + }; + g->driver = list; + g->type = type; + g->dirty = 1; + if (o) + c3object_add_geometry(o, g); + return g; +} + +void +c3geometry_dispose( + c3geometry_p g) +{ + C3_DRIVER(g, dispose); +} + +void +c3geometry_prepare( + c3geometry_p g ) +{ + if (!g->dirty) + return; + C3_DRIVER(g, prepare); } diff --git a/examples/board_reprap/src/c3/c3geometry.h b/examples/board_reprap/src/c3/c3geometry.h index e3a6d6e..2bfaa07 100644 --- a/examples/board_reprap/src/c3/c3geometry.h +++ b/examples/board_reprap/src/c3/c3geometry.h @@ -38,35 +38,72 @@ DECLARE_C_ARRAY(c3colorf, c3colorf_array, 16); typedef struct c3material_t { c3colorf color; + uint32_t texture; } c3material_t; +typedef struct c3bbox_t { + c3vec3 min, max; +} c3bbox_t; + +#define C3_RAW_TYPE (0) + +typedef union { + struct { uint32_t type : 16, subtype : 16; }; + uint32_t value; +} c3geometry_type_t; + typedef struct c3geometry_t { - int type; // GL_LINES etc - int dirty : 1; - str_p name; + c3geometry_type_t type; // GL_LINES etc + int dirty : 1, texture : 1; + str_p name; // optional c3material_t mat; struct c3object_t * object; + const struct c3driver_geometry_t ** driver; c3vertex_array_t vertice; c3tex_array_t textures; c3colorf_array_t colorf; // projected version of the vertice c3vertex_array_t projected; + c3bbox_t bbox; + + /* + * optional, geometry dependant custom draw method + * return nonzero will orevent the default drawing code + * from being called (c3context one) + */ + int (*draw)(struct c3geometry_t *); } c3geometry_t, *c3geometry_p; DECLARE_C_ARRAY(c3geometry_p, c3geometry_array, 4); c3geometry_p c3geometry_new( - int type, + c3geometry_type_t type, + struct c3object_t * o /* = NULL */); +c3geometry_p +c3geometry_init( + c3geometry_p g, + c3geometry_type_t type, struct c3object_t * o /* = NULL */); void c3geometry_dispose( c3geometry_p g); +void +c3geometry_prepare( + c3geometry_p g ); + IMPLEMENT_C_ARRAY(c3geometry_array); IMPLEMENT_C_ARRAY(c3vertex_array); IMPLEMENT_C_ARRAY(c3tex_array); IMPLEMENT_C_ARRAY(c3colorf_array); +static inline c3geometry_type_t +c3geometry_type(int type, int subtype) +{ + c3geometry_type_t r = { .type = type, . subtype = subtype }; + return r; +} + #endif /* __C3GEOMETRY_H___ */ diff --git a/examples/board_reprap/src/c3/c3object.c b/examples/board_reprap/src/c3/c3object.c index 0b1d31c..19ddb4e 100644 --- a/examples/board_reprap/src/c3/c3object.c +++ b/examples/board_reprap/src/c3/c3object.c @@ -21,12 +21,13 @@ #include "c3/c3object.h" +#include "c3/c3driver_object.h" void _c3object_clear( - c3object_driver_p d) + c3object_p o, + const c3driver_object_t * d) { - c3object_p o = d->object; for (int oi = 0; oi < o->transform.count; oi++) { o->transform.e[oi]->object = NULL; c3transform_dispose(o->transform.e[oi]); @@ -46,9 +47,9 @@ _c3object_clear( void _c3object_dispose( - c3object_driver_p d) + c3object_p o, + const c3driver_object_t * d) { - c3object_p o = d->object; if (o->parent) { for (int oi = 0; oi < o->parent->objects.count; oi++) if (o->parent->objects.e[oi] == o) { @@ -59,24 +60,15 @@ _c3object_dispose( o->parent = NULL; } //C3O_DRIVER_INHERITED(dispose, d); - /* - * free the driver chain - */ - c3object_driver_p driver = o->driver; - while (driver) { - c3object_driver_p n = driver->next; - free(n); - driver = n; - } free(o); } void _c3object_get_geometry( - c3object_driver_p d, + c3object_p o, + const c3driver_object_t * d, c3geometry_array_p out) { - c3object_p o = d->object; for (int oi = 0; oi < o->geometry.count; oi++) c3geometry_array_add(out, o->geometry.e[oi]); for (int oi = 0; oi < o->objects.count; oi++) @@ -85,27 +77,39 @@ _c3object_get_geometry( void _c3object_project( - c3object_driver_p d, + c3object_p o, + const c3driver_object_t * d, c3mat4p m) { - c3object_p o = d->object; if (!o->dirty) return; - c3mat4 identity = identity3D(); +// c3mat4 identity = identity3D(); c3mat4 p = *m; for (int pi = 0; pi < o->transform.count; pi++) p = c3mat4_mul(&p, &o->transform.e[pi]->matrix); - bool is_identity = c3mat4_equal(m, &identity); +// bool is_identity = c3mat4_equal(m, &identity); for (int gi = 0; gi < o->geometry.count; gi++) { c3geometry_p g = o->geometry.e[gi]; c3vertex_array_clear(&g->projected); - if (1) { + + g->bbox.min = g->bbox.max = c3vec3f(0,0,0); + c3geometry_prepare(g); + + /* 'prepare' might have done something ? */ + if (g->vertice.count && !g->projected.count) { c3vertex_array_realloc(&g->projected, g->vertice.count); g->projected.count = g->vertice.count; - for (int vi = 0; vi < g->vertice.count; vi++) + for (int vi = 0; vi < g->vertice.count; vi++) { g->projected.e[vi] = c3mat4_mulv3(&p, g->vertice.e[vi]); + if (vi == 0) + g->bbox.min = g->bbox.max = g->projected.e[vi]; + else { + g->bbox.max = c3vec3_min(g->bbox.min, g->projected.e[vi]); + g->bbox.max = c3vec3_max(g->bbox.max, g->projected.e[vi]); + } + } } } for (int oi = 0; oi < o->objects.count; oi++) @@ -113,13 +117,14 @@ _c3object_project( o->dirty = false; } -const c3object_driver_t c3object_base_driver = { +const c3driver_object_t c3object_driver = { .clear = _c3object_clear, .dispose = _c3object_dispose, .get_geometry = _c3object_get_geometry, .project = _c3object_project, }; + c3object_p c3object_init( c3object_p o /* = NULL */, @@ -127,11 +132,13 @@ c3object_init( { memset(o, 0, sizeof(*o)); o->parent = parent; - o->driver = malloc(sizeof(c3object_driver_t)); - *o->driver = c3object_base_driver; - o->driver->object = o; - if (parent) + static const c3driver_object_t * list[] = + { &c3object_driver, NULL }; + o->driver = list; + if (parent) { c3object_array_add(&parent->objects, o); + o->context = parent->context; + } return o; } @@ -147,7 +154,7 @@ void c3object_clear( c3object_p o) { - C3O_DRIVER(o, clear); + C3_DRIVER(o, clear); } void @@ -155,7 +162,7 @@ c3object_dispose( c3object_p o) { c3object_clear(o); - C3O_DRIVER(o, dispose); + C3_DRIVER(o, dispose); } void @@ -229,7 +236,7 @@ c3object_get_geometry( c3object_p o, c3geometry_array_p array ) { - C3O_DRIVER(o, get_geometry, array); + C3_DRIVER(o, get_geometry, array); } void @@ -237,5 +244,5 @@ c3object_project( c3object_p o, const c3mat4p m) { - C3O_DRIVER(o, project, m); + C3_DRIVER(o, project, m); } diff --git a/examples/board_reprap/src/c3/c3object.h b/examples/board_reprap/src/c3/c3object.h index d221393..dd77975 100644 --- a/examples/board_reprap/src/c3/c3object.h +++ b/examples/board_reprap/src/c3/c3object.h @@ -26,7 +26,6 @@ #include #include "c3/c3transform.h" #include "c3/c3geometry.h" -#include "c3/c3object_driver.h" struct c3object_t; @@ -34,9 +33,10 @@ DECLARE_C_ARRAY(struct c3object_t*, c3object_array, 4); typedef struct c3object_t { str_p name; - int dirty : 1; + int dirty : 1, visible : 1 /* TODO: Implement visible */; + struct c3context_t * context; struct c3object_t * parent; - c3object_driver_p driver; + const struct c3driver_object_t ** driver; c3transform_array_t transform; c3object_array_t objects; c3geometry_array_t geometry; @@ -56,6 +56,7 @@ c3object_p c3object_init( c3object_p o /* = NULL */, c3object_p parent); + void c3object_set_dirty( c3object_p o, diff --git a/examples/board_reprap/src/c3/c3pixels.c b/examples/board_reprap/src/c3/c3pixels.c new file mode 100644 index 0000000..445b4f0 --- /dev/null +++ b/examples/board_reprap/src/c3/c3pixels.c @@ -0,0 +1,100 @@ +/* + c3pixels.c + + Copyright 2008-2012 Michel Pollet + + This file is part of simavr. + + simavr is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + simavr is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with simavr. If not, see . + */ + +#include +#include +#include "c3pixels.h" + +c3pixelsp +c3pixels_new( + uint32_t w, + uint32_t h, + int psize /* in bytes */, + size_t row, + void * base) +{ + c3pixelsp p = malloc(sizeof(*p)); + c3pixels_init(p, w, h, psize, row, base); + p->alloc = 1; + return p; +} + +c3pixelsp +c3pixels_init( + c3pixelsp p, + uint32_t w, + uint32_t h, + int psize /* in bytes */, + size_t row, + void * base) +{ + memset (p, 0, sizeof(*p)); + p->w = w; + p->h = h; + p->row = row; + p->psize = psize; + p->base = base; + c3pixels_alloc(p); + return p; +} + +void +c3pixels_dispose( + c3pixelsp p ) +{ + if (p->own && p->base) + free(p->base); + if (p->alloc) + free(p); + else + memset(p, 0, sizeof(p)); +} + +void +c3pixels_alloc( + c3pixelsp p ) +{ + if (p->base) + return; + p->base = malloc(p->row * p->h); + p->own = p->base != NULL; +} + +void +c3pixels_purge( + c3pixelsp p ) +{ + if (!p->base) + return; + if (p->own) + free(p->base); + p->own = 0; + p->base = NULL; +} + +void +c3pixels_zero( + c3pixelsp p) +{ + if (!p->base) + return; + memset(p->base, 0, p->h * p->row); +} diff --git a/examples/board_reprap/src/c3/c3pixels.h b/examples/board_reprap/src/c3/c3pixels.h new file mode 100644 index 0000000..6fc1aa1 --- /dev/null +++ b/examples/board_reprap/src/c3/c3pixels.h @@ -0,0 +1,94 @@ +/* + c3pixels.h + + Copyright 2008-2012 Michel Pollet + + This file is part of simavr. + + simavr is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + simavr is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with simavr. If not, see . + */ + + +#ifndef __C3PIXELS_H___ +#define __C3PIXELS_H___ + +#include + +typedef struct c3pixels_t { + uint32_t w, h; // width & height in pixels + size_t row; // size of one row in bytes + void * base; // base address + + union { + struct { + uint32_t own : 1, // is the base our own to delete + alloc : 1, // is the c3pixelsp our own to delete + dirty : 1, // pixels have been changed + psize : 4, // pixel size in byte + format : 8; // not used internally + }; + uint32_t flags; + }; + int refCount; // TODO: Implement reference counting ? +} c3pixels_t, *c3pixelsp; + +//! Allocates a new c3pixels, also allocates the pixels if row == NULL +c3pixelsp +c3pixels_new( + uint32_t w, + uint32_t h, + int psize /* in bytes */, + size_t row, + void * base); + +//! Initializes p, also allocates the pixels if row == NULL +c3pixelsp +c3pixels_init( + c3pixelsp p, + uint32_t w, + uint32_t h, + int psize /* in bytes */, + size_t row, + void * base); + +//! Dispose of the pixels, and potentially p if it was allocated with c3pixels_new +void +c3pixels_dispose( + c3pixelsp p ); + +//! Disposes of the pixels, only +void +c3pixels_purge( + c3pixelsp p ); + +//! (Re)allocate pixels if pixels had been purged +void +c3pixels_alloc( + c3pixelsp p ); + +//! Get a pixel address +static inline void * +c3pixels_get( + c3pixelsp p, + int x, int y) +{ + return ((uint8_t*)p->base) + (y * p->row) + (x * p->psize); +} + +//! Zeroes the pixels +void +c3pixels_zero( + c3pixelsp p); + +#endif /* __C3PIXELS_H___ */ diff --git a/examples/board_reprap/src/c3/c3texture.c b/examples/board_reprap/src/c3/c3texture.c new file mode 100644 index 0000000..abccc52 --- /dev/null +++ b/examples/board_reprap/src/c3/c3texture.c @@ -0,0 +1,101 @@ +/* + c3texture.c + + Copyright 2008-2012 Michel Pollet + + This file is part of simavr. + + simavr is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + simavr is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with simavr. If not, see . + */ + + +#include "c3texture.h" +#include "c3/c3driver_geometry.h" + +void +_c3texture_dispose( + c3geometry_p g, + const c3driver_geometry_t * d) +{ + c3texture_p t = (c3texture_p)g; + c3pixels_dispose(&t->pixels); + C3_DRIVER_INHERITED(g, d, dispose); +} + +void +_c3texture_prepare( + c3geometry_p g, + const c3driver_geometry_t * d) +{ + c3texture_p t = (c3texture_p)g; + if (!t->pixels.base) { + C3_DRIVER_INHERITED(g, d, prepare); + return; + } + c3vec3 v[4] = { + c3vec3f(0, 0, 0), c3vec3f(t->pixels.w, 0, 0), + c3vec3f(t->pixels.w, t->pixels.h, 0), c3vec3f(0, t->pixels.h, 0) + }; + c3vertex_array_clear(&g->vertice); + c3vertex_array_realloc(&g->vertice, 4); + c3vertex_array_insert(&g->vertice, 0, v, 4); + + c3vec2 ti[4] = { + c3vec2f(0, 0), c3vec2f(t->pixels.w, 0), + c3vec2f(t->pixels.w, t->pixels.h), c3vec2f(0, t->pixels.h) + }; + c3tex_array_clear(&t->geometry.textures); + c3tex_array_realloc(&t->geometry.textures, 4); + c3tex_array_insert(&t->geometry.textures, 0, ti, 4); + + C3_DRIVER_INHERITED(g, d, prepare); +} + +const c3driver_geometry_t c3texture_driver = { + .dispose = _c3texture_dispose, + .prepare = _c3texture_prepare, +}; +const c3driver_geometry_t c3geometry_driver; + +c3texture_p +c3texture_new( + struct c3object_t * o /* = NULL */) +{ + c3texture_p res = malloc(sizeof(*res)); + return c3texture_init(res, o); +} + +c3texture_p +c3texture_init( + c3texture_p t, + struct c3object_t * o /* = NULL */) +{ + memset(t, 0, sizeof(*t)); + c3geometry_init(&t->geometry, + c3geometry_type(C3_TEXTURE_TYPE, 0 /* GL_TRIANGLE_FAN */), + o); + static const c3driver_geometry_t * list[] = { + &c3texture_driver, &c3geometry_driver, NULL, + }; + t->geometry.driver = list; + + return t; +} + +void +c3texture_setpixels( + ) +{ + +} diff --git a/examples/board_reprap/src/c3/c3texture.h b/examples/board_reprap/src/c3/c3texture.h new file mode 100644 index 0000000..cd34ecb --- /dev/null +++ b/examples/board_reprap/src/c3/c3texture.h @@ -0,0 +1,44 @@ +/* + c3texture.h + + Copyright 2008-2012 Michel Pollet + + This file is part of simavr. + + simavr is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + simavr is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with simavr. If not, see . + */ + + +#ifndef __C3TEXTURE_H___ +#define __C3TEXTURE_H___ + +#include "c3/c3geometry.h" +#include "c3/c3pixels.h" + +#define C3_TEXTURE_TYPE (1) + +typedef struct c3texture_t { + c3geometry_t geometry; + c3pixels_t pixels; +} c3texture_t, *c3texture_p; + +c3texture_p +c3texture_new( + struct c3object_t * parent /* = NULL */); +c3texture_p +c3texture_init( + c3texture_p t, + struct c3object_t * parent /* = NULL */); + +#endif /* __C3TEXTURE_H___ */ diff --git a/examples/board_reprap/src/reprap_gl.c b/examples/board_reprap/src/reprap_gl.c index e2afe54..fc6d16f 100644 --- a/examples/board_reprap/src/reprap_gl.c +++ b/examples/board_reprap/src/reprap_gl.c @@ -26,6 +26,7 @@ #endif #include +#include #include "reprap.h" #include "reprap_gl.h" @@ -33,16 +34,27 @@ #include "c3/c3.h" #include "c3/c3camera.h" #include "c3/c3arcball.h" +#include "c3/c3driver_context.h" int _w = 800, _h = 600; c3cam cam; c3arcball arcball; -c3object_p root; +c3context_p c3; c3object_p head; -c3geometry_array_t geo_sorted = C_ARRAY_NULL; extern reprap_t reprap; +static int dumpError(const char * what) +{ + GLenum e; + int count = 0; + while ((e = glGetError()) != GL_NO_ERROR) { + printf("%s: %s\n", what, gluErrorString(e)); + count++; + } + return count; +} + static void _gl_key_cb( unsigned char key, @@ -65,6 +77,98 @@ _gl_key_cb( } } +static void +_c3_geometry_prepare( + c3context_p c, + const struct c3driver_context_t *d, + c3geometry_p g) +{ + printf("_c3_geometry_prepare %p %d/%d!\n", g, g->type.type, g->type.subtype); + switch(g->type.type) { + case C3_TEXTURE_TYPE: { + c3texture_p t = (c3texture_p)g; + g->type.subtype = GL_TRIANGLE_FAN; + g->mat.color = c3vec4f(0.0, 1.0, 0.0, 0.5); + printf("_c3_geometry_prepare xrure %d!\n", g->textures.count); + if (!g->texture) { + GLuint texID = 0; + dumpError("cp_gl_texture_load_argb flush"); + + glEnable(GL_TEXTURE_RECTANGLE_ARB); + dumpError("cp_gl_texture_load_argb GL_TEXTURE_RECTANGLE_ARB"); + + glGenTextures(1, &texID); + dumpError("cp_gl_texture_load_argb glBindTexture GL_TEXTURE_RECTANGLE_ARB"); + + glPixelStorei(GL_UNPACK_ROW_LENGTH, t->pixels.row / 4); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + g->mat.texture = texID; + g->texture = 1; + } + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, g->mat.texture); + glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, + t->pixels.w, t->pixels.h, 0, + GL_RGBA, GL_UNSIGNED_BYTE, + t->pixels.base); + } break; + default: + break; + } +} + +static void +_c3_geometry_draw( + c3context_p c, + const struct c3driver_context_t *d, + c3geometry_p g ) +{ + glColor4fv(g->mat.color.n); + glVertexPointer(3, GL_FLOAT, 0, + g->projected.count ? g->projected.e : g->vertice.e); + glEnableClientState(GL_VERTEX_ARRAY); + if (g->textures.count && g->texture) { + glDisable(GL_TEXTURE_2D); + glEnable(GL_TEXTURE_RECTANGLE_ARB); + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, g->mat.texture); + glTexCoordPointer(2, GL_FLOAT, 0, + g->textures.e); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + } else + glDisable(GL_TEXTURE_RECTANGLE_ARB); + + glDrawArrays(g->type.subtype, 0, g->vertice.count); + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); +} + +const c3driver_context_t c3context_driver = { + .geometry_prepare = _c3_geometry_prepare, + .geometry_draw = _c3_geometry_draw, +}; + +/* + * Computes the distance from the eye, sort by this value + */ +static int +_c3_z_sorter( + const void *_p1, + const void *_p2) +{ + c3geometry_p g1 = *(c3geometry_p*)_p1; + c3geometry_p g2 = *(c3geometry_p*)_p2; + // get center of bboxes + c3vec3 c1 = c3vec3_add(g1->bbox.min, c3vec3_divf(c3vec3_sub(g1->bbox.max, g1->bbox.min), 2)); + c3vec3 c2 = c3vec3_add(g2->bbox.min, c3vec3_divf(c3vec3_sub(g2->bbox.max, g2->bbox.min), 2)); + + c3f d1 = c3vec3_length2(c3vec3_sub(c1, cam.eye)); + c3f d2 = c3vec3_length2(c3vec3_sub(c2, cam.eye)); + + return d1 < d2 ? 1 : d1 > d2 ? -1 : 0; +} static void _gl_display_cb(void) /* function called whenever redisplay needed */ @@ -101,25 +205,14 @@ _gl_display_cb(void) /* function called whenever redisplay needed */ c3mat4 headmove = translation3D(headp); c3transform_set(head->transform.e[0], &headmove); - if (root->dirty) { + if (c3->root->dirty) { printf("reproject\n"); - c3mat4 m = identity3D(); - c3object_project(root, &m); - c3geometry_array_clear(&geo_sorted); - c3object_get_geometry(root, &geo_sorted); - } - - for (int gi = 0; gi < geo_sorted.count; gi++) { - c3geometry_p g = geo_sorted.e[gi]; - glColor4fv(g->mat.color.n); - glVertexPointer(3, GL_FLOAT, 0, g->projected.count ? g->projected.e : g->vertice.e); - glEnableClientState(GL_VERTEX_ARRAY); - - glDrawArrays(g->type, 0, g->vertice.count); - - glDisableClientState(GL_VERTEX_ARRAY); + c3context_prepare(c3); + qsort(c3->projected.e, c3->projected.count, + sizeof(c3->projected.e[0]), _c3_z_sorter); } + c3context_draw(c3); glMatrixMode(GL_PROJECTION); // Select projection matrix glLoadIdentity(); // Start with an identity matrix @@ -187,6 +280,7 @@ _gl_motion_cb( c3cam_rot_about_lookat(&cam, &rotx); c3cam_update_matrix(&cam); + c3->root->dirty = 1; // resort the array // c3arcball_mouse_motion(&arcball, x, y, 0,0,0); } break; case GLUT_RIGHT_BUTTON: { @@ -226,8 +320,17 @@ gl_init( glutMouseFunc(_gl_button_cb); glutMotionFunc(_gl_motion_cb); + glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); + glHint(GL_POINT_SMOOTH_HINT, GL_NICEST); glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); + glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST); + glEnable(GL_LINE_SMOOTH); + + glEnable(GL_BLEND); + // Works for the UI !! + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + cam = c3cam_new(); cam.lookat = c3vec3f(100.0, 100.0, 0.0); cam.eye = c3vec3f(100.0, -100.0, 100.0); @@ -236,27 +339,31 @@ gl_init( c3arcball_init_center(&arcball, c3vec2f(_w/2, _h/2), 100); // hd44780_gl_init(); - root = c3object_new(NULL); + c3 = c3context_new(_w, _h); + static const c3driver_context_t * list[] = { &c3context_driver, NULL }; + c3->driver = list; - c3object_p grid = c3object_new(root); + c3object_p grid = c3object_new(c3->root); { - c3geometry_p g = c3geometry_new(GL_LINES, grid); - g->mat.color = c3vec4f(1.0, 1.0, 1.0, 1.0); for (int x = 0; x < 20; x++) { for (int y = 0; y < 20; y++) { c3vec3 p[4] = { c3vec3f(-1+x*10,y*10,0), c3vec3f(1+x*10,y*10,0), c3vec3f(x*10,-1+y*10,0), c3vec3f(x*10,1+y*10,0), }; + c3geometry_p g = c3geometry_new( + c3geometry_type(C3_RAW_TYPE, GL_LINES), grid); + g->mat.color = c3vec4f(1.0, 1.0, 1.0, 1.0); c3vertex_array_insert(&g->vertice, g->vertice.count, p, 4); } } } - head = c3object_new(root); + head = c3object_new(c3->root); c3transform_new(head); { - c3geometry_p g = c3geometry_new(GL_LINES, head); + c3geometry_p g = c3geometry_new( + c3geometry_type(C3_RAW_TYPE, GL_LINES), head); g->mat.color = c3vec4f(1.0, 0.0, 0.0, 1.0); c3vec3 p[4] = { c3vec3f(-1, 0, 0), c3vec3f(1, 0, 0), @@ -265,6 +372,11 @@ gl_init( c3vertex_array_insert(&g->vertice, g->vertice.count, p, 4); } + c3texture_p b = c3texture_new(head); + c3pixels_init(&b->pixels, 64, 64, 4, 4 * 64, NULL); + b->geometry.dirty = 1; + memset(b->pixels.base, 0xff, 10 * b->pixels.row); + return 1; } -- 2.39.5