Commit c4b85342d6f8b5e3a205492a59821ba673def98f
authorMichel Pollet <buserror@gmail.com>
Sun, 20 May 2012 20:25:16 +0000 (21:25 +0100)
committerMichel Pollet <buserror@gmail.com>
Sun, 20 May 2012 20:25:16 +0000 (21:25 +0100)
Added tons of stuff to the micro-scene-graph 3D code.

Signed-off-by: Michel Pollet <buserror@gmail.com>
20 files changed:
examples/board_reprap/src/c3/README.md
examples/board_reprap/src/c3/c3.h
examples/board_reprap/src/c3/c3cairo.c
examples/board_reprap/src/c3/c3cairo.h
examples/board_reprap/src/c3/c3context.c [new file with mode: 0644]
examples/board_reprap/src/c3/c3context.h [new file with mode: 0644]
examples/board_reprap/src/c3/c3driver.h [new file with mode: 0644]
examples/board_reprap/src/c3/c3driver_context.h [new file with mode: 0644]
examples/board_reprap/src/c3/c3driver_geometry.h [new file with mode: 0644]
examples/board_reprap/src/c3/c3driver_object.h [new file with mode: 0644]
examples/board_reprap/src/c3/c3geometry.c
examples/board_reprap/src/c3/c3geometry.h
examples/board_reprap/src/c3/c3object.c
examples/board_reprap/src/c3/c3object.h
examples/board_reprap/src/c3/c3object_driver.h [deleted file]
examples/board_reprap/src/c3/c3pixels.c [new file with mode: 0644]
examples/board_reprap/src/c3/c3pixels.h [new file with mode: 0644]
examples/board_reprap/src/c3/c3texture.c [new file with mode: 0644]
examples/board_reprap/src/c3/c3texture.h [new file with mode: 0644]
examples/board_reprap/src/reprap_gl.c

index b1e709094dc7c9d34274fe4e7ea02211842e787b..31207abfb6f7e6b16a19846edf47c60b7526e5d5 100644 (file)
@@ -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.
-
index 5766c585cd62d9d6bb7aafcc72346fd4c09034e5..410fa3e51885fc3c2c9255332918403fa9bfa7bb 100644 (file)
 #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___ */
index 6472b6244811d298c4ca51a0c8bb5a58287e5499..88fa4d985c6de025b6abd5269d412fc19df52cbe 100644 (file)
 
 
 #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
index cecae0e623a15aab8ce5b6717455cb66c881c048..75082b370ba8559ddf0536c804888f2a4edc2039 100644 (file)
 #ifndef __C3CAIRO_H___
 #define __C3CAIRO_H___
 
-#include "c3/c3object.h"
+#include "c3/c3texture.h"
+#include "c3/c3pixels.h"
+#include <pango/pangocairo.h>
 
 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 (file)
index 0000000..6c28758
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+       c3context.c
+
+       Copyright 2008-2012 Michel Pollet <buserror@gmail.com>
+
+       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 <http://www.gnu.org/licenses/>.
+ */
+
+
+#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 (file)
index 0000000..8d42887
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+       c3context.h
+
+       Copyright 2008-2012 Michel Pollet <buserror@gmail.com>
+
+       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 <http://www.gnu.org/licenses/>.
+ */
+
+
+#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 (file)
index 0000000..901c32d
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+       c3driver.h
+
+       Copyright 2008-2012 Michel Pollet <buserror@gmail.com>
+
+       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 <http://www.gnu.org/licenses/>.
+ */
+
+
+#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 (file)
index 0000000..1a744a7
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+       c3driver_context.h
+
+       Copyright 2008-2012 Michel Pollet <buserror@gmail.com>
+
+       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 <http://www.gnu.org/licenses/>.
+ */
+
+
+#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 (file)
index 0000000..5a6d49b
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+       c3driver_geometry.h
+
+       Copyright 2008-2012 Michel Pollet <buserror@gmail.com>
+
+       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 <http://www.gnu.org/licenses/>.
+ */
+
+
+#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/c3driver_object.h b/examples/board_reprap/src/c3/c3driver_object.h
new file mode 100644 (file)
index 0000000..05a11f2
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+       c3driver_object.h
+
+       Copyright 2008-2012 Michel Pollet <buserror@gmail.com>
+
+       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 <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef __C3DRIVER_OBJECT_H___
+#define __C3DRIVER_OBJECT_H___
+
+#include "c3/c3driver.h"
+
+struct c3object_t;
+struct c3geometry_array_t;
+union c3mat4;
+
+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_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_t * object,
+                       const struct c3driver_object_t * d);
+       /*
+        * Adds sub objects geometry and self geometry to array 'out'
+        */
+       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_t * object,
+                       const struct c3driver_object_t * d,
+                       union c3mat4 * mat);
+} c3driver_object_t, *c3driver_object_p;
+
+
+#endif /* __C3DRIVER_OBJECT_H___ */
index c81df63f2d9c6520a451fc9ce6bce7fb74644389..d1f2994ae074939e6a62b365e18474d22d419ac5 100644 (file)
 
 
 #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);
 }
index e3a6d6ecce6626e3ea488170b29b4fd82fe3e2ed..2bfaa079ba1d4bb40b264e6ee0e6fa9b11201b43 100644 (file)
@@ -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___ */
index 0b1d31c48dc1756f6d6a0a3647bb75d6dba47815..19ddb4edd5223b6b2fd61e073d7dc3fba91bee3c 100644 (file)
 
 
 #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);
 }
index d2213939f9cd7b2e64227a75bbcf8d0a33b90102..dd77975eea70030fe543501d4cb8aa05e780b277 100644 (file)
@@ -26,7 +26,6 @@
 #include <stdbool.h>
 #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/c3object_driver.h b/examples/board_reprap/src/c3/c3object_driver.h
deleted file mode 100644 (file)
index 056ea22..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
-       c3object_driver.h
-
-       Copyright 2008-2012 Michel Pollet <buserror@gmail.com>
-
-       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 <http://www.gnu.org/licenses/>.
- */
-
-
-#ifndef __C3OBJECT_DRIVER_H___
-#define __C3OBJECT_DRIVER_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;
-       /*
-        * Delete any object related to this object, geometry etc
-        * The object will still exist, just empty
-        */
-       void (*clear)(struct c3object_driver_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);
-       /*
-        * Adds sub objects geometry and self geometry to array 'out'
-        */
-       void (*get_geometry)(struct c3object_driver_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,
-                       union c3mat4 * mat);
-} c3object_driver_t, *c3object_driver_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___ */
diff --git a/examples/board_reprap/src/c3/c3pixels.c b/examples/board_reprap/src/c3/c3pixels.c
new file mode 100644 (file)
index 0000000..445b4f0
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+       c3pixels.c
+
+       Copyright 2008-2012 Michel Pollet <buserror@gmail.com>
+
+       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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#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 (file)
index 0000000..6fc1aa1
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+       c3pixels.h
+
+       Copyright 2008-2012 Michel Pollet <buserror@gmail.com>
+
+       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 <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef __C3PIXELS_H___
+#define __C3PIXELS_H___
+
+#include <stdint.h>
+
+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 (file)
index 0000000..abccc52
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+       c3texture.c
+
+       Copyright 2008-2012 Michel Pollet <buserror@gmail.com>
+
+       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 <http://www.gnu.org/licenses/>.
+ */
+
+
+#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 (file)
index 0000000..cd34ecb
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+       c3texture.h
+
+       Copyright 2008-2012 Michel Pollet <buserror@gmail.com>
+
+       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 <http://www.gnu.org/licenses/>.
+ */
+
+
+#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___ */
index e2afe54eb26259af8a9f1f9b028d0d0af0b3f7f8..fc6d16f9f3d26d924bbdf69f8dd7c983bb64dfce 100644 (file)
@@ -26,6 +26,7 @@
 #endif
 
 #include <stdio.h>
+#include <math.h>
 
 #include "reprap.h"
 #include "reprap_gl.h"
 #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;
 }