Creating a BGE staging branch.
[blender.git] / intern / cycles / render / curves.cpp
1 /*
2  * Copyright 2011, Blender Foundation.
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
19 #include "device.h"
20 #include "curves.h"
21 #include "mesh.h"
22 #include "object.h"
23 #include "scene.h"
24
25 #include "util_foreach.h"
26 #include "util_map.h"
27 #include "util_progress.h"
28 #include "util_vector.h"
29
30 CCL_NAMESPACE_BEGIN
31
32 /* Curve functions */
33
34 void curvebounds(float *lower, float *upper, float3 *p, int dim)
35 {
36         float *p0 = &p[0].x;
37         float *p1 = &p[1].x;
38         float *p2 = &p[2].x;
39         float *p3 = &p[3].x;
40         float fc = 0.71f;
41         float curve_coef[4];
42         curve_coef[0] = p1[dim];
43         curve_coef[1] = -fc*p0[dim] + fc*p2[dim];
44         curve_coef[2] = 2.0f * fc * p0[dim] + (fc - 3.0f) * p1[dim] + (3.0f - 2.0f * fc) * p2[dim] - fc * p3[dim];
45         curve_coef[3] = -fc * p0[dim] + (2.0f - fc) * p1[dim] + (fc - 2.0f) * p2[dim] + fc * p3[dim];
46         float discroot = curve_coef[2] * curve_coef[2] - 3 * curve_coef[3] * curve_coef[1];
47         float ta = -1.0f;
48         float tb = -1.0f;
49         if(discroot >= 0) {
50                 discroot = sqrt(discroot);
51                 ta = (-curve_coef[2] - discroot) / (3 * curve_coef[3]);
52                 tb = (-curve_coef[2] + discroot) / (3 * curve_coef[3]);
53                 ta = (ta > 1.0f || ta < 0.0f) ? -1.0f : ta;
54                 tb = (tb > 1.0f || tb < 0.0f) ? -1.0f : tb;
55         }
56
57         *upper = max(p1[dim],p2[dim]);
58         *lower = min(p1[dim],p2[dim]);
59         float exa = p1[dim];
60         float exb = p2[dim];
61         float t2;
62         float t3;
63         if(ta >= 0.0f) {
64                 t2 = ta * ta;
65                 t3 = t2 * ta;
66                 exa = curve_coef[3] * t3 + curve_coef[2] * t2 + curve_coef[1] * ta + curve_coef[0];
67         }
68         if(tb >= 0.0f) {
69                 t2 = tb * tb;
70                 t3 = t2 * tb;
71                 exb = curve_coef[3] * t3 + curve_coef[2] * t2 + curve_coef[1] * tb + curve_coef[0];
72         }
73         *upper = max(*upper, max(exa,exb));
74         *lower = min(*lower, min(exa,exb));
75         
76 }
77
78 /* Hair System Manager */
79
80 CurveSystemManager::CurveSystemManager()
81 {
82         primitive = CURVE_LINE_SEGMENTS;
83         line_method = CURVE_CORRECTED;
84         interpolation = CURVE_CARDINAL;
85         triangle_method = CURVE_CAMERA_TRIANGLES;
86         resolution = 3;
87         segments = 1;
88         subdivisions = 3;
89
90         normalmix = 1.0f;
91         encasing_ratio = 1.01f;
92         minimum_width = 0.0f;
93         maximum_width = 0.0f;
94
95         use_curves = true;
96         use_smooth = true;
97         use_parents = false;
98         use_encasing = true;
99         use_backfacing = false;
100         use_joined = false;
101         use_tangent_normal = false;
102         use_tangent_normal_geometry = false;
103         use_tangent_normal_correction = false;
104
105         need_update = true;
106         need_mesh_update = false;
107 }
108
109 CurveSystemManager::~CurveSystemManager()
110 {
111 }
112
113 void CurveSystemManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
114 {
115         if(!need_update)
116                 return;
117
118         device_free(device, dscene);
119
120         progress.set_status("Updating Hair settings", "Copying Hair settings to device");
121
122         KernelCurves *kcurve= &dscene->data.curve_kernel_data;
123
124         kcurve->curveflags = 0;
125
126         if(use_curves) {
127                 if(primitive == CURVE_SEGMENTS || primitive == CURVE_RIBBONS)
128                         kcurve->curveflags |= CURVE_KN_INTERPOLATE;
129                 if(primitive == CURVE_RIBBONS)
130                         kcurve->curveflags |= CURVE_KN_RIBBONS;
131
132                 if(line_method == CURVE_ACCURATE)
133                         kcurve->curveflags |= CURVE_KN_ACCURATE;
134                 if(line_method == CURVE_CORRECTED)
135                         kcurve->curveflags |= CURVE_KN_INTERSECTCORRECTION;
136                 if(line_method == CURVE_POSTCORRECTED)
137                         kcurve->curveflags |= CURVE_KN_POSTINTERSECTCORRECTION;
138
139                 if(use_tangent_normal)
140                         kcurve->curveflags |= CURVE_KN_TANGENTGNORMAL;
141                 if(use_tangent_normal_correction)
142                         kcurve->curveflags |= CURVE_KN_NORMALCORRECTION;
143                 if(use_tangent_normal_geometry)
144                         kcurve->curveflags |= CURVE_KN_TRUETANGENTGNORMAL;
145                 if(use_joined)
146                         kcurve->curveflags |= CURVE_KN_CURVEDATA;
147                 if(use_backfacing)
148                         kcurve->curveflags |= CURVE_KN_BACKFACING;
149                 if(use_encasing)
150                         kcurve->curveflags |= CURVE_KN_ENCLOSEFILTER;
151
152                 kcurve->normalmix = normalmix;
153                 kcurve->encasing_ratio = encasing_ratio;
154                 kcurve->minimum_width = minimum_width;
155                 kcurve->maximum_width = maximum_width;
156                 kcurve->subdivisions = subdivisions;
157         }
158
159         if(progress.get_cancel()) return;
160
161         need_update = false;
162 }
163
164 void CurveSystemManager::device_free(Device *device, DeviceScene *dscene)
165 {
166
167 }
168
169 bool CurveSystemManager::modified(const CurveSystemManager& CurveSystemManager)
170 {
171         return !(line_method == CurveSystemManager.line_method &&
172                 interpolation == CurveSystemManager.interpolation &&
173                 primitive == CurveSystemManager.primitive &&
174                 use_encasing == CurveSystemManager.use_encasing &&
175                 use_tangent_normal == CurveSystemManager.use_tangent_normal &&
176                 use_tangent_normal_correction == CurveSystemManager.use_tangent_normal_correction &&
177                 use_tangent_normal_geometry == CurveSystemManager.use_tangent_normal_geometry &&
178                 encasing_ratio == CurveSystemManager.encasing_ratio &&
179                 minimum_width == CurveSystemManager.minimum_width &&
180                 maximum_width == CurveSystemManager.maximum_width &&
181                 use_backfacing == CurveSystemManager.use_backfacing &&
182                 normalmix == CurveSystemManager.normalmix &&
183                 use_smooth == CurveSystemManager.use_smooth &&
184                 triangle_method == CurveSystemManager.triangle_method &&
185                 resolution == CurveSystemManager.resolution &&
186                 use_curves == CurveSystemManager.use_curves &&
187                 use_joined == CurveSystemManager.use_joined &&
188                 segments == CurveSystemManager.segments &&
189                 use_parents == CurveSystemManager.use_parents &&
190                 subdivisions == CurveSystemManager.subdivisions);
191 }
192
193 bool CurveSystemManager::modified_mesh(const CurveSystemManager& CurveSystemManager)
194 {
195         return !(primitive == CurveSystemManager.primitive &&
196                 interpolation == CurveSystemManager.interpolation &&
197                 use_parents == CurveSystemManager.use_parents &&
198                 use_smooth == CurveSystemManager.use_smooth &&
199                 triangle_method == CurveSystemManager.triangle_method &&
200                 resolution == CurveSystemManager.resolution &&
201                 use_curves == CurveSystemManager.use_curves &&
202                 use_joined == CurveSystemManager.use_joined &&
203                 segments == CurveSystemManager.segments);
204 }
205
206 void CurveSystemManager::tag_update(Scene *scene)
207 {
208         need_update = true;
209 }
210
211 void CurveSystemManager::tag_update_mesh()
212 {
213         need_mesh_update = true;
214 }
215 CCL_NAMESPACE_END
216