Added tons of stuff to the micro-scene-graph 3D code.
Signed-off-by: Michel Pollet <buserror@gmail.com>
* 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)
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)
* *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.
-
#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___ */
#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
#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___ */
--- /dev/null
+/*
+ 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);
+ }
+}
--- /dev/null
+/*
+ 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___ */
--- /dev/null
+/*
+ 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___ */
--- /dev/null
+/*
+ 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___ */
--- /dev/null
+/*
+ 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___ */
--- /dev/null
+/*
+ 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___ */
#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
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);
}
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___ */
#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]);
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) {
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++)
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++)
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 */,
{
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;
}
c3object_clear(
c3object_p o)
{
- C3O_DRIVER(o, clear);
+ C3_DRIVER(o, clear);
}
void
c3object_p o)
{
c3object_clear(o);
- C3O_DRIVER(o, dispose);
+ C3_DRIVER(o, dispose);
}
void
c3object_p o,
c3geometry_array_p array )
{
- C3O_DRIVER(o, get_geometry, array);
+ C3_DRIVER(o, get_geometry, array);
}
void
c3object_p o,
const c3mat4p m)
{
- C3O_DRIVER(o, project, m);
+ C3_DRIVER(o, project, m);
}
#include <stdbool.h>
#include "c3/c3transform.h"
#include "c3/c3geometry.h"
-#include "c3/c3object_driver.h"
struct c3object_t;
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;
c3object_init(
c3object_p o /* = NULL */,
c3object_p parent);
+
void
c3object_set_dirty(
c3object_p o,
+++ /dev/null
-/*
- 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___ */
--- /dev/null
+/*
+ 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);
+}
--- /dev/null
+/*
+ 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___ */
--- /dev/null
+/*
+ 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(
+ )
+{
+
+}
--- /dev/null
+/*
+ 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___ */
#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,
}
}
+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 */
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
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: {
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);
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),
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;
}