1 //******************************************************************************
2 ///
3 /// @file core/shape/bezier.cpp
4 ///
5 /// Implementation of the Bezier bicubic patch geometric primitive.
6 ///
7 /// @author Alexander Enzmann
8 ///
9 /// @copyright
10 /// @parblock
11 ///
12 /// Persistence of Vision Ray Tracer ('POV-Ray') version 3.8.
13 /// Copyright 1991-2018 Persistence of Vision Raytracer Pty. Ltd.
14 ///
15 /// POV-Ray is free software: you can redistribute it and/or modify
16 /// it under the terms of the GNU Affero General Public License as
17 /// published by the Free Software Foundation, either version 3 of the
18 /// License, or (at your option) any later version.
19 ///
20 /// POV-Ray is distributed in the hope that it will be useful,
21 /// but WITHOUT ANY WARRANTY; without even the implied warranty of
22 /// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 /// GNU Affero General Public License for more details.
24 ///
25 /// You should have received a copy of the GNU Affero General Public License
26 /// along with this program. If not, see <http://www.gnu.org/licenses/>.
27 ///
28 /// ----------------------------------------------------------------------------
29 ///
30 /// POV-Ray is based on the popular DKB raytracer version 2.12.
31 /// DKBTrace was originally written by David K. Buck.
32 /// DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
33 ///
34 /// @endparblock
35 ///
36 //******************************************************************************
37
38 // Unit header file must be the first file included within POV-Ray *.cpp files (pulls in config)
39 #include "core/shape/bezier.h"
40
41 #include <algorithm>
42
43 #include "base/pov_err.h"
44
45 #include "core/math/matrix.h"
46 #include "core/render/ray.h"
47 #include "core/scene/tracethreaddata.h"
48
49 // this must be the last file included
50 #include "base/povdebug.h"
51
52 namespace pov
53 {
54
55 /*****************************************************************************
56 * Local preprocessor defines
57 ******************************************************************************/
58
59 const DBL BEZIER_EPSILON = 1.0e-10;
60 const DBL BEZIER_TOLERANCE = 1.0e-5;
61
62 #define BEZIER_INTERIOR_NODE 0
63 #define BEZIER_LEAF_NODE 1
64
65
66 /*****************************************************************************
67 *
68 * FUNCTION
69 *
70 * create_new_bezier_node
71 *
72 * INPUT
73 *
74 * OUTPUT
75 *
76 * RETURNS
77 *
78 * AUTHOR
79 *
80 * Alexander Enzmann
81 *
82 * DESCRIPTION
83 *
84 * -
85 *
86 * CHANGES
87 *
88 * -
89 *
90 ******************************************************************************/
91
create_new_bezier_node()92 BEZIER_NODE *BicubicPatch::create_new_bezier_node()
93 {
94 BEZIER_NODE *Node = reinterpret_cast<BEZIER_NODE *>(POV_MALLOC(sizeof(BEZIER_NODE), "bezier node"));
95
96 Node->Data_Ptr = nullptr;
97
98 return (Node);
99 }
100
101
102
103 /*****************************************************************************
104 *
105 * FUNCTION
106 *
107 * create_bezier_vertex_block
108 *
109 * INPUT
110 *
111 * OUTPUT
112 *
113 * RETURNS
114 *
115 * AUTHOR
116 *
117 * Alexander Enzmann
118 *
119 * DESCRIPTION
120 *
121 * -
122 *
123 * CHANGES
124 *
125 * -
126 *
127 ******************************************************************************/
128
create_bezier_vertex_block()129 BEZIER_VERTICES *BicubicPatch::create_bezier_vertex_block()
130 {
131 BEZIER_VERTICES *Vertices;
132
133 Vertices = reinterpret_cast<BEZIER_VERTICES *>(POV_MALLOC(sizeof(BEZIER_VERTICES), "bezier vertices"));
134
135 return (Vertices);
136 }
137
138
139
140 /*****************************************************************************
141 *
142 * FUNCTION
143 *
144 * create_bezier_child_block
145 *
146 * INPUT
147 *
148 * OUTPUT
149 *
150 * RETURNS
151 *
152 * AUTHOR
153 *
154 * Alexander Enzmann
155 *
156 * DESCRIPTION
157 *
158 * -
159 *
160 * CHANGES
161 *
162 * -
163 *
164 ******************************************************************************/
165
create_bezier_child_block()166 BEZIER_CHILDREN *BicubicPatch::create_bezier_child_block()
167 {
168 BEZIER_CHILDREN *Children;
169
170 Children = reinterpret_cast<BEZIER_CHILDREN *>(POV_MALLOC(sizeof(BEZIER_CHILDREN), "bezier children"));
171
172 return (Children);
173 }
174
175
176
177 /*****************************************************************************
178 *
179 * FUNCTION
180 *
181 * bezier_tree_builder
182 *
183 * INPUT
184 *
185 * OUTPUT
186 *
187 * RETURNS
188 *
189 * AUTHOR
190 *
191 * Alexander Enzmann
192 *
193 * DESCRIPTION
194 *
195 * -
196 *
197 * CHANGES
198 *
199 * -
200 *
201 ******************************************************************************/
202
bezier_tree_builder(const ControlPoints * Patch,DBL u0,DBL u1,DBL v0,DBL v1,int depth,int & max_depth_reached)203 BEZIER_NODE *BicubicPatch::bezier_tree_builder(const ControlPoints *Patch, DBL u0, DBL u1, DBL v0, DBL v1, int depth, int& max_depth_reached)
204 {
205 ControlPoints Lower_Left, Lower_Right;
206 ControlPoints Upper_Left, Upper_Right;
207 BEZIER_CHILDREN *Children;
208 BEZIER_VERTICES *Vertices;
209 BEZIER_NODE *Node = create_new_bezier_node();
210
211 if (depth > max_depth_reached)
212 {
213 max_depth_reached = depth;
214 }
215
216 /* Build the bounding sphere for this subpatch. */
217
218 bezier_bounding_sphere(Patch, Node->Center, &(Node->Radius_Squared));
219
220 /*
221 * If the patch is close to being flat, then just perform
222 * a ray-plane intersection test.
223 */
224
225 if (flat_enough(Patch))
226 {
227 /* The patch is now flat enough to simply store the corners. */
228
229 Node->Node_Type = BEZIER_LEAF_NODE;
230
231 Vertices = create_bezier_vertex_block();
232
233 Vertices->Vertices[0] = (*Patch)[0][0];
234 Vertices->Vertices[1] = (*Patch)[0][3];
235 Vertices->Vertices[2] = (*Patch)[3][3];
236 Vertices->Vertices[3] = (*Patch)[3][0];
237
238 Vertices->uvbnds[0] = u0;
239 Vertices->uvbnds[1] = u1;
240 Vertices->uvbnds[2] = v0;
241 Vertices->uvbnds[3] = v1;
242
243 Node->Data_Ptr = reinterpret_cast<void *>(Vertices);
244 }
245 else
246 {
247 if (depth >= U_Steps)
248 {
249 if (depth >= V_Steps)
250 {
251 /* We are at the max recursion depth. Just store corners. */
252
253 Node->Node_Type = BEZIER_LEAF_NODE;
254
255 Vertices = create_bezier_vertex_block();
256
257 Vertices->Vertices[0] = (*Patch)[0][0];
258 Vertices->Vertices[1] = (*Patch)[0][3];
259 Vertices->Vertices[2] = (*Patch)[3][3];
260 Vertices->Vertices[3] = (*Patch)[3][0];
261
262 Vertices->uvbnds[0] = u0;
263 Vertices->uvbnds[1] = u1;
264 Vertices->uvbnds[2] = v0;
265 Vertices->uvbnds[3] = v1;
266
267 Node->Count = 0;
268
269 Node->Data_Ptr = reinterpret_cast<void *>(Vertices);
270 }
271 else
272 {
273 bezier_split_up_down(Patch, &Lower_Left, &Upper_Left);
274
275 Node->Node_Type = BEZIER_INTERIOR_NODE;
276
277 Children = create_bezier_child_block();
278
279 Children->Children[0] = bezier_tree_builder(&Lower_Left, u0, u1, v0, (v0 + v1) / 2.0, depth + 1, max_depth_reached);
280 Children->Children[1] = bezier_tree_builder(&Upper_Left, u0, u1, (v0 + v1) / 2.0, v1, depth + 1, max_depth_reached);
281
282 Node->Count = 2;
283
284 Node->Data_Ptr = reinterpret_cast<void *>(Children);
285 }
286 }
287 else
288 {
289 if (depth >= V_Steps)
290 {
291 bezier_split_left_right(Patch, &Lower_Left, &Lower_Right);
292
293 Node->Node_Type = BEZIER_INTERIOR_NODE;
294
295 Children = create_bezier_child_block();
296
297 Children->Children[0] = bezier_tree_builder(&Lower_Left, u0, (u0 + u1) / 2.0, v0, v1, depth + 1, max_depth_reached);
298 Children->Children[1] = bezier_tree_builder(&Lower_Right, (u0 + u1) / 2.0, u1, v0, v1, depth + 1, max_depth_reached);
299
300 Node->Count = 2;
301
302 Node->Data_Ptr = reinterpret_cast<void *>(Children);
303 }
304 else
305 {
306 bezier_split_left_right(Patch, &Lower_Left, &Lower_Right);
307
308 bezier_split_up_down(&Lower_Left, &Lower_Left, &Upper_Left);
309
310 bezier_split_up_down(&Lower_Right, &Lower_Right, &Upper_Right);
311
312 Node->Node_Type = BEZIER_INTERIOR_NODE;
313
314 Children = create_bezier_child_block();
315
316 Children->Children[0] = bezier_tree_builder(&Lower_Left, u0, (u0 + u1) / 2.0, v0, (v0 + v1) / 2.0, depth + 1, max_depth_reached);
317 Children->Children[1] = bezier_tree_builder(&Upper_Left, u0, (u0 + u1) / 2.0, (v0 + v1) / 2.0, v1, depth + 1, max_depth_reached);
318 Children->Children[2] = bezier_tree_builder(&Lower_Right, (u0 + u1) / 2.0, u1, v0, (v0 + v1) / 2.0, depth + 1, max_depth_reached);
319 Children->Children[3] = bezier_tree_builder(&Upper_Right, (u0 + u1) / 2.0, u1, (v0 + v1) / 2.0, v1, depth + 1, max_depth_reached);
320
321 Node->Count = 4;
322
323 Node->Data_Ptr = reinterpret_cast<void *>(Children);
324 }
325 }
326 }
327
328 return (Node);
329 }
330
331
332
333 /*****************************************************************************
334 *
335 * FUNCTION
336 *
337 * bezier_value
338 *
339 * INPUT
340 *
341 * OUTPUT
342 *
343 * RETURNS
344 *
345 * AUTHOR
346 *
347 * Alexander Enzmann
348 *
349 * DESCRIPTION
350 *
351 * Determine the position and normal at a single coordinate
352 * point (u, v) on a Bezier patch.
353 *
354 * CHANGES
355 *
356 * -
357 *
358 ******************************************************************************/
359
bezier_value(const ControlPoints * cp,DBL u0,DBL v0,Vector3d & P,Vector3d & N)360 void BicubicPatch::bezier_value(const ControlPoints *cp, DBL u0, DBL v0, Vector3d& P, Vector3d& N)
361 {
362 const DBL C[] = { 1.0, 3.0, 3.0, 1.0 };
363 int i, j;
364 DBL c, t, ut, vt;
365 DBL u[4], uu[4], v[4], vv[4];
366 DBL du[4], duu[4], dv[4], dvv[4];
367 DBL squared_u1, squared_v1;
368 Vector3d U1, V1;
369
370 /* Calculate binomial coefficients times coordinate positions. */
371
372 u[0] = 1.0; uu[0] = 1.0; du[0] = 0.0; duu[0] = 0.0;
373 v[0] = 1.0; vv[0] = 1.0; dv[0] = 0.0; dvv[0] = 0.0;
374
375 for (i = 1; i < 4; i++)
376 {
377 u[i] = u[i - 1] * u0; uu[i] = uu[i - 1] * (1.0 - u0);
378 v[i] = v[i - 1] * v0; vv[i] = vv[i - 1] * (1.0 - v0);
379
380 du[i] = i * u[i - 1]; duu[i] = -i * uu[i - 1];
381 dv[i] = i * v[i - 1]; dvv[i] = -i * vv[i - 1];
382 }
383
384 /* Now evaluate position and tangents based on control points. */
385
386 P = Vector3d(0.0, 0.0, 0.0);
387 U1 = Vector3d(0.0, 0.0, 0.0);
388 V1 = Vector3d(0.0, 0.0, 0.0);
389
390 for (i = 0; i < 4; i++)
391 {
392 for (j = 0; j < 4; j++)
393 {
394 c = C[i] * C[j];
395
396 ut = u[i] * uu[3 - i];
397 vt = v[j] * vv[3 - j];
398
399 t = c * ut * vt;
400
401 P += t * (*cp)[i][j];
402
403 t = c * vt * (du[i] * uu[3 - i] + u[i] * duu[3 - i]);
404
405 U1 += t * (*cp)[i][j];
406
407 t = c * ut * (dv[j] * vv[3 - j] + v[j] * dvv[3 - j]);
408
409 V1 += t * (*cp)[i][j];
410 }
411 }
412
413 /* Make the normal from the cross product of the tangents. */
414
415 N = cross(U1, V1);
416
417 t = N.lengthSqr();
418
419 squared_u1 = U1.lengthSqr();
420 squared_v1 = V1.lengthSqr();
421 if (t > (BEZIER_EPSILON * squared_u1 * squared_v1))
422 {
423 t = 1.0 / sqrt(t);
424
425 N *= t;
426 }
427 else
428 {
429 N = Vector3d(1.0, 0.0, 0.0);
430 }
431 }
432
433
434
435 /*****************************************************************************
436 *
437 * FUNCTION
438 *
439 * subpatch_normal
440 *
441 * INPUT
442 *
443 * OUTPUT
444 *
445 * RETURNS
446 *
447 * AUTHOR
448 *
449 * Alexander Enzmann
450 *
451 * DESCRIPTION
452 *
453 * Calculate the normal to a subpatch (triangle) return the vector
454 * <1.0 0.0 0.0> if the triangle is degenerate.
455 *
456 * CHANGES
457 *
458 * -
459 *
460 ******************************************************************************/
461
subpatch_normal(const Vector3d & v1,const Vector3d & v2,const Vector3d & v3,Vector3d & Result,DBL * d)462 bool BicubicPatch::subpatch_normal(const Vector3d& v1, const Vector3d& v2, const Vector3d& v3, Vector3d& Result, DBL *d)
463 {
464 Vector3d V1, V2;
465 DBL squared_v1, squared_v2;
466 DBL Length;
467
468 V1 = v1 - v2;
469 V2 = v3 - v2;
470
471 Result = cross(V1, V2);
472
473 Length = Result.lengthSqr();
474 squared_v1 = V1.lengthSqr();
475 squared_v2 = V2.lengthSqr();
476
477 if (Length <= (BEZIER_EPSILON * squared_v1 * squared_v2))
478 {
479 Result = Vector3d(1.0, 0.0, 0.0);
480
481 *d = -v1[X];
482
483 return false;
484 }
485 else
486 {
487 Length = sqrt(Length);
488
489 Result /= Length;
490
491 *d = -dot(Result, v1);
492
493 return true;
494 }
495 }
496
497 /*****************************************************************************
498 *
499 * FUNCTION
500 *
501 * intersect_subpatch
502 *
503 * INPUT
504 *
505 * OUTPUT
506 *
507 * RETURNS
508 *
509 * AUTHOR
510 *
511 * Alexander Enzmann
512 *
513 * DESCRIPTION
514 *
515 * -
516 *
517 * CHANGES
518 *
519 * -
520 *
521 ******************************************************************************/
522
intersect_subpatch(const BasicRay & ray,const TripleVector3d & V1,const DBL uu[3],const DBL vv[3],DBL * Depth,Vector3d & P,Vector3d & N,DBL * u,DBL * v) const523 bool BicubicPatch::intersect_subpatch(const BasicRay &ray, const TripleVector3d& V1, const DBL uu[3], const DBL vv[3], DBL *Depth, Vector3d& P, Vector3d& N, DBL *u, DBL *v) const
524 {
525 DBL squared_b0, squared_b1;
526 DBL d, n, a, b, r;
527 Vector3d Q;
528 Vector3d T1;
529 Matrix3x3 B, IB;
530 Vector3d NN[3];
531
532 B[0] = V1[1] - V1[0];
533 B[1] = V1[2] - V1[0];
534
535 B[2] = cross(B[0], B[1]);
536
537 d = B[2].lengthSqr();
538
539 squared_b0 = B[0].lengthSqr();
540 squared_b1 = B[1].lengthSqr();
541 if (d <= (BEZIER_EPSILON * squared_b1 * squared_b0))
542 {
543 return false;
544 }
545
546 d = 1.0 / sqrt(d);
547
548 B[2] *= d;
549
550 /* Degenerate triangle. */
551
552 if (!MInvers3(B, IB))
553 {
554 return false;
555 }
556
557 d = dot(ray.Direction, IB[2]);
558
559 if (fabs(d) < BEZIER_EPSILON)
560 {
561 return false;
562 }
563
564 Q = V1[0] - ray.Origin;
565
566 n = dot(Q, IB[2]);
567
568 *Depth = n / d;
569
570 if (*Depth < BEZIER_TOLERANCE)
571 {
572 return false;
573 }
574
575 T1 = ray.Direction * (*Depth);
576
577 P = ray.Origin + T1;
578
579 Q = P - V1[0];
580
581 a = dot(Q, IB[0]);
582 b = dot(Q, IB[1]);
583
584 if ((a < 0.0) || (b < 0.0) || (a + b > 1.0))
585 {
586 return false;
587 }
588
589 r = 1.0 - a - b;
590
591 bezier_value(&Control_Points, uu[0], vv[0], T1, NN[0]);
592 bezier_value(&Control_Points, uu[1], vv[1], T1, NN[1]);
593 bezier_value(&Control_Points, uu[2], vv[2], T1, NN[2]);
594
595 N = NN[0] * r
596 + NN[1] * a
597 + NN[2] * b;
598
599 *u = r * uu[0] + a * uu[1] + b * uu[2];
600 *v = r * vv[0] + a * vv[1] + b * vv[2];
601
602 d = N.lengthSqr();
603
604 if (d > BEZIER_EPSILON)
605 {
606 d = 1.0 / sqrt(d);
607
608 N *= d;
609 }
610 else
611 {
612 N = Vector3d(1.0, 0.0, 0.0);
613 }
614
615 return true;
616 }
617
618
619
620 /*****************************************************************************
621 *
622 * FUNCTION
623 *
624 * spherical_bounds_check
625 *
626 * INPUT
627 *
628 * OUTPUT
629 *
630 * RETURNS
631 *
632 * AUTHOR
633 *
634 * Alexander Enzmann
635 *
636 * DESCRIPTION
637 *
638 * -
639 *
640 * CHANGES
641 *
642 * -
643 *
644 ******************************************************************************/
645
spherical_bounds_check(const BasicRay & ray,const Vector3d & center,DBL radiusSqr)646 bool BicubicPatch::spherical_bounds_check(const BasicRay &ray, const Vector3d& center, DBL radiusSqr)
647 {
648 Vector3d v;
649 DBL dist1, dist2;
650
651 v = center - ray.Origin;
652
653 dist1 = v.lengthSqr();
654
655 if (dist1 < radiusSqr)
656 {
657 /* ray starts inside sphere - assume it intersects. */
658
659 return true;
660 }
661 else
662 {
663 dist2 = dot(v, ray.Direction);
664
665 dist2 *= dist2;
666
667 if ((dist2 > 0) && ((dist1 - dist2) <= (radiusSqr + BEZIER_EPSILON) ))
668 {
669 return true;
670 }
671 }
672
673 return false;
674 }
675
676
677
678 /*****************************************************************************
679 *
680 * FUNCTION
681 *
682 * bezier_bounding_sphere
683 *
684 * INPUT
685 *
686 * OUTPUT
687 *
688 * RETURNS
689 *
690 * AUTHOR
691 *
692 * Alexander Enzmann
693 *
694 * DESCRIPTION
695 *
696 * Find a sphere that bounds all of the control points of a Bezier patch.
697 * The values returned are: the center of the bounding sphere, and the
698 * square of the radius of the bounding sphere.
699 *
700 * CHANGES
701 *
702 * -
703 *
704 ******************************************************************************/
705
bezier_bounding_sphere(const ControlPoints * Patch,Vector3d & center,DBL * radiusSqr)706 void BicubicPatch::bezier_bounding_sphere(const ControlPoints *Patch, Vector3d& center, DBL *radiusSqr)
707 {
708 int i, j;
709 DBL r0, r1;
710 Vector3d v0;
711
712 center = Vector3d(0.0);
713 for (i = 0; i < 4; i++)
714 {
715 for (j = 0; j < 4; j++)
716 {
717 center += (*Patch)[i][j];
718 }
719 }
720
721 center /= 16.0;
722
723 r0 = 0.0;
724
725 for (i = 0; i < 4; i++)
726 {
727 for (j = 0; j < 4; j++)
728 {
729 v0 = (*Patch)[i][j] - center;
730
731 r1 = v0.lengthSqr();
732
733 if (r1 > r0)
734 {
735 r0 = r1;
736 }
737 }
738 }
739
740 *radiusSqr = r0;
741 }
742
743
744
745 /*****************************************************************************
746 *
747 * FUNCTION
748 *
749 * Precompute_Patch_Values
750 *
751 * INPUT
752 *
753 * OUTPUT
754 *
755 * RETURNS
756 *
757 * AUTHOR
758 *
759 * Alexander Enzmann
760 *
761 * DESCRIPTION
762 *
763 * Precompute grid points and normals for a bezier patch.
764 *
765 * CHANGES
766 *
767 * -
768 *
769 ******************************************************************************/
770
Precompute_Patch_Values()771 void BicubicPatch::Precompute_Patch_Values()
772 {
773 int max_depth_reached = 0;
774
775 if (Patch_Type == 1)
776 {
777 if (Node_Tree != nullptr)
778 {
779 bezier_tree_deleter(Node_Tree);
780 }
781
782 Node_Tree = bezier_tree_builder(&Control_Points, 0.0, 1.0, 0.0, 1.0, 0, max_depth_reached);
783 }
784 }
785
786
787
788 /*****************************************************************************
789 *
790 * FUNCTION
791 *
792 * point_plane_distance
793 *
794 * INPUT
795 *
796 * OUTPUT
797 *
798 * RETURNS
799 *
800 * AUTHOR
801 *
802 * Alexander Enzmann
803 *
804 * DESCRIPTION
805 *
806 * Determine the distance from a point to a plane.
807 *
808 * CHANGES
809 *
810 * -
811 *
812 ******************************************************************************/
813
point_plane_distance(const Vector3d & p,const Vector3d & n,DBL d)814 DBL BicubicPatch::point_plane_distance(const Vector3d& p, const Vector3d& n, DBL d)
815 {
816 DBL temp1, temp2;
817
818 temp1 = dot(p, n);
819
820 temp1 += d;
821
822 temp2 = n.length();
823
824 if (fabs(temp2) < EPSILON)
825 {
826 return (0.0);
827 }
828
829 temp1 /= temp2;
830
831 return (temp1);
832 }
833
834
835
836 /*****************************************************************************
837 *
838 * FUNCTION
839 *
840 * bezier_subpatch_intersect
841 *
842 * INPUT
843 *
844 * OUTPUT
845 *
846 * RETURNS
847 *
848 * AUTHOR
849 *
850 * Alexander Enzmann
851 *
852 * DESCRIPTION
853 *
854 * -
855 *
856 * CHANGES
857 *
858 * -
859 *
860 ******************************************************************************/
861
bezier_subpatch_intersect(const BasicRay & ray,const ControlPoints * Patch,DBL u0,DBL u1,DBL v0,DBL v1,IStack & Depth_Stack,TraceThreadData * Thread)862 int BicubicPatch::bezier_subpatch_intersect(const BasicRay &ray, const ControlPoints *Patch, DBL u0, DBL u1, DBL v0, DBL v1, IStack& Depth_Stack, TraceThreadData *Thread)
863 {
864 int cnt = 0;
865 TripleVector3d V1;
866 DBL u, v, Depth;
867 DBL uu[3], vv[3];
868 Vector3d P, N;
869 Vector2d UV;
870 Vector2d uv_point, tpoint;
871
872 V1[0] = (*Patch)[0][0];
873 V1[1] = (*Patch)[0][3];
874 V1[2] = (*Patch)[3][3];
875
876 uu[0] = u0; uu[1] = u0; uu[2] = u1;
877 vv[0] = v0; vv[1] = v1; vv[2] = v1;
878
879 if (intersect_subpatch(ray, V1, uu, vv, &Depth, P, N, &u, &v))
880 {
881 if (Clip.empty() || Point_In_Clip(P, Clip, Thread))
882 {
883 /* transform current point from uv space to texture space */
884 uv_point[0] = v;
885 uv_point[1] = u;
886 Compute_Texture_UV(uv_point, ST, tpoint);
887
888 UV[U] = tpoint[0];
889 UV[V] = tpoint[1];
890 Depth_Stack->push(Intersection(Depth, P, N, UV, this));
891
892 cnt++;
893 }
894 }
895
896 V1[1] = V1[2];
897 V1[2] = (*Patch)[3][0];
898
899 uu[1] = uu[2]; uu[2] = u1;
900 vv[1] = vv[2]; vv[2] = v0;
901
902 if (intersect_subpatch(ray, V1, uu, vv, &Depth, P, N, &u, &v))
903 {
904 if (Clip.empty() || Point_In_Clip(P, Clip, Thread))
905 {
906 /* transform current point from uv space to texture space */
907 uv_point[0] = v;
908 uv_point[1] = u;
909 Compute_Texture_UV(uv_point, ST, tpoint);
910
911 UV[U] = tpoint[0];
912 UV[V] = tpoint[1];
913 Depth_Stack->push(Intersection(Depth, P, N, UV, this));
914
915 cnt++;
916 }
917 }
918
919 return (cnt);
920 }
921
922
923
924
925 /*****************************************************************************
926 *
927 * FUNCTION
928 *
929 * bezier_split_left_right
930 *
931 * INPUT
932 *
933 * OUTPUT
934 *
935 * RETURNS
936 *
937 * AUTHOR
938 *
939 * Alexander Enzmann
940 *
941 * DESCRIPTION
942 *
943 * -
944 *
945 * CHANGES
946 *
947 * -
948 *
949 ******************************************************************************/
950
bezier_split_left_right(const ControlPoints * Patch,ControlPoints * Left_Patch,ControlPoints * Right_Patch)951 void BicubicPatch::bezier_split_left_right(const ControlPoints *Patch, ControlPoints *Left_Patch, ControlPoints *Right_Patch)
952 {
953 int i, j;
954 Vector3d Half;
955 Vector3d Temp1[4], Temp2[4];
956
957 for (i = 0; i < 4; i++)
958 {
959 Temp1[0] = (*Patch)[0][i];
960
961 Temp1[1] = midpoint( (*Patch)[0][i], (*Patch)[1][i] );
962 Half = midpoint( (*Patch)[1][i], (*Patch)[2][i] );
963 Temp1[2] = midpoint( Temp1[1], Half );
964 Temp2[2] = midpoint( (*Patch)[2][i], (*Patch)[3][i] );
965 Temp2[1] = midpoint( Half, Temp2[2] );
966 Temp1[3] = midpoint( Temp1[2], Temp2[1] );
967
968 Temp2[0] = Temp1[3];
969 Temp2[3] = (*Patch)[3][i];
970
971 for (j = 0; j < 4; j++)
972 {
973 (*Left_Patch)[j][i] = Temp1[j];
974 (*Right_Patch)[j][i] = Temp2[j];
975 }
976 }
977 }
978
979
980
981 /*****************************************************************************
982 *
983 * FUNCTION
984 *
985 * bezier_split_up_down
986 *
987 * INPUT
988 *
989 * OUTPUT
990 *
991 * RETURNS
992 *
993 * AUTHOR
994 *
995 * Alexander Enzmann
996 *
997 * DESCRIPTION
998 *
999 * -
1000 *
1001 * CHANGES
1002 *
1003 * -
1004 *
1005 ******************************************************************************/
1006
bezier_split_up_down(const ControlPoints * Patch,ControlPoints * Bottom_Patch,ControlPoints * Top_Patch)1007 void BicubicPatch::bezier_split_up_down(const ControlPoints *Patch, ControlPoints *Bottom_Patch, ControlPoints *Top_Patch)
1008 {
1009 int i, j;
1010 Vector3d Temp1[4], Temp2[4];
1011 Vector3d Half;
1012
1013 for (i = 0; i < 4; i++)
1014 {
1015 Temp1[0] = (*Patch)[i][0];
1016
1017 Temp1[1] = midpoint( (*Patch)[i][0], (*Patch)[i][1] );
1018 Half = midpoint( (*Patch)[i][1], (*Patch)[i][2] );
1019 Temp1[2] = midpoint( Temp1[1], Half );
1020 Temp2[2] = midpoint( (*Patch)[i][2], (*Patch)[i][3] );
1021 Temp2[1] = midpoint( Half, Temp2[2] );
1022 Temp1[3] = midpoint( Temp1[2], Temp2[1] );
1023
1024 Temp2[0] = Temp1[3];
1025 Temp2[3] = (*Patch)[i][3];
1026
1027 for (j = 0; j < 4; j++)
1028 {
1029 (*Bottom_Patch)[i][j] = Temp1[j];
1030 (*Top_Patch)[i][j] = Temp2[j];
1031 }
1032 }
1033 }
1034
1035
1036
1037 /*****************************************************************************
1038 *
1039 * FUNCTION
1040 *
1041 * determine_subpatch_flatness
1042 *
1043 * INPUT
1044 *
1045 * OUTPUT
1046 *
1047 * RETURNS
1048 *
1049 * AUTHOR
1050 *
1051 * Alexander Enzmann
1052 *
1053 * DESCRIPTION
1054 *
1055 * See how close to a plane a subpatch is, the patch must have at least
1056 * three distinct vertices. A negative result from this function indicates
1057 * that a degenerate value of some sort was encountered.
1058 *
1059 * CHANGES
1060 *
1061 * -
1062 *
1063 ******************************************************************************/
1064
determine_subpatch_flatness(const ControlPoints * Patch)1065 DBL BicubicPatch::determine_subpatch_flatness(const ControlPoints *Patch)
1066 {
1067 int i, j;
1068 DBL d, dist, temp1;
1069 Vector3d n;
1070 Vector3d TempV;
1071 Vector3d vertices[3];
1072
1073 vertices[0] = (*Patch)[0][0];
1074 vertices[1] = (*Patch)[0][3];
1075
1076 TempV = vertices[0] - vertices[1];
1077
1078 temp1 = TempV.length();
1079
1080 if (fabs(temp1) < EPSILON)
1081 {
1082 /*
1083 * Degenerate in the V direction for U = 0. This is ok if the other
1084 * two corners are distinct from the lower left corner - I'm sure there
1085 * are cases where the corners coincide and the middle has good values,
1086 * but that is somewhat pathalogical and won't be considered.
1087 */
1088
1089 vertices[1] = (*Patch)[3][3];
1090
1091 TempV = vertices[0] - vertices[1];
1092
1093 temp1 = TempV.length();
1094
1095 if (fabs(temp1) < EPSILON)
1096 {
1097 return (-1.0);
1098 }
1099
1100 vertices[2] = (*Patch)[3][0];
1101
1102 TempV = vertices[0] - vertices[1];
1103
1104 temp1 = TempV.length();
1105
1106 if (fabs(temp1) < EPSILON)
1107 {
1108 return (-1.0);
1109 }
1110
1111 TempV = vertices[1] - vertices[2];
1112
1113 temp1 = TempV.length();
1114
1115 if (fabs(temp1) < EPSILON)
1116 {
1117 return (-1.0);
1118 }
1119 }
1120 else
1121 {
1122 vertices[2] = (*Patch)[3][0];
1123
1124 TempV = vertices[0] - vertices[1];
1125
1126 temp1 = TempV.length();
1127
1128 if (fabs(temp1) < EPSILON)
1129 {
1130 vertices[2] = (*Patch)[3][3];
1131
1132 TempV = vertices[0] - vertices[2];
1133
1134 temp1 = TempV.length();
1135
1136 if (fabs(temp1) < EPSILON)
1137 {
1138 return (-1.0);
1139 }
1140
1141 TempV = vertices[1] - vertices[2];
1142
1143 temp1 = TempV.length();
1144
1145 if (fabs(temp1) < EPSILON)
1146 {
1147 return (-1.0);
1148 }
1149 }
1150 else
1151 {
1152 TempV = vertices[1] - vertices[2];
1153
1154 temp1 = TempV.length();
1155
1156 if (fabs(temp1) < EPSILON)
1157 {
1158 return (-1.0);
1159 }
1160 }
1161 }
1162
1163 /*
1164 * Now that a good set of candidate points has been found,
1165 * find the plane equations for the patch.
1166 */
1167
1168 if (subpatch_normal(vertices[0], vertices[1], vertices[2], n, &d))
1169 {
1170 /*
1171 * Step through all vertices and see what the maximum
1172 * distance from the plane happens to be.
1173 */
1174
1175 dist = 0.0;
1176
1177 for (i = 0; i < 4; i++)
1178 {
1179 for (j = 0; j < 4; j++)
1180 {
1181 temp1 = fabs(point_plane_distance((*Patch)[i][j], n, d));
1182
1183 if (temp1 > dist)
1184 {
1185 dist = temp1;
1186 }
1187 }
1188 }
1189
1190 return (dist);
1191 }
1192 else
1193 {
1194 /*
1195 Debug_Info("Subpatch normal failed in determine_subpatch_flatness\n");
1196 */
1197
1198 return (-1.0);
1199 }
1200 }
1201
1202
1203
1204 /*****************************************************************************
1205 *
1206 * FUNCTION
1207 *
1208 * flat_enough
1209 *
1210 * INPUT
1211 *
1212 * OUTPUT
1213 *
1214 * RETURNS
1215 *
1216 * AUTHOR
1217 *
1218 * Alexander Enzmann
1219 *
1220 * DESCRIPTION
1221 *
1222 * -
1223 *
1224 * CHANGES
1225 *
1226 * -
1227 *
1228 ******************************************************************************/
1229
flat_enough(const ControlPoints * Patch) const1230 bool BicubicPatch::flat_enough(const ControlPoints *Patch) const
1231 {
1232 DBL Dist;
1233
1234 Dist = determine_subpatch_flatness(Patch);
1235
1236 if (Dist < 0.0)
1237 {
1238 return false;
1239 }
1240 else
1241 {
1242 if (Dist < Flatness_Value)
1243 {
1244 return true;
1245 }
1246 else
1247 {
1248 return false;
1249 }
1250 }
1251 }
1252
1253
1254
1255 /*****************************************************************************
1256 *
1257 * FUNCTION
1258 *
1259 * bezier_subdivider
1260 *
1261 * INPUT
1262 *
1263 * OUTPUT
1264 *
1265 * RETURNS
1266 *
1267 * AUTHOR
1268 *
1269 * Alexander Enzmann
1270 *
1271 * DESCRIPTION
1272 *
1273 * -
1274 *
1275 * CHANGES
1276 *
1277 * -
1278 *
1279 ******************************************************************************/
1280
bezier_subdivider(const BasicRay & ray,const ControlPoints * Patch,DBL u0,DBL u1,DBL v0,DBL v1,int recursion_depth,IStack & Depth_Stack,TraceThreadData * Thread)1281 int BicubicPatch::bezier_subdivider(const BasicRay &ray, const ControlPoints *Patch, DBL u0, DBL u1, DBL v0, DBL v1, int recursion_depth, IStack& Depth_Stack, TraceThreadData *Thread)
1282 {
1283 int cnt = 0;
1284 DBL ut, vt, radiusSqr;
1285 ControlPoints Lower_Left, Lower_Right;
1286 ControlPoints Upper_Left, Upper_Right;
1287 Vector3d center;
1288
1289 /*
1290 * Make sure the ray passes through a sphere bounding
1291 * the control points of the patch.
1292 */
1293
1294 bezier_bounding_sphere(Patch, center, &radiusSqr);
1295
1296 if (!spherical_bounds_check(ray, center, radiusSqr))
1297 {
1298 return (0);
1299 }
1300
1301 /*
1302 * If the patch is close to being flat, then just
1303 * perform a ray-plane intersection test.
1304 */
1305
1306 if (flat_enough(Patch))
1307 return bezier_subpatch_intersect(ray, Patch, u0, u1, v0, v1, Depth_Stack, Thread);
1308
1309 if (recursion_depth >= U_Steps)
1310 {
1311 if (recursion_depth >= V_Steps)
1312 {
1313 return bezier_subpatch_intersect(ray, Patch, u0, u1, v0, v1, Depth_Stack, Thread);
1314 }
1315 else
1316 {
1317 bezier_split_up_down(Patch, &Lower_Left, &Upper_Left);
1318
1319 vt = (v1 + v0) / 2.0;
1320
1321 cnt += bezier_subdivider(ray, &Lower_Left, u0, u1, v0, vt, recursion_depth + 1, Depth_Stack, Thread);
1322 cnt += bezier_subdivider(ray, &Upper_Left, u0, u1, vt, v1, recursion_depth + 1, Depth_Stack, Thread);
1323 }
1324 }
1325 else
1326 {
1327 if (recursion_depth >= V_Steps)
1328 {
1329 bezier_split_left_right(Patch, &Lower_Left, &Lower_Right);
1330
1331 ut = (u1 + u0) / 2.0;
1332
1333 cnt += bezier_subdivider(ray, &Lower_Left, u0, ut, v0, v1, recursion_depth + 1, Depth_Stack, Thread);
1334 cnt += bezier_subdivider(ray, &Lower_Right, ut, u1, v0, v1, recursion_depth + 1, Depth_Stack, Thread);
1335 }
1336 else
1337 {
1338 ut = (u1 + u0) / 2.0;
1339 vt = (v1 + v0) / 2.0;
1340
1341 bezier_split_left_right(Patch, &Lower_Left, &Lower_Right);
1342 bezier_split_up_down(&Lower_Left, &Lower_Left, &Upper_Left) ;
1343 bezier_split_up_down(&Lower_Right, &Lower_Right, &Upper_Right);
1344
1345 cnt += bezier_subdivider(ray, &Lower_Left, u0, ut, v0, vt, recursion_depth + 1, Depth_Stack, Thread);
1346 cnt += bezier_subdivider(ray, &Upper_Left, u0, ut, vt, v1, recursion_depth + 1, Depth_Stack, Thread);
1347 cnt += bezier_subdivider(ray, &Lower_Right, ut, u1, v0, vt, recursion_depth + 1, Depth_Stack, Thread);
1348 cnt += bezier_subdivider(ray, &Upper_Right, ut, u1, vt, v1, recursion_depth + 1, Depth_Stack, Thread);
1349 }
1350 }
1351
1352 return (cnt);
1353 }
1354
1355
1356
1357 /*****************************************************************************
1358 *
1359 * FUNCTION
1360 *
1361 * bezier_tree_deleter
1362 *
1363 * INPUT
1364 *
1365 * OUTPUT
1366 *
1367 * RETURNS
1368 *
1369 * AUTHOR
1370 *
1371 * Alexander Enzmann
1372 *
1373 * DESCRIPTION
1374 *
1375 * -
1376 *
1377 * CHANGES
1378 *
1379 * -
1380 *
1381 ******************************************************************************/
1382
bezier_tree_deleter(BEZIER_NODE * Node)1383 void BicubicPatch::bezier_tree_deleter(BEZIER_NODE *Node)
1384 {
1385 int i;
1386 BEZIER_CHILDREN *Children;
1387
1388 /* If this is an interior node then continue the descent. */
1389
1390 if (Node->Node_Type == BEZIER_INTERIOR_NODE)
1391 {
1392 Children = reinterpret_cast<BEZIER_CHILDREN *>(Node->Data_Ptr);
1393
1394 for (i = 0; i < Node->Count; i++)
1395 {
1396 bezier_tree_deleter(Children->Children[i]);
1397 }
1398
1399 POV_FREE(Children);
1400 }
1401 else
1402 {
1403 if (Node->Node_Type == BEZIER_LEAF_NODE)
1404 {
1405 /* Free the memory used for the vertices. */
1406
1407 POV_FREE(Node->Data_Ptr);
1408 }
1409 }
1410
1411 /* Free the memory used for the node. */
1412
1413 POV_FREE(Node);
1414 }
1415
1416
1417
1418 /*****************************************************************************
1419 *
1420 * FUNCTION
1421 *
1422 * bezier_tree_walker
1423 *
1424 * INPUT
1425 *
1426 * OUTPUT
1427 *
1428 * RETURNS
1429 *
1430 * AUTHOR
1431 *
1432 * Alexander Enzmann
1433 *
1434 * DESCRIPTION
1435 *
1436 * -
1437 *
1438 * CHANGES
1439 *
1440 * -
1441 *
1442 ******************************************************************************/
1443
bezier_tree_walker(const BasicRay & ray,const BEZIER_NODE * Node,IStack & Depth_Stack,TraceThreadData * Thread)1444 int BicubicPatch::bezier_tree_walker(const BasicRay &ray, const BEZIER_NODE *Node, IStack& Depth_Stack, TraceThreadData *Thread)
1445 {
1446 int i, cnt = 0;
1447 DBL Depth, u, v;
1448 DBL uu[3], vv[3];
1449 Vector3d N, P;
1450 TripleVector3d V1;
1451 Vector2d UV;
1452 Vector2d uv_point, tpoint;
1453 const BEZIER_CHILDREN *Children;
1454 const BEZIER_VERTICES *Vertices;
1455
1456 /*
1457 * Make sure the ray passes through a sphere bounding
1458 * the control points of the patch.
1459 */
1460
1461 if (!spherical_bounds_check(ray, Node->Center, Node->Radius_Squared))
1462 {
1463 return (0);
1464 }
1465
1466 /*
1467 * If this is an interior node then continue the descent,
1468 * else do a check against the vertices.
1469 */
1470
1471 if (Node->Node_Type == BEZIER_INTERIOR_NODE)
1472 {
1473 Children = reinterpret_cast<const BEZIER_CHILDREN *>(Node->Data_Ptr);
1474
1475 for (i = 0; i < Node->Count; i++)
1476 {
1477 cnt += bezier_tree_walker(ray, Children->Children[i], Depth_Stack, Thread);
1478 }
1479 }
1480 else if (Node->Node_Type == BEZIER_LEAF_NODE)
1481 {
1482 Vertices = reinterpret_cast<const BEZIER_VERTICES *>(Node->Data_Ptr);
1483
1484 V1[0] = Vertices->Vertices[0];
1485 V1[1] = Vertices->Vertices[1];
1486 V1[2] = Vertices->Vertices[2];
1487
1488 uu[0] = Vertices->uvbnds[0];
1489 uu[1] = Vertices->uvbnds[0];
1490 uu[2] = Vertices->uvbnds[1];
1491 vv[0] = Vertices->uvbnds[2];
1492 vv[1] = Vertices->uvbnds[3];
1493 vv[2] = Vertices->uvbnds[3];
1494
1495 /*
1496 * Triangulate this subpatch, then check for
1497 * intersections in the triangles.
1498 */
1499
1500 if (intersect_subpatch(ray, V1, uu, vv, &Depth, P, N, &u, &v))
1501 {
1502 if (Clip.empty() || Point_In_Clip(P, Clip, Thread))
1503 {
1504 /* transform current point from uv space to texture space */
1505 uv_point[0] = v;
1506 uv_point[1] = u;
1507 Compute_Texture_UV(uv_point, ST, tpoint);
1508
1509 UV[U] = tpoint[0];
1510 UV[V] = tpoint[1];
1511 Depth_Stack->push(Intersection(Depth, P, N, UV, this));
1512
1513 cnt++;
1514 }
1515 }
1516
1517 V1[1] = V1[2];
1518 V1[2] = Vertices->Vertices[3];
1519
1520 uu[1] = uu[2]; uu[2] = Vertices->uvbnds[1];
1521 vv[1] = vv[2]; vv[2] = Vertices->uvbnds[2];
1522
1523 if (intersect_subpatch(ray, V1, uu, vv, &Depth, P, N, &u, &v))
1524 {
1525 if (Clip.empty() || Point_In_Clip(P, Clip, Thread))
1526 {
1527 /* transform current point from object space to texture space */
1528 uv_point[0] = v;
1529 uv_point[1] = u;
1530 Compute_Texture_UV(uv_point, ST, tpoint);
1531
1532 UV[U] = tpoint[0];
1533 UV[V] = tpoint[1];
1534 Depth_Stack->push(Intersection(Depth, P, N, UV, this));
1535
1536 cnt++;
1537 }
1538 }
1539 }
1540 else
1541 {
1542 throw POV_EXCEPTION_STRING("Bad Node type in bezier_tree_walker().");
1543 }
1544
1545 return (cnt);
1546 }
1547
1548
1549
1550 /*****************************************************************************
1551 *
1552 * FUNCTION
1553 *
1554 * intersect_bicubic_patch0
1555 *
1556 * INPUT
1557 *
1558 * OUTPUT
1559 *
1560 * RETURNS
1561 *
1562 * AUTHOR
1563 *
1564 * Alexander Enzmann
1565 *
1566 * DESCRIPTION
1567 *
1568 * -
1569 *
1570 * CHANGES
1571 *
1572 * -
1573 *
1574 ******************************************************************************/
1575
intersect_bicubic_patch0(const BasicRay & ray,IStack & Depth_Stack,TraceThreadData * Thread)1576 int BicubicPatch::intersect_bicubic_patch0(const BasicRay &ray, IStack& Depth_Stack, TraceThreadData *Thread)
1577 {
1578 return (bezier_subdivider(ray, &Control_Points, 0.0, 1.0, 0.0, 1.0, 0, Depth_Stack, Thread));
1579 }
1580
1581
1582
1583 /*****************************************************************************
1584 *
1585 * FUNCTION
1586 *
1587 * All_Bicubic_Patch_Intersections
1588 *
1589 * INPUT
1590 *
1591 * OUTPUT
1592 *
1593 * RETURNS
1594 *
1595 * AUTHOR
1596 *
1597 * Alexander Enzmann
1598 *
1599 * DESCRIPTION
1600 *
1601 * -
1602 *
1603 * CHANGES
1604 *
1605 * -
1606 *
1607 ******************************************************************************/
1608
All_Intersections(const Ray & ray,IStack & Depth_Stack,TraceThreadData * Thread)1609 bool BicubicPatch::All_Intersections(const Ray& ray, IStack& Depth_Stack, TraceThreadData *Thread)
1610 {
1611 int Found, cnt = 0;
1612
1613 Found = false;
1614
1615 Thread->Stats()[Ray_Bicubic_Tests]++;
1616
1617 switch (Patch_Type)
1618 {
1619 case 0:
1620
1621 cnt = intersect_bicubic_patch0(ray, Depth_Stack, Thread);
1622
1623 break;
1624
1625 case 1:
1626
1627 cnt = bezier_tree_walker(ray, Node_Tree, Depth_Stack, Thread);
1628
1629 break;
1630
1631 default:
1632
1633 throw POV_EXCEPTION_STRING("Bad patch type in All_Bicubic_Patch_Intersections.");
1634 }
1635
1636 if (cnt > 0)
1637 {
1638 Thread->Stats()[Ray_Bicubic_Tests_Succeeded]++;
1639
1640 Found = true;
1641 }
1642
1643 return (Found);
1644 }
1645
1646
1647
1648 /*****************************************************************************
1649 *
1650 * FUNCTION
1651 *
1652 * Inside_Bicubic_Patch
1653 *
1654 * INPUT
1655 *
1656 * OUTPUT
1657 *
1658 * RETURNS
1659 *
1660 * AUTHOR
1661 *
1662 * Alexander Enzmann
1663 *
1664 * DESCRIPTION
1665 *
1666 * A patch is not a solid, so an inside test doesn't make sense.
1667 *
1668 * CHANGES
1669 *
1670 * -
1671 *
1672 ******************************************************************************/
1673
Inside(const Vector3d &,TraceThreadData *) const1674 bool BicubicPatch::Inside(const Vector3d&, TraceThreadData *) const
1675 {
1676 return false;
1677 }
1678
1679
1680
1681 /*****************************************************************************
1682 *
1683 * FUNCTION
1684 *
1685 * Bicubic_Patch_Normal
1686 *
1687 * INPUT
1688 *
1689 * OUTPUT
1690 *
1691 * RETURNS
1692 *
1693 * AUTHOR
1694 *
1695 * Alexander Enzmann
1696 *
1697 * DESCRIPTION
1698 *
1699 * -
1700 *
1701 * CHANGES
1702 *
1703 * -
1704 *
1705 ******************************************************************************/
1706
Normal(Vector3d & Result,Intersection * Inter,TraceThreadData * Thread) const1707 void BicubicPatch::Normal(Vector3d& Result, Intersection *Inter, TraceThreadData *Thread) const
1708 {
1709 /* Use preocmputed normal. */
1710
1711 Result = Inter->INormal;
1712 }
1713
1714
1715
1716 /*****************************************************************************
1717 *
1718 * FUNCTION
1719 *
1720 * Translate_Bicubic_Patch
1721 *
1722 * INPUT
1723 *
1724 * OUTPUT
1725 *
1726 * RETURNS
1727 *
1728 * AUTHOR
1729 *
1730 * Alexander Enzmann
1731 *
1732 * DESCRIPTION
1733 *
1734 * -
1735 *
1736 * CHANGES
1737 *
1738 * -
1739 *
1740 ******************************************************************************/
1741
Translate(const Vector3d & Vector,const TRANSFORM *)1742 void BicubicPatch::Translate(const Vector3d& Vector, const TRANSFORM *)
1743 {
1744 int i, j;
1745
1746 for (i = 0; i < 4; i++)
1747 {
1748 for (j = 0; j < 4; j++)
1749 {
1750 Control_Points[i][j] += Vector;
1751 }
1752 }
1753
1754 Precompute_Patch_Values();
1755
1756 Compute_BBox();
1757 }
1758
1759
1760
1761 /*****************************************************************************
1762 *
1763 * FUNCTION
1764 *
1765 * Rotate_Bicubic_Patch
1766 *
1767 * INPUT
1768 *
1769 * OUTPUT
1770 *
1771 * RETURNS
1772 *
1773 * AUTHOR
1774 *
1775 * Alexander Enzmann
1776 *
1777 * DESCRIPTION
1778 *
1779 * -
1780 *
1781 * CHANGES
1782 *
1783 * -
1784 *
1785 ******************************************************************************/
1786
Rotate(const Vector3d &,const TRANSFORM * tr)1787 void BicubicPatch::Rotate(const Vector3d&, const TRANSFORM *tr)
1788 {
1789 Transform(tr);
1790 }
1791
1792
1793
1794 /*****************************************************************************
1795 *
1796 * FUNCTION
1797 *
1798 * Scale_Bicubic_Patch
1799 *
1800 * INPUT
1801 *
1802 * OUTPUT
1803 *
1804 * RETURNS
1805 *
1806 * AUTHOR
1807 *
1808 * Alexander Enzmann
1809 *
1810 * DESCRIPTION
1811 *
1812 * -
1813 *
1814 * CHANGES
1815 *
1816 * -
1817 *
1818 ******************************************************************************/
1819
Scale(const Vector3d & Vector,const TRANSFORM *)1820 void BicubicPatch::Scale(const Vector3d& Vector, const TRANSFORM *)
1821 {
1822 int i, j;
1823
1824 for (i = 0; i < 4; i++)
1825 {
1826 for (j = 0; j < 4; j++)
1827 {
1828 Control_Points[i][j] *= Vector;
1829 }
1830 }
1831
1832 Precompute_Patch_Values();
1833
1834 Compute_BBox();
1835 }
1836
1837
1838
1839
1840 /*****************************************************************************
1841 *
1842 * FUNCTION
1843 *
1844 * Transform_Bicubic_Patch
1845 *
1846 * INPUT
1847 *
1848 * OUTPUT
1849 *
1850 * RETURNS
1851 *
1852 * AUTHOR
1853 *
1854 * Alexander Enzmann
1855 *
1856 * DESCRIPTION
1857 *
1858 * -
1859 *
1860 * CHANGES
1861 *
1862 * -
1863 *
1864 ******************************************************************************/
1865
Transform(const TRANSFORM * tr)1866 void BicubicPatch::Transform(const TRANSFORM *tr)
1867 {
1868 int i, j;
1869
1870 for (i = 0; i < 4; i++)
1871 {
1872 for (j = 0; j < 4; j++)
1873 {
1874 MTransPoint(Control_Points[i][j], Control_Points[i][j], tr);
1875 }
1876 }
1877
1878 Precompute_Patch_Values();
1879
1880 Compute_BBox();
1881 }
1882
1883
1884
1885 /*****************************************************************************
1886 *
1887 * FUNCTION
1888 *
1889 * Create_Bicubic_Patch
1890 *
1891 * INPUT
1892 *
1893 * OUTPUT
1894 *
1895 * RETURNS
1896 *
1897 * AUTHOR
1898 *
1899 * Alexander Enzmann
1900 *
1901 * DESCRIPTION
1902 *
1903 * -
1904 *
1905 * CHANGES
1906 *
1907 * -
1908 *
1909 ******************************************************************************/
1910
BicubicPatch()1911 BicubicPatch::BicubicPatch() : NonsolidObject(BICUBIC_PATCH_OBJECT)
1912 {
1913 Patch_Type = - 1;
1914
1915 U_Steps = 0;
1916 V_Steps = 0;
1917
1918 Flatness_Value = 0.0;
1919 accuracy = 0.01;
1920
1921 Node_Tree = nullptr;
1922 Weights = nullptr;
1923
1924 /*
1925 * NOTE: Control_Points[4][4] is initialized in Parse_Bicubic_Patch.
1926 * Bounding_Sphere_Center,Bounding_Sphere_Radius, Normal_Vector[], and
1927 * IPoint[] are initialized in Precompute_Patch_Values.
1928 */
1929
1930 /* set the default uv-mapping coordinates */
1931 ST[0] = Vector2d(0.0, 0.0);
1932 ST[1] = Vector2d(1.0, 0.0);
1933 ST[2] = Vector2d(1.0, 1.0);
1934 ST[3] = Vector2d(0.0, 1.0);
1935 }
1936
1937
1938
1939 /*****************************************************************************
1940 *
1941 * FUNCTION
1942 *
1943 * Copy_Bicubic_Patch
1944 *
1945 * INPUT
1946 *
1947 * OUTPUT
1948 *
1949 * RETURNS
1950 *
1951 * AUTHOR
1952 *
1953 * Alexander Enzmann
1954 *
1955 * DESCRIPTION
1956 *
1957 * -
1958 *
1959 * CHANGES
1960 *
1961 * -
1962 *
1963 ******************************************************************************/
1964
Copy()1965 ObjectPtr BicubicPatch::Copy()
1966 {
1967 int i, j;
1968 BicubicPatch *New = new BicubicPatch();
1969 int m;
1970
1971 /* Do not do *New = *Old so that Precompute works right */
1972
1973 New->Patch_Type = Patch_Type;
1974
1975 New->U_Steps = U_Steps;
1976 New->V_Steps = V_Steps;
1977
1978 if (Weights != nullptr)
1979 {
1980 New->Weights = reinterpret_cast<BEZIER_WEIGHTS *>(POV_MALLOC( sizeof(BEZIER_WEIGHTS),"bicubic patch" ));
1981 POV_MEMCPY( New->Weights, Weights, sizeof(BEZIER_WEIGHTS) );
1982 }
1983
1984 for (i = 0; i < 4; i++)
1985 {
1986 for (j = 0; j < 4; j++)
1987 {
1988 New->Control_Points[i][j] = Control_Points[i][j];
1989 }
1990 }
1991
1992 New->Flatness_Value = Flatness_Value;
1993
1994 New->Precompute_Patch_Values();
1995
1996 /* copy the mapping */
1997 for (m = 0; m < 4; m++)
1998 {
1999 New->ST[m] = ST[m];
2000 }
2001
2002 return (New);
2003 }
2004
2005
2006
2007 /*****************************************************************************
2008 *
2009 * FUNCTION
2010 *
2011 * Destroy_Bicubic_Patch
2012 *
2013 * INPUT
2014 *
2015 * OUTPUT
2016 *
2017 * RETURNS
2018 *
2019 * AUTHOR
2020 *
2021 * Alexander Enzmann
2022 *
2023 * DESCRIPTION
2024 *
2025 * -
2026 *
2027 * CHANGES
2028 *
2029 * -
2030 *
2031 ******************************************************************************/
2032
~BicubicPatch()2033 BicubicPatch::~BicubicPatch()
2034 {
2035 if (Patch_Type == 1)
2036 {
2037 if (Node_Tree != nullptr)
2038 {
2039 bezier_tree_deleter(Node_Tree);
2040 }
2041 }
2042
2043 if (Weights != nullptr)
2044 POV_FREE(Weights);
2045 }
2046
2047
2048
2049 /*****************************************************************************
2050 *
2051 * FUNCTION
2052 *
2053 * Compute_Bicubic_Patch_BBox
2054 *
2055 * INPUT
2056 *
2057 * Bicubic_Patch - Bicubic patch
2058 *
2059 * OUTPUT
2060 *
2061 * Bicubic_Patch
2062 *
2063 * RETURNS
2064 *
2065 * AUTHOR
2066 *
2067 * Dieter Bayer
2068 *
2069 * DESCRIPTION
2070 *
2071 * Calculate the bounding box of a bicubic patch.
2072 *
2073 * CHANGES
2074 *
2075 * Aug 1994 : Creation.
2076 *
2077 ******************************************************************************/
2078
Compute_BBox()2079 void BicubicPatch::Compute_BBox()
2080 {
2081 int i, j;
2082 Vector3d Min, Max;
2083
2084 Min = Vector3d(BOUND_HUGE);
2085 Max = Vector3d(-BOUND_HUGE);
2086
2087 for (i = 0; i < 4; i++)
2088 {
2089 for (j = 0; j < 4; j++)
2090 {
2091 Min[X] = min(Min[X], Control_Points[i][j][X]);
2092 Min[Y] = min(Min[Y], Control_Points[i][j][Y]);
2093 Min[Z] = min(Min[Z], Control_Points[i][j][Z]);
2094 Max[X] = max(Max[X], Control_Points[i][j][X]);
2095 Max[Y] = max(Max[Y], Control_Points[i][j][Y]);
2096 Max[Z] = max(Max[Z], Control_Points[i][j][Z]);
2097 }
2098 }
2099
2100 Make_BBox_from_min_max(BBox, Min, Max);
2101 }
2102
2103 /*****************************************************************************
2104 *
2105 * FUNCTION
2106 *
2107 * Bicubic_Patch_UVCoord
2108 *
2109 * INPUT
2110 *
2111 * OUTPUT
2112 *
2113 * RETURNS
2114 *
2115 * AUTHOR
2116 *
2117 * Nathan Kopp
2118 *
2119 * DESCRIPTION
2120 *
2121 * -
2122 *
2123 * CHANGES
2124 *
2125 * -
2126 *
2127 ******************************************************************************/
2128
UVCoord(Vector2d & Result,const Intersection * Inter,TraceThreadData * Thread) const2129 void BicubicPatch::UVCoord(Vector2d& Result, const Intersection *Inter, TraceThreadData *Thread) const
2130 {
2131 /* Use preocmputed uv coordinates. */
2132
2133 Result = Inter->Iuv;
2134 }
2135
2136
2137 /*****************************************************************************
2138 *
2139 * FUNCTION
2140 *
2141 * Compute_UV_Point
2142 *
2143 * INPUT
2144 *
2145 * OUTPUT
2146 *
2147 * RETURNS
2148 *
2149 * AUTHOR
2150 *
2151 * Mike Hough
2152 *
2153 * DESCRIPTION
2154 *
2155 * Transform p from uv space to texture space (point t) using the
2156 * shape's ST mapping
2157 *
2158 * CHANGES
2159 *
2160 * -
2161 *
2162 ******************************************************************************/
2163
Compute_Texture_UV(const Vector2d & p,const Vector2d st[4],Vector2d & t)2164 void BicubicPatch::Compute_Texture_UV(const Vector2d& p, const Vector2d st[4], Vector2d& t)
2165 {
2166 Vector2d u1, u2;
2167
2168 u1[0] = st[0][0] + p[0] * (st[1][0] - st[0][0]);
2169 u1[1] = st[0][1] + p[0] * (st[1][1] - st[0][1]);
2170
2171 u2[0] = st[3][0] + p[0] * (st[2][0] - st[3][0]);
2172 u2[1] = st[3][1] + p[0] * (st[2][1] - st[3][1]);
2173
2174 t[0] = u1[0] + p[1] * (u2[0] - u1[0]);
2175 t[1] = u1[1] + p[1] * (u2[1] - u1[1]);
2176 }
2177
2178 }
2179