reprap: c3 update
[simavr] / examples / board_reprap / src / c3 / c3object.c
1 /*
2         c3object.c
3
4         Copyright 2008-2012 Michel Pollet <buserror@gmail.com>
5
6         This file is part of simavr.
7
8         simavr is free software: you can redistribute it and/or modify
9         it under the terms of the GNU General Public License as published by
10         the Free Software Foundation, either version 3 of the License, or
11         (at your option) any later version.
12
13         simavr is distributed in the hope that it will be useful,
14         but WITHOUT ANY WARRANTY; without even the implied warranty of
15         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16         GNU General Public License for more details.
17
18         You should have received a copy of the GNU General Public License
19         along with simavr.  If not, see <http://www.gnu.org/licenses/>.
20  */
21
22
23 #include "c3/c3object.h"
24 #include "c3/c3driver_object.h"
25
26 void
27 _c3object_clear(
28                 c3object_p o,
29                 const c3driver_object_t * d)
30 {
31         for (int oi = 0; oi < o->transform.count; oi++) {
32                 o->transform.e[oi]->object = NULL;
33                 c3transform_dispose(o->transform.e[oi]);
34         }
35         for (int oi = 0; oi < o->geometry.count; oi++) {
36                 o->geometry.e[oi]->object = NULL;       // don't try to detach
37                 c3geometry_dispose(o->geometry.e[oi]);
38         }
39         for (int oi = 0; oi < o->objects.count; oi++) {
40                 o->objects.e[oi]->parent = NULL;        // don't try to detach
41                 c3object_dispose(o->objects.e[oi]);
42         }
43         c3object_array_free(&o->objects);
44         c3geometry_array_free(&o->geometry);
45         c3transform_array_free(&o->transform);
46 }
47
48 void
49 _c3object_dispose(
50                 c3object_p o,
51                 const c3driver_object_t * d)
52 {
53         if (o->parent) {
54                 for (int oi = 0; oi < o->parent->objects.count; oi++)
55                         if (o->parent->objects.e[oi] == o) {
56                                 c3object_array_delete(&o->parent->objects, oi, 1);
57                                 c3object_set_dirty(o->parent, true);
58                                 break;
59                         }
60                 o->parent = NULL;
61         }
62         //C3O_DRIVER_INHERITED(dispose, d);
63         free(o);
64 }
65
66 void
67 _c3object_get_geometry(
68                 c3object_p o,
69                 const c3driver_object_t * d,
70                 c3geometry_array_p out)
71 {
72         for (int oi = 0; oi < o->geometry.count; oi++)
73                 c3geometry_array_add(out, o->geometry.e[oi]);
74         for (int oi = 0; oi < o->objects.count; oi++)
75                 c3object_get_geometry(o->objects.e[oi], out);
76 }
77
78 void
79 _c3object_project(
80                 c3object_p o,
81                 const c3driver_object_t * d,
82                 c3mat4p m)
83 {
84         if (!o->dirty)
85                 return;
86
87 //      c3mat4 identity = identity3D();
88         c3mat4 p = *m;
89         for (int pi = 0; pi < o->transform.count; pi++)
90                 p = c3mat4_mul(&p, &o->transform.e[pi]->matrix);
91 //      bool is_identity = c3mat4_equal(m, &identity);
92
93         for (int gi = 0; gi < o->geometry.count; gi++) {
94                 c3geometry_p g = o->geometry.e[gi];
95                 c3vertex_array_clear(&g->projected);
96
97                 g->bbox.min = g->bbox.max = c3vec3f(0,0,0);
98                 c3geometry_prepare(g);
99
100                 /* 'prepare' might have done something ? */
101                 if (g->vertice.count && !g->projected.count) {
102                         c3vertex_array_realloc(&g->projected, g->vertice.count);
103                         g->projected.count = g->vertice.count;
104                         for (int vi = 0; vi < g->vertice.count; vi++) {
105                                 g->projected.e[vi] = c3mat4_mulv3(&p, g->vertice.e[vi]);
106                                 if (vi == 0)
107                                         g->bbox.min = g->bbox.max = g->projected.e[vi];
108                                 else {
109                                         g->bbox.max = c3vec3_min(g->bbox.min, g->projected.e[vi]);
110                                         g->bbox.max = c3vec3_max(g->bbox.max, g->projected.e[vi]);
111                                 }
112                         }
113                 }
114         }
115         for (int oi = 0; oi < o->objects.count; oi++)
116                 c3object_project(o->objects.e[oi], &p);
117         o->dirty = false;
118 }
119
120 const c3driver_object_t c3object_driver = {
121         .clear = _c3object_clear,
122         .dispose = _c3object_dispose,
123         .get_geometry = _c3object_get_geometry,
124         .project = _c3object_project,
125 };
126
127
128 c3object_p
129 c3object_init(
130                 c3object_p o /* = NULL */,
131                 c3object_p parent)
132 {
133         memset(o, 0, sizeof(*o));
134         o->parent = parent;
135         static const c3driver_object_t * list[] =
136                         { &c3object_driver, NULL };
137         o->driver = list;
138         if (parent) {
139                 c3object_array_add(&parent->objects, o);
140                 o->context = parent->context;
141         }
142         return o;
143 }
144
145 c3object_p
146 c3object_new(
147                 c3object_p o /* = NULL */)
148 {
149         c3object_p res = malloc(sizeof(*o));
150         return c3object_init(res, o);
151 }
152
153 void
154 c3object_clear(
155                 c3object_p o)
156 {
157         C3_DRIVER(o, clear);
158 }
159
160 void
161 c3object_dispose(
162                 c3object_p o)
163 {
164         c3object_clear(o);
165         C3_DRIVER(o, dispose);
166 }
167
168 void
169 c3object_set_dirty(
170                 c3object_p o,
171                 bool dirty)
172 {
173         if (dirty) {
174                 while (o) {
175                         o->dirty = true;
176                         o = o->parent;
177                 }
178         } else {
179                 for (int oi = 0; oi < o->objects.count; oi++)
180                         if (o->objects.e[oi]->dirty)
181                                 c3object_set_dirty(o->objects.e[oi], false);
182                 o->dirty = false;
183         }
184 }
185
186 void
187 c3object_add_object(
188                 c3object_p o,
189                 c3object_p sub)
190 {
191         if (sub->parent == o)
192                 return;
193         if (sub->parent) {
194                 for (int oi = 0; oi < sub->parent->objects.count; oi++) {
195                         if (sub->parent->objects.e[oi] == sub) {
196                                 c3object_array_delete(&sub->parent->objects, oi, 1);
197                                 c3object_set_dirty(sub->parent, true);
198                                 break;
199                         }
200                 }
201                 sub->parent = NULL;
202         }
203         sub->parent = o;
204         if (o) {
205                 c3object_array_add(&o->objects, sub);
206                 c3object_set_dirty(o, true);
207         }
208 }
209
210 void
211 c3object_add_geometry(
212                 c3object_p o,
213                 c3geometry_p g)
214 {
215         if (g->object == o)
216                 return;
217         if (g->object) {
218                 for (int oi = 0; oi < g->object->geometry.count; oi++) {
219                         if (g->object->geometry.e[oi] == g) {
220                                 c3geometry_array_delete(&g->object->geometry, oi, 1);
221                                 c3object_set_dirty(g->object, true);
222                                 break;
223                         }
224                 }
225                 g->object = NULL;
226         }
227         g->object = o;
228         if (o) {
229                 c3geometry_array_add(&o->geometry, g);
230                 c3object_set_dirty(o, true);
231         }
232 }
233
234 void
235 c3object_get_geometry(
236                 c3object_p o,
237                 c3geometry_array_p array )
238 {
239         C3_DRIVER(o, get_geometry, array);
240 }
241
242 void
243 c3object_project(
244                 c3object_p o,
245                 const c3mat4p m)
246 {
247         C3_DRIVER(o, project, m);
248 }