1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
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.
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/>.
19 #include "nel/3d/bezier_patch.h"
21 using namespace NLMISC
;
29 // ***************************************************************************
30 void CBezierPatch::make(CVector vertices
[4], CVector normals
[4])
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};
37 Vertices
[i
]= vertices
[i
];
42 CVector tgt
= Vertices
[ends
[i
]] - Vertices
[starts
[i
]];
44 J
= normals
[starts
[i
]];
48 // Yes, we store tangents as position, not vectors...
49 Tangents
[i
]= Vertices
[starts
[i
]] + K
*tgt
.norm()/3;
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
)
74 Vertices
[i
]= m
*Vertices
[i
];
76 Tangents
[i
]= m
*Tangents
[i
];
78 Interiors
[i
]= m
*Interiors
[i
];
81 // ***************************************************************************
82 static inline void mulAdd(CVector
&tgt
, const CVector
&src
, float f
)
89 // ***************************************************************************
90 static inline void mulAddD(CVectorD
&tgt
, const CVector
&src
, double f
)
97 // ***************************************************************************
98 CVector
CBezierPatch::eval(float ps
, float pt
) const
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
;
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
;
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
);
138 // ***************************************************************************
139 CVectorD
CBezierPatch::evalDouble(double ps
, double pt
) const
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
;
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
);
179 // ***************************************************************************
180 CVector
CBezierPatch::evalNormal(float ps
, float pt
) const
187 float ps1
= 1.0f
- ps
;
188 float ps12
= ps1
* ps1
;
190 float pt1
= 1.0f
- pt
;
191 float pt12
= pt1
* pt1
;
197 s1
= 9*ps2
+ 3 -12*ps
;
202 t1
= 3.0f
* pt
* pt12
;
203 t2
= 3.0f
* pt2
* pt1
;
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
);
228 s1
= 3.0f
* ps
* ps12
;
229 s2
= 3.0f
* ps2
* ps1
;
233 t1
= 9*pt2
+ 3 -12*pt
;
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
;
261 // ***************************************************************************
262 CVector
CBezierPatch::evalTangentS(float ps
, float pt
) const
269 float ps1
= 1.0f
- ps
;
270 float ps12
= ps1
* ps1
;
272 float pt1
= 1.0f
- pt
;
273 float pt12
= pt1
* pt1
;
279 s1
= 9*ps2
+ 3 -12*ps
;
284 t1
= 3.0f
* pt
* pt12
;
285 t2
= 3.0f
* pt2
* pt1
;
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
318 float ps1
= 1.0f
- ps
;
319 float ps12
= ps1
* ps1
;
321 float pt1
= 1.0f
- pt
;
322 float pt12
= pt1
* pt1
;
328 s1
= 3.0f
* ps
* ps12
;
329 s2
= 3.0f
* ps2
* ps1
;
333 t1
= 9*pt2
+ 3 -12*pt
;
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
)
364 // Subdivide the 2 curves.
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]);
392 for(sint i
=0;i
<4;i
++)
393 curveT
[i
].subdivide(curveTLeft
[i
], curveTRight
[i
], s
);
395 // Setup bezier patchs.
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]);
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]);
422 for(sint i
=0;i
<4;i
++)
423 curveS
[i
].subdivide(curveSTop
[i
], curveSBottom
[i
], t
);
425 // Setup bezier patchs.
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]);
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]);