Merge branch 'ryzom/ark-features' into main/gingo-test
[ryzomcore.git] / nel / src / 3d / bezier_patch.cpp
blob099a532d240346600cc54c1962c3372c6e1fca63
1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as
6 // published by the Free Software Foundation, either version 3 of the
7 // 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 Affero General Public License for more details.
14 // You should have received a copy of the GNU Affero General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
17 #include "std3d.h"
19 #include "nel/3d/bezier_patch.h"
21 using namespace NLMISC;
23 #ifdef DEBUG_NEW
24 #define new DEBUG_NEW
25 #endif
27 namespace NL3D {
29 // ***************************************************************************
30 void CBezierPatch::make(CVector vertices[4], CVector normals[4])
32 sint i;
33 static sint starts[8]= {0,1, 1,2, 2,3, 3,0};
34 static sint ends[8]= {1,0, 2,1, 3,2, 0,3};
36 for(i=0;i<4;i++)
37 Vertices[i]= vertices[i];
39 // For all tangents.
40 for(i=0;i<8;i++)
42 CVector tgt= Vertices[ends[i]] - Vertices[starts[i]];
43 CVector I,J,K;
44 J= normals[starts[i]];
45 I= J^tgt;
46 K= I^J;
47 K.normalize();
48 // Yes, we store tangents as position, not vectors...
49 Tangents[i]= Vertices[starts[i]] + K*tgt.norm()/3;
52 makeInteriors();
55 // ***************************************************************************
56 void CBezierPatch::makeInteriors()
58 CVector &a = Vertices[0];
59 CVector &b = Vertices[1];
60 CVector &c = Vertices[2];
61 CVector &d = Vertices[3];
62 Interiors[0] = Tangents[7] + Tangents[0] - a;
63 Interiors[1] = Tangents[1] + Tangents[2] - b;
64 Interiors[2] = Tangents[3] + Tangents[4] - c;
65 Interiors[3] = Tangents[5] + Tangents[6] - d;
68 // ***************************************************************************
69 void CBezierPatch::applyMatrix(const CMatrix &m)
71 sint i;
73 for(i=0;i<4;i++)
74 Vertices[i]= m*Vertices[i];
75 for(i=0;i<8;i++)
76 Tangents[i]= m*Tangents[i];
77 for(i=0;i<4;i++)
78 Interiors[i]= m*Interiors[i];
81 // ***************************************************************************
82 static inline void mulAdd(CVector &tgt, const CVector &src, float f)
84 tgt.x+= src.x*f;
85 tgt.y+= src.y*f;
86 tgt.z+= src.z*f;
89 // ***************************************************************************
90 static inline void mulAddD(CVectorD &tgt, const CVector &src, double f)
92 tgt.x+= src.x*f;
93 tgt.y+= src.y*f;
94 tgt.z+= src.z*f;
97 // ***************************************************************************
98 CVector CBezierPatch::eval(float ps, float pt) const
100 CVector p;
102 float ps2 = ps * ps;
103 float ps1 = 1.0f - ps;
104 float ps12 = ps1 * ps1;
105 float s0 = ps12 * ps1;
106 float s1 = 3.0f * ps * ps12;
107 float s2 = 3.0f * ps2 * ps1;
108 float s3 = ps2 * ps;
109 float pt2 = pt * pt;
110 float pt1 = 1.0f - pt;
111 float pt12 = pt1 * pt1;
112 float t0 = pt12 * pt1;
113 float t1 = 3.0f * pt * pt12;
114 float t2 = 3.0f * pt2 * pt1;
115 float t3 = pt2 * pt;
117 p.set(0,0,0);
118 mulAdd(p, Vertices[0] , s0 * t0);
119 mulAdd(p, Tangents[7] , s1 * t0);
120 mulAdd(p, Tangents[6] , s2 * t0);
121 mulAdd(p, Vertices[3] , s3 * t0);
122 mulAdd(p, Tangents[0] , s0 * t1);
123 mulAdd(p, Interiors[0], s1 * t1);
124 mulAdd(p, Interiors[3], s2 * t1);
125 mulAdd(p, Tangents[5] , s3 * t1);
126 mulAdd(p, Tangents[1] , s0 * t2);
127 mulAdd(p, Interiors[1], s1 * t2);
128 mulAdd(p, Interiors[2], s2 * t2);
129 mulAdd(p, Tangents[4] , s3 * t2);
130 mulAdd(p, Vertices[1] , s0 * t3);
131 mulAdd(p, Tangents[2] , s1 * t3);
132 mulAdd(p, Tangents[3] , s2 * t3);
133 mulAdd(p, Vertices[2] , s3 * t3);
135 return p;
138 // ***************************************************************************
139 CVectorD CBezierPatch::evalDouble(double ps, double pt) const
141 CVectorD p;
143 double ps2 = ps * ps;
144 double ps1 = 1.0f - ps;
145 double ps12 = ps1 * ps1;
146 double s0 = ps12 * ps1;
147 double s1 = 3.0f * ps * ps12;
148 double s2 = 3.0f * ps2 * ps1;
149 double s3 = ps2 * ps;
150 double pt2 = pt * pt;
151 double pt1 = 1.0f - pt;
152 double pt12 = pt1 * pt1;
153 double t0 = pt12 * pt1;
154 double t1 = 3.0f * pt * pt12;
155 double t2 = 3.0f * pt2 * pt1;
156 double t3 = pt2 * pt;
158 p.set(0,0,0);
159 mulAddD(p, Vertices[0] , s0 * t0);
160 mulAddD(p, Tangents[7] , s1 * t0);
161 mulAddD(p, Tangents[6] , s2 * t0);
162 mulAddD(p, Vertices[3] , s3 * t0);
163 mulAddD(p, Tangents[0] , s0 * t1);
164 mulAddD(p, Interiors[0], s1 * t1);
165 mulAddD(p, Interiors[3], s2 * t1);
166 mulAddD(p, Tangents[5] , s3 * t1);
167 mulAddD(p, Tangents[1] , s0 * t2);
168 mulAddD(p, Interiors[1], s1 * t2);
169 mulAddD(p, Interiors[2], s2 * t2);
170 mulAddD(p, Tangents[4] , s3 * t2);
171 mulAddD(p, Vertices[1] , s0 * t3);
172 mulAddD(p, Tangents[2] , s1 * t3);
173 mulAddD(p, Tangents[3] , s2 * t3);
174 mulAddD(p, Vertices[2] , s3 * t3);
176 return p;
179 // ***************************************************************************
180 CVector CBezierPatch::evalNormal(float ps, float pt) const
182 CVector tgtS, tgtT;
184 float s0,s1,s2,s3;
185 float t0,t1,t2,t3;
186 float ps2 = ps * ps;
187 float ps1 = 1.0f - ps;
188 float ps12 = ps1 * ps1;
189 float pt2 = pt * pt;
190 float pt1 = 1.0f - pt;
191 float pt12 = pt1 * pt1;
193 // Compute tangentS
194 //=================
195 // s/ds.
196 s0 = -3* ps12;
197 s1 = 9*ps2 + 3 -12*ps;
198 s2 =-9*ps2 + 6*ps ;
199 s3 = 3* ps2;
200 // t/dt.
201 t0 = pt12 * pt1;
202 t1 = 3.0f * pt * pt12;
203 t2 = 3.0f * pt2 * pt1;
204 t3 = pt2 * pt;
206 tgtS.set(0,0,0);
207 mulAdd(tgtS, Vertices[0] , s0 * t0);
208 mulAdd(tgtS, Tangents[7] , s1 * t0);
209 mulAdd(tgtS, Tangents[6] , s2 * t0);
210 mulAdd(tgtS, Vertices[3] , s3 * t0);
211 mulAdd(tgtS, Tangents[0] , s0 * t1);
212 mulAdd(tgtS, Interiors[0], s1 * t1);
213 mulAdd(tgtS, Interiors[3], s2 * t1);
214 mulAdd(tgtS, Tangents[5] , s3 * t1);
215 mulAdd(tgtS, Tangents[1] , s0 * t2);
216 mulAdd(tgtS, Interiors[1], s1 * t2);
217 mulAdd(tgtS, Interiors[2], s2 * t2);
218 mulAdd(tgtS, Tangents[4] , s3 * t2);
219 mulAdd(tgtS, Vertices[1] , s0 * t3);
220 mulAdd(tgtS, Tangents[2] , s1 * t3);
221 mulAdd(tgtS, Tangents[3] , s2 * t3);
222 mulAdd(tgtS, Vertices[2] , s3 * t3);
224 // Compute tangentT
225 //=================
226 // s/ds.
227 s0 = ps12 * ps1;
228 s1 = 3.0f * ps * ps12;
229 s2 = 3.0f * ps2 * ps1;
230 s3 = ps2 * ps;
231 // t/dt.
232 t0 = -3* pt12;
233 t1 = 9*pt2 + 3 -12*pt;
234 t2 =-9*pt2 + 6*pt ;
235 t3 = 3* pt2;
237 tgtT.set(0,0,0);
238 mulAdd(tgtT, Vertices[0] , s0 * t0);
239 mulAdd(tgtT, Tangents[7] , s1 * t0);
240 mulAdd(tgtT, Tangents[6] , s2 * t0);
241 mulAdd(tgtT, Vertices[3] , s3 * t0);
242 mulAdd(tgtT, Tangents[0] , s0 * t1);
243 mulAdd(tgtT, Interiors[0], s1 * t1);
244 mulAdd(tgtT, Interiors[3], s2 * t1);
245 mulAdd(tgtT, Tangents[5] , s3 * t1);
246 mulAdd(tgtT, Tangents[1] , s0 * t2);
247 mulAdd(tgtT, Interiors[1], s1 * t2);
248 mulAdd(tgtT, Interiors[2], s2 * t2);
249 mulAdd(tgtT, Tangents[4] , s3 * t2);
250 mulAdd(tgtT, Vertices[1] , s0 * t3);
251 mulAdd(tgtT, Tangents[2] , s1 * t3);
252 mulAdd(tgtT, Tangents[3] , s2 * t3);
253 mulAdd(tgtT, Vertices[2] , s3 * t3);
255 // Return the normal.
256 CVector norm= tgtT^tgtS;
257 norm.normalize();
258 return norm;
261 // ***************************************************************************
262 CVector CBezierPatch::evalTangentS(float ps, float pt) const
264 CVector tgtS;
266 float s0,s1,s2,s3;
267 float t0,t1,t2,t3;
268 float ps2 = ps * ps;
269 float ps1 = 1.0f - ps;
270 float ps12 = ps1 * ps1;
271 float pt2 = pt * pt;
272 float pt1 = 1.0f - pt;
273 float pt12 = pt1 * pt1;
275 // Compute tangentS
276 //=================
277 // s/ds.
278 s0 = -3* ps12;
279 s1 = 9*ps2 + 3 -12*ps;
280 s2 =-9*ps2 + 6*ps ;
281 s3 = 3* ps2;
282 // t/dt.
283 t0 = pt12 * pt1;
284 t1 = 3.0f * pt * pt12;
285 t2 = 3.0f * pt2 * pt1;
286 t3 = pt2 * pt;
288 tgtS.set(0,0,0);
289 mulAdd(tgtS, Vertices[0] , s0 * t0);
290 mulAdd(tgtS, Tangents[7] , s1 * t0);
291 mulAdd(tgtS, Tangents[6] , s2 * t0);
292 mulAdd(tgtS, Vertices[3] , s3 * t0);
293 mulAdd(tgtS, Tangents[0] , s0 * t1);
294 mulAdd(tgtS, Interiors[0], s1 * t1);
295 mulAdd(tgtS, Interiors[3], s2 * t1);
296 mulAdd(tgtS, Tangents[5] , s3 * t1);
297 mulAdd(tgtS, Tangents[1] , s0 * t2);
298 mulAdd(tgtS, Interiors[1], s1 * t2);
299 mulAdd(tgtS, Interiors[2], s2 * t2);
300 mulAdd(tgtS, Tangents[4] , s3 * t2);
301 mulAdd(tgtS, Vertices[1] , s0 * t3);
302 mulAdd(tgtS, Tangents[2] , s1 * t3);
303 mulAdd(tgtS, Tangents[3] , s2 * t3);
304 mulAdd(tgtS, Vertices[2] , s3 * t3);
306 // Return the tgt normalized
307 return tgtS.normed();
310 // ***************************************************************************
311 CVector CBezierPatch::evalTangentT(float ps, float pt) const
313 CVector tgtT;
315 float s0,s1,s2,s3;
316 float t0,t1,t2,t3;
317 float ps2 = ps * ps;
318 float ps1 = 1.0f - ps;
319 float ps12 = ps1 * ps1;
320 float pt2 = pt * pt;
321 float pt1 = 1.0f - pt;
322 float pt12 = pt1 * pt1;
324 // Compute tangentT
325 //=================
326 // s/ds.
327 s0 = ps12 * ps1;
328 s1 = 3.0f * ps * ps12;
329 s2 = 3.0f * ps2 * ps1;
330 s3 = ps2 * ps;
331 // t/dt.
332 t0 = -3* pt12;
333 t1 = 9*pt2 + 3 -12*pt;
334 t2 =-9*pt2 + 6*pt ;
335 t3 = 3* pt2;
337 tgtT.set(0,0,0);
338 mulAdd(tgtT, Vertices[0] , s0 * t0);
339 mulAdd(tgtT, Tangents[7] , s1 * t0);
340 mulAdd(tgtT, Tangents[6] , s2 * t0);
341 mulAdd(tgtT, Vertices[3] , s3 * t0);
342 mulAdd(tgtT, Tangents[0] , s0 * t1);
343 mulAdd(tgtT, Interiors[0], s1 * t1);
344 mulAdd(tgtT, Interiors[3], s2 * t1);
345 mulAdd(tgtT, Tangents[5] , s3 * t1);
346 mulAdd(tgtT, Tangents[1] , s0 * t2);
347 mulAdd(tgtT, Interiors[1], s1 * t2);
348 mulAdd(tgtT, Interiors[2], s2 * t2);
349 mulAdd(tgtT, Tangents[4] , s3 * t2);
350 mulAdd(tgtT, Vertices[1] , s0 * t3);
351 mulAdd(tgtT, Tangents[2] , s1 * t3);
352 mulAdd(tgtT, Tangents[3] , s2 * t3);
353 mulAdd(tgtT, Vertices[2] , s3 * t3);
355 // Return the tgt normalized
356 return tgtT.normed();
359 // ***************************************************************************
360 void CBezierPatch::CBezierCurve::subdivide(CBezierCurve &left, CBezierCurve &right, float t)
362 float t1= 1-t;
364 // Subdivide the 2 curves.
365 left.P0= P0;
366 right.P3= P3;
368 left.P1= t1*P0 + t*P1;
369 right.P2= t1*P2 + t*P3;
370 CVector middle12= t1*P1 + t*P2;
372 left.P2= t1*left.P1 + t*middle12;
373 right.P1= t1*middle12 + t*right.P2;
375 left.P3= right.P0= t1*left.P2 + t*right.P1;
378 // ***************************************************************************
379 void CBezierPatch::subdivideS(CBezierPatch &left, CBezierPatch &right, float s) const
381 CBezierCurve curveT[4];
382 CBezierCurve curveTLeft[4];
383 CBezierCurve curveTRight[4];
385 // Setup horizontal curves.
386 curveT[0].set(Vertices[0], Tangents[7] , Tangents[6] , Vertices[3]);
387 curveT[1].set(Tangents[0], Interiors[0], Interiors[3], Tangents[5]);
388 curveT[2].set(Tangents[1], Interiors[1], Interiors[2], Tangents[4]);
389 curveT[3].set(Vertices[1], Tangents[2] , Tangents[3] , Vertices[2]);
391 // Subdivide curves.
392 for(sint i=0;i<4;i++)
393 curveT[i].subdivide(curveTLeft[i], curveTRight[i], s);
395 // Setup bezier patchs.
396 // left.
397 curveTLeft[0].get(left.Vertices[0], left.Tangents[7] , left.Tangents[6] , left.Vertices[3]);
398 curveTLeft[1].get(left.Tangents[0], left.Interiors[0], left.Interiors[3], left.Tangents[5]);
399 curveTLeft[2].get(left.Tangents[1], left.Interiors[1], left.Interiors[2], left.Tangents[4]);
400 curveTLeft[3].get(left.Vertices[1], left.Tangents[2] , left.Tangents[3] , left.Vertices[2]);
401 // right.
402 curveTRight[0].get(right.Vertices[0], right.Tangents[7] , right.Tangents[6] , right.Vertices[3]);
403 curveTRight[1].get(right.Tangents[0], right.Interiors[0], right.Interiors[3], right.Tangents[5]);
404 curveTRight[2].get(right.Tangents[1], right.Interiors[1], right.Interiors[2], right.Tangents[4]);
405 curveTRight[3].get(right.Vertices[1], right.Tangents[2] , right.Tangents[3] , right.Vertices[2]);
408 // ***************************************************************************
409 void CBezierPatch::subdivideT(CBezierPatch &top, CBezierPatch &bottom, float t) const
411 CBezierCurve curveS[4];
412 CBezierCurve curveSTop[4];
413 CBezierCurve curveSBottom[4];
415 // Setup vertical curves.
416 curveS[0].set(Vertices[0], Tangents[0] , Tangents[1] , Vertices[1]);
417 curveS[1].set(Tangents[7], Interiors[0], Interiors[1], Tangents[2]);
418 curveS[2].set(Tangents[6], Interiors[3], Interiors[2], Tangents[3]);
419 curveS[3].set(Vertices[3], Tangents[5] , Tangents[4] , Vertices[2]);
421 // Subdivide curves.
422 for(sint i=0;i<4;i++)
423 curveS[i].subdivide(curveSTop[i], curveSBottom[i], t);
425 // Setup bezier patchs.
426 // top.
427 curveSTop[0].get(top.Vertices[0], top.Tangents[0] , top.Tangents[1] , top.Vertices[1]);
428 curveSTop[1].get(top.Tangents[7], top.Interiors[0], top.Interiors[1], top.Tangents[2]);
429 curveSTop[2].get(top.Tangents[6], top.Interiors[3], top.Interiors[2], top.Tangents[3]);
430 curveSTop[3].get(top.Vertices[3], top.Tangents[5] , top.Tangents[4] , top.Vertices[2]);
431 // bottom.
432 curveSBottom[0].get(bottom.Vertices[0], bottom.Tangents[0] , bottom.Tangents[1] , bottom.Vertices[1]);
433 curveSBottom[1].get(bottom.Tangents[7], bottom.Interiors[0], bottom.Interiors[1], bottom.Tangents[2]);
434 curveSBottom[2].get(bottom.Tangents[6], bottom.Interiors[3], bottom.Interiors[2], bottom.Tangents[3]);
435 curveSBottom[3].get(bottom.Vertices[3], bottom.Tangents[5] , bottom.Tangents[4] , bottom.Vertices[2]);
438 } // NL3D