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