d710ada48bcd29e190d1863aff0cba6b3982224c
[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
30 void veccopy(float dst[3], const float src[3])
31 {
32         dst[0] = src[0];
33         dst[1] = src[1];
34         dst[2] = src[2];
35 }
36
37 #define GET_FACE(_mesh, _n) \
38         (*(DualConFaces)(((char*)(_mesh)->faces) + ((_n) * (_mesh)->face_stride)))
39
40 #define GET_CO(_mesh, _n) \
41         (*(DualConCo)(((char*)(_mesh)->co) + ((_n) * (_mesh)->co_stride)))
42
43 class DualConInputReader : public ModelReader
44 {
45 private:
46         const DualConInput *input_mesh;
47         int tottri, curface, offset;
48         float min[3], max[3], maxsize;
49         float scale;
50 public:
51         DualConInputReader(const DualConInput *mesh, float _scale)
52         : input_mesh(mesh), scale(_scale)
53         {
54                 reset();
55         }
56
57         void reset()
58         {
59                 tottri = 0;
60                 curface = 0;
61                 offset = 0;
62                 maxsize = 0;
63
64                 /* initialize tottri */
65                 for(int i = 0; i < input_mesh->totface; i++)
66                         tottri += GET_FACE(input_mesh, i)[3] ? 2 : 1;
67
68                 veccopy(min, input_mesh->min);
69                 veccopy(max, input_mesh->max);
70
71                 /* initialize maxsize */
72                 for(int i = 0; i < 3; i++) {
73                         float d = max[i] - min[i];
74                         if(d > maxsize)
75                                 maxsize = d;
76                 }
77
78                 /* redo the bounds */
79                 for(int i = 0; i < 3; i++)
80                 {
81                         min[i] = (max[i] + min[i]) / 2 - maxsize / 2;
82                         max[i] = (max[i] + min[i]) / 2 + maxsize / 2;
83                 }
84
85                 for(int i = 0; i < 3; i++)
86                         min[i] -= maxsize * (1 / scale - 1) / 2;
87                 maxsize *= 1 / scale;
88         }
89
90         Triangle* getNextTriangle()
91         {
92                 if(curface == input_mesh->totface)
93                         return 0;
94
95                 Triangle* t = new Triangle();
96                 
97                 unsigned int *f = GET_FACE(input_mesh, curface);
98                 if(offset == 0) {
99                         veccopy(t->vt[0], GET_CO(input_mesh, f[0]));
100                         veccopy(t->vt[1], GET_CO(input_mesh, f[1]));
101                         veccopy(t->vt[2], GET_CO(input_mesh, f[2]));
102                 }
103                 else {
104                         veccopy(t->vt[0], GET_CO(input_mesh, f[2]));
105                         veccopy(t->vt[1], GET_CO(input_mesh, f[3]));
106                         veccopy(t->vt[2], GET_CO(input_mesh, f[0]));
107                 }
108
109                 if(offset == 0 && f[3])
110                         offset++;
111                 else {
112                         offset = 0;
113                         curface++;
114                 }
115
116                 return t;
117         }
118
119         int getNextTriangle(int t[3])
120         {
121                 if(curface == input_mesh->totface)
122                         return 0;
123                 
124                 unsigned int *f = GET_FACE(input_mesh, curface);
125                 if(offset == 0) {
126                         t[0] = f[0];
127                         t[1] = f[1];
128                         t[2] = f[2];
129                 }
130                 else {
131                         t[0] = f[2];
132                         t[1] = f[3];
133                         t[2] = f[0];
134                 }
135
136                 if(offset == 0 && f[3])
137                         offset++;
138                 else {
139                         offset = 0;
140                         curface++;
141                 }
142
143                 return 1;
144         }
145
146         int getNumTriangles()
147         {
148                 return tottri;
149         }
150
151         int getNumVertices()
152         {
153                 return input_mesh->totco;
154         }
155
156         float getBoundingBox(float origin[3])
157         {
158                 veccopy(origin, min);
159                 return maxsize ;
160         }
161
162         /* output */
163         void getNextVertex(float v[3])
164         {
165                 /* not used */
166         }
167
168         /* stubs */
169         void printInfo() {}
170         int getMemory() { return sizeof(DualConInputReader); }
171 };
172
173 void *dualcon(const DualConInput *input_mesh,
174                           /* callbacks for output */
175                           DualConAllocOutput alloc_output,
176                           DualConAddVert add_vert,
177                           DualConAddQuad add_quad,
178                                          
179                           DualConFlags flags,
180                           DualConMode mode,
181                           float threshold,
182                           float hermite_num,
183                           float scale,
184                           int depth)
185 {
186         DualConInputReader r(input_mesh, scale);
187         Octree o(&r, alloc_output, add_vert, add_quad,
188                          flags, mode, depth, threshold, hermite_num);
189         o.scanConvert();
190         return o.getOutputMesh();
191 }