And another fix for r45669 to have dualcon compile on windows...
[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 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         int getMemory() { return sizeof(DualConInputReader); }
185 };
186
187 void *dualcon(const DualConInput *input_mesh,
188                           /* callbacks for output */
189                           DualConAllocOutput alloc_output,
190                           DualConAddVert add_vert,
191                           DualConAddQuad add_quad,
192                                          
193                           DualConFlags flags,
194                           DualConMode mode,
195                           float threshold,
196                           float hermite_num,
197                           float scale,
198                           int depth)
199 {
200         DualConInputReader r(input_mesh, scale);
201         Octree o(&r, alloc_output, add_vert, add_quad,
202                          flags, mode, depth, threshold, hermite_num);
203         o.scanConvert();
204         return o.getOutputMesh();
205 }