svn merge ^/trunk/blender -r48592:HEAD
[blender.git] / intern / dualcon / intern / dualcon_c_api.cpp
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * Contributor(s): Nicholas Bishop
19  *
20  * ***** END GPL LICENSE BLOCK *****
21  */
22
23 #include <cassert>
24 #include "dualcon.h"
25 #include "ModelReader.h"
26 #include "octree.h"
27
28 #include <cstdio>
29 #include <float.h>
30
31 #if defined(_WIN32) && !defined(__MINGW32__)
32 #define isnan(n) _isnan(n)
33 #endif
34
35 static void veccopy(float dst[3], const float src[3])
36 {
37         dst[0] = src[0];
38         dst[1] = src[1];
39         dst[2] = src[2];
40 }
41
42 #define GET_FACE(_mesh, _n) \
43         (*(DualConFaces)(((char *)(_mesh)->faces) + ((_n) * (_mesh)->face_stride)))
44
45 #define GET_CO(_mesh, _n) \
46         (*(DualConCo)(((char *)(_mesh)->co) + ((_n) * (_mesh)->co_stride)))
47
48 class DualConInputReader : public ModelReader
49 {
50 private:
51 const DualConInput *input_mesh;
52 int tottri, curface, offset;
53 float min[3], max[3], maxsize;
54 float scale;
55 public:
56 DualConInputReader(const DualConInput *mesh, float _scale)
57         : input_mesh(mesh), scale(_scale)
58 {
59         reset();
60 }
61
62 void reset()
63 {
64         tottri = 0;
65         curface = 0;
66         offset = 0;
67         maxsize = 0;
68
69         /* initialize tottri */
70         for (int i = 0; i < input_mesh->totface; i++)
71                 tottri += GET_FACE(input_mesh, i)[3] ? 2 : 1;
72
73         veccopy(min, input_mesh->min);
74         veccopy(max, input_mesh->max);
75
76         /* initialize maxsize */
77         for (int i = 0; i < 3; i++) {
78                 float d = max[i] - min[i];
79                 if (d > maxsize)
80                         maxsize = d;
81         }
82
83         /* redo the bounds */
84         for (int i = 0; i < 3; i++)
85         {
86                 min[i] = (max[i] + min[i]) / 2 - maxsize / 2;
87                 max[i] = (max[i] + min[i]) / 2 + maxsize / 2;
88         }
89
90         for (int i = 0; i < 3; i++)
91                 min[i] -= maxsize * (1 / scale - 1) / 2;
92         maxsize *= 1 / scale;
93 }
94
95 Triangle *getNextTriangle()
96 {
97         if (curface == input_mesh->totface)
98                 return 0;
99
100         Triangle *t = new Triangle();
101
102         unsigned int *f = GET_FACE(input_mesh, curface);
103         if (offset == 0) {
104                 veccopy(t->vt[0], GET_CO(input_mesh, f[0]));
105                 veccopy(t->vt[1], GET_CO(input_mesh, f[1]));
106                 veccopy(t->vt[2], GET_CO(input_mesh, f[2]));
107         }
108         else {
109                 veccopy(t->vt[0], GET_CO(input_mesh, f[2]));
110                 veccopy(t->vt[1], GET_CO(input_mesh, f[3]));
111                 veccopy(t->vt[2], GET_CO(input_mesh, f[0]));
112         }
113
114         if (offset == 0 && f[3])
115                 offset++;
116         else {
117                 offset = 0;
118                 curface++;
119         }
120
121         /* remove triangle if it contains invalid coords */
122         for (int i = 0; i < 3; i++) {
123                 const float *co = t->vt[i];
124                 if (isnan(co[0]) || isnan(co[1]) || isnan(co[2])) {
125                         delete t;
126                         return getNextTriangle();
127                 }
128         }
129
130         return t;
131 }
132
133 int getNextTriangle(int t[3])
134 {
135         if (curface == input_mesh->totface)
136                 return 0;
137
138         unsigned int *f = GET_FACE(input_mesh, curface);
139         if (offset == 0) {
140                 t[0] = f[0];
141                 t[1] = f[1];
142                 t[2] = f[2];
143         }
144         else {
145                 t[0] = f[2];
146                 t[1] = f[3];
147                 t[2] = f[0];
148         }
149
150         if (offset == 0 && f[3])
151                 offset++;
152         else {
153                 offset = 0;
154                 curface++;
155         }
156
157         return 1;
158 }
159
160 int getNumTriangles()
161 {
162         return tottri;
163 }
164
165 int getNumVertices()
166 {
167         return input_mesh->totco;
168 }
169
170 float getBoundingBox(float origin[3])
171 {
172         veccopy(origin, min);
173         return maxsize;
174 }
175
176 /* output */
177 void getNextVertex(float v[3])
178 {
179         /* not used */
180 }
181
182 /* stubs */
183 void printInfo() {
184 }
185 int getMemory() {
186         return sizeof(DualConInputReader);
187 }
188 };
189
190 void *dualcon(const DualConInput *input_mesh,
191               /* callbacks for output */
192               DualConAllocOutput alloc_output,
193               DualConAddVert add_vert,
194               DualConAddQuad add_quad,
195
196               DualConFlags flags,
197               DualConMode mode,
198               float threshold,
199               float hermite_num,
200               float scale,
201               int depth)
202 {
203         DualConInputReader r(input_mesh, scale);
204         Octree o(&r, alloc_output, add_vert, add_quad,
205                  flags, mode, depth, threshold, hermite_num);
206         o.scanConvert();
207         return o.getOutputMesh();
208 }