1 /*******************************************************************************
2 * mesh.cpp
3 *
4 * This module implements primitives for mesh objects.
5 *
6 * This module was written by Dieter Bayer [DB].
7 *
8 * ---------------------------------------------------------------------------
9 * Persistence of Vision Ray Tracer ('POV-Ray') version 3.7.
10 * Copyright 1991-2013 Persistence of Vision Raytracer Pty. Ltd.
11 *
12 * POV-Ray is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Affero General Public License as
14 * published by the Free Software Foundation, either version 3 of the
15 * License, or (at your option) any later version.
16 *
17 * POV-Ray is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU Affero General Public License for more details.
21 *
22 * You should have received a copy of the GNU Affero General Public License
23 * along with this program. If not, see <http://www.gnu.org/licenses/>.
24 * ---------------------------------------------------------------------------
25 * POV-Ray is based on the popular DKB raytracer version 2.12.
26 * DKBTrace was originally written by David K. Buck.
27 * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
28 * ---------------------------------------------------------------------------
29 * $File: //depot/public/povray/3.x/source/backend/shape/mesh.cpp $
30 * $Revision: #1 $
31 * $Change: 6069 $
32 * $DateTime: 2013/11/06 11:59:40 $
33 * $Author: chrisc $
34 *******************************************************************************/
35
36 /****************************************************************************
37 *
38 * Explanation:
39 *
40 * -
41 *
42 * Syntax:
43 *
44 * mesh
45 * {
46 * triangle { <CORNER1>, <CORNER2>, <CORNER3>, texture { NAME } }
47 * smooth_triangle { <CORNER1>, <NORMAL1>, <CORNER2>, <NORMAL2>, <CORNER3>, <NORMAL3>, texture { NAME } }
48 * ...
49 * [ hierarchy FLAG ]
50 * }
51 *
52 * ---
53 *
54 * Feb 1995 : Creation. [DB]
55 *
56 *****************************************************************************/
57
58 // frame.h must always be the first POV file included (pulls in platform config)
59 #include "backend/frame.h"
60 #include "backend/math/vector.h"
61 #include "backend/bounding/bbox.h"
62 #include "backend/math/matrices.h"
63 #include "backend/scene/objects.h"
64 #include "backend/shape/mesh.h"
65 #include "backend/texture/texture.h"
66 #include "backend/shape/triangle.h"
67 #include "backend/scene/threaddata.h"
68 #include "base/pov_err.h"
69
70 #include <algorithm>
71
72 // this must be the last file included
73 #include "base/povdebug.h"
74
75 namespace pov
76 {
77
78 /*****************************************************************************
79 * Local preprocessor defines
80 ******************************************************************************/
81
82 const DBL DEPTH_TOLERANCE = 1e-6;
83
84 #define max3_coordinate(x,y,z) ((x > y) ? ((x > z) ? X : Z) : ((y > z) ? Y : Z))
85
86 const int HASH_SIZE = 1000;
87
88 const int INITIAL_NUMBER_OF_ENTRIES = 256;
89
90
91
92 /*****************************************************************************
93 * Local variables
94 ******************************************************************************/
95
96 HASH_TABLE **Mesh::Vertex_Hash_Table;
97 HASH_TABLE **Mesh::Normal_Hash_Table;
98 UV_HASH_TABLE **Mesh::UV_Hash_Table;
99
100 /*****************************************************************************
101 *
102 * FUNCTION
103 *
104 * All_Mesh_Intersections
105 *
106 * INPUT
107 *
108 * OUTPUT
109 *
110 * RETURNS
111 *
112 * AUTHOR
113 *
114 * Dieter Bayer
115 *
116 * DESCRIPTION
117 *
118 * -
119 *
120 * CHANGES
121 *
122 * Feb 1995 : Creation.
123 *
124 ******************************************************************************/
125
All_Intersections(const Ray & ray,IStack & Depth_Stack,TraceThreadData * Thread)126 bool Mesh::All_Intersections(const Ray& ray, IStack& Depth_Stack, TraceThreadData *Thread)
127 {
128 Thread->Stats()[Ray_Mesh_Tests]++;
129
130 if (Intersect(ray, Depth_Stack, Thread))
131 {
132 Thread->Stats()[Ray_Mesh_Tests_Succeeded]++;
133 return(true);
134 }
135
136 return(false);
137 }
138
139
140
141 /*****************************************************************************
142 *
143 * FUNCTION
144 *
145 * Intersect_Mesh
146 *
147 * INPUT
148 *
149 * OUTPUT
150 *
151 * RETURNS
152 *
153 * AUTHOR
154 *
155 * Dieter Bayer
156 *
157 * DESCRIPTION
158 *
159 * -
160 *
161 * CHANGES
162 *
163 * Feb 1995 : Creation.
164 *
165 ******************************************************************************/
166
Intersect(const Ray & ray,IStack & Depth_Stack,TraceThreadData * Thread)167 bool Mesh::Intersect(const Ray& ray, IStack& Depth_Stack, TraceThreadData *Thread)
168 {
169 int i;
170 bool found;
171 DBL len, t;
172 Ray New_Ray;
173
174 /* Transform the ray into mesh space. */
175
176 if (Trans != NULL)
177 {
178 MInvTransPoint(New_Ray.Origin, ray.Origin, Trans);
179 MInvTransDirection(New_Ray.Direction, ray.Direction, Trans);
180
181 VLength(len, New_Ray.Direction);
182 VInverseScaleEq(New_Ray.Direction, len);
183 }
184 else
185 {
186 New_Ray = ray;
187
188 len = 1.0;
189 }
190
191 found = false;
192
193 if (Data->Tree == NULL)
194 {
195 /* There's no bounding hierarchy so just step through all elements. */
196
197 for (i = 0; i < Data->Number_Of_Triangles; i++)
198 {
199 if (intersect_mesh_triangle(New_Ray, &Data->Triangles[i], &t))
200 {
201 if (test_hit(&Data->Triangles[i], ray, t, len, Depth_Stack, Thread))
202 {
203 found = true;
204 }
205 }
206 }
207 }
208 else
209 {
210 /* Use the mesh's bounding hierarchy. */
211
212 return(intersect_bbox_tree(New_Ray, ray, len, Depth_Stack, Thread));
213 }
214
215 return(found);
216 }
217
218
219
220 /*****************************************************************************
221 *
222 * FUNCTION
223 *
224 * Inside_Mesh
225 *
226 * INPUT
227 *
228 * OUTPUT
229 *
230 * RETURNS
231 *
232 * AUTHOR
233 *
234 * Nathan Kopp & Dieter Bayer (adapted from Intersect_Mesh by Dieter Bayer)
235 *
236 * DESCRIPTION
237 *
238 * Shoot a ray out from this point, if the ray hits an odd number of
239 * triangles, it is inside the object. If it hits an even number
240 * than it is outside the object.
241 * The triangle mesh should be closed, otherwise results are unpredictable.
242 *
243 * CHANGES
244 *
245 * October, 1998 : Creation.
246 *
247 ******************************************************************************/
248
Inside(const VECTOR IPoint,TraceThreadData * Thread) const249 bool Mesh::Inside(const VECTOR IPoint, TraceThreadData *Thread) const
250 {
251 int inside, i;
252 unsigned found;
253 DBL len, t;
254 Ray ray, New_Ray;
255
256 if (has_inside_vector==false)
257 return false;
258
259 /* shoot a ray in the chosen direction from this point */
260 // if( (fabs(Data->Inside_Vect[X]) < EPSILON) &&
261 // (fabs(Data->Inside_Vect[Y]) < EPSILON) &&
262 // (fabs(Data->Inside_Vect[Z]) < EPSILON))
263 // {
264 // /* if no inside_vect , use X... maybe we should quit */
265 // /* return(false); */
266 //
267 // Make_Vector(Ray.Direction, 0, 0, 1);
268 // }
269 // else
270
271 Assign_Vector(ray.Direction, Data->Inside_Vect);
272
273 Assign_Vector(ray.Origin, IPoint);
274
275 /* Transform the ray into mesh space. */
276 if (Trans != NULL)
277 {
278 MInvTransPoint(New_Ray.Origin, ray.Origin, Trans);
279 MInvTransDirection(New_Ray.Direction, ray.Direction, Trans);
280
281 VLength(len, New_Ray.Direction);
282 VInverseScaleEq(New_Ray.Direction, len);
283 }
284 else
285 {
286 New_Ray = ray;
287 len = 1.0;
288 }
289
290 found = 0;
291
292 if (Data->Tree == NULL)
293 {
294 /* just step through all elements. */
295 for (i = 0; i < Data->Number_Of_Triangles; i++)
296 {
297 if (intersect_mesh_triangle(New_Ray, &Data->Triangles[i], &t))
298 {
299 /* actually, this should push onto a local depth stack and
300 make sure that we don't have the same intersection point from
301 two (or three) different triangles!!!!! */
302 found++;
303 }
304 }
305 /* odd number = inside, even number = outside */
306 inside = found & 1;
307 }
308 else
309 {
310 /* Use the mesh's bounding hierarchy. */
311 inside = inside_bbox_tree(New_Ray, Thread);
312 }
313
314 if (Test_Flag(this, INVERTED_FLAG))
315 {
316 inside = !inside;
317 }
318 return (inside);
319 }
320
321
322
323
324 /*****************************************************************************
325 *
326 * FUNCTION
327 *
328 * Mesh_Normal
329 *
330 * INPUT
331 *
332 * OUTPUT
333 *
334 * RETURNS
335 *
336 * AUTHOR
337 *
338 * Dieter Bayer
339 *
340 * DESCRIPTION
341 *
342 * Return the normalized normal in the given point.
343 *
344 * CHANGES
345 *
346 * Feb 1995 : Creation.
347 *
348 ******************************************************************************/
349
Normal(VECTOR Result,Intersection * Inter,TraceThreadData * Thread) const350 void Mesh::Normal(VECTOR Result, Intersection *Inter, TraceThreadData *Thread) const
351 {
352 VECTOR IPoint;
353 const MESH_TRIANGLE *Triangle;
354
355 Triangle = reinterpret_cast<const MESH_TRIANGLE *>(Inter->Pointer);
356
357 if (Triangle->Smooth)
358 {
359 if (Trans != NULL)
360 {
361 MInvTransPoint(IPoint, Inter->IPoint, Trans);
362 }
363 else
364 {
365 Assign_Vector(IPoint, Inter->IPoint);
366 }
367
368 Smooth_Mesh_Normal(Result, Triangle, IPoint);
369
370 if (Trans != NULL)
371 {
372 MTransNormal(Result, Result, Trans);
373 }
374
375 VNormalize(Result, Result);
376 }
377 else
378 {
379 Assign_Vector(Result, Data->Normals[Triangle->Normal_Ind]);
380
381 if (Trans != NULL)
382 {
383 MTransNormal(Result, Result, Trans);
384
385 VNormalize(Result, Result);
386 }
387 }
388 }
389
390
391
392 /*****************************************************************************
393 *
394 * FUNCTION
395 *
396 * Smooth_Mesh_Normal
397 *
398 * INPUT
399 *
400 * OUTPUT
401 *
402 * RETURNS
403 *
404 * AUTHOR
405 *
406 * Dieter Bayer
407 *
408 * DESCRIPTION
409 *
410 * Remove the un-normalized normal of a smoothed triangle.
411 *
412 * CHANGES
413 *
414 * Feb 1995 : Creation. (Derived from TRIANGLE.C)
415 *
416 ******************************************************************************/
417
Smooth_Mesh_Normal(VECTOR Result,const MESH_TRIANGLE * Triangle,const VECTOR IPoint) const418 void Mesh::Smooth_Mesh_Normal(VECTOR Result, const MESH_TRIANGLE *Triangle, const VECTOR IPoint) const
419 {
420 int axis;
421 DBL u, v;
422 DBL k1, k2, k3;
423 VECTOR PIMinusP1, N1, N2, N3;
424
425 get_triangle_normals(Triangle, N1, N2, N3);
426
427 VSub(PIMinusP1, IPoint, Data->Vertices[Triangle->P1]);
428
429 VDot(u, PIMinusP1, Triangle->Perp);
430
431 if (u < EPSILON)
432 {
433 Assign_Vector(Result, N1);
434 }
435 else
436 {
437 axis = Triangle->vAxis;
438
439 k1 = Data->Vertices[Triangle->P1][axis];
440 k2 = Data->Vertices[Triangle->P2][axis];
441 k3 = Data->Vertices[Triangle->P3][axis];
442
443 v = (PIMinusP1[axis] / u + k1 - k2) / (k3 - k2);
444
445 Result[X] = N1[X] + u * (N2[X] - N1[X] + v * (N3[X] - N2[X]));
446 Result[Y] = N1[Y] + u * (N2[Y] - N1[Y] + v * (N3[Y] - N2[Y]));
447 Result[Z] = N1[Z] + u * (N2[Z] - N1[Z] + v * (N3[Z] - N2[Z]));
448 }
449 }
450
451
452
453 /*****************************************************************************
454 *
455 * FUNCTION
456 *
457 * Translate_Mesh
458 *
459 * INPUT
460 *
461 * OUTPUT
462 *
463 * RETURNS
464 *
465 * AUTHOR
466 *
467 * Dieter Bayer
468 *
469 * DESCRIPTION
470 *
471 * -
472 *
473 * CHANGES
474 *
475 * Feb 1995 : Creation.
476 *
477 ******************************************************************************/
478
Translate(const VECTOR,const TRANSFORM * tr)479 void Mesh::Translate(const VECTOR, const TRANSFORM *tr)
480 {
481 Transform(tr);
482 }
483
484
485
486 /*****************************************************************************
487 *
488 * FUNCTION
489 *
490 * Rotate_Mesh
491 *
492 * INPUT
493 *
494 * OUTPUT
495 *
496 * RETURNS
497 *
498 * AUTHOR
499 *
500 * Dieter Bayer
501 *
502 * DESCRIPTION
503 *
504 * -
505 *
506 * CHANGES
507 *
508 * Feb 1995 : Creation.
509 *
510 ******************************************************************************/
511
Rotate(const VECTOR,const TRANSFORM * tr)512 void Mesh::Rotate(const VECTOR, const TRANSFORM *tr)
513 {
514 Transform(tr);
515 }
516
517
518
519 /*****************************************************************************
520 *
521 * FUNCTION
522 *
523 * Scale_Mesh
524 *
525 * INPUT
526 *
527 * OUTPUT
528 *
529 * RETURNS
530 *
531 * AUTHOR
532 *
533 * Dieter Bayer
534 *
535 * DESCRIPTION
536 *
537 * -
538 *
539 * CHANGES
540 *
541 * Feb 1995 : Creation.
542 *
543 ******************************************************************************/
544
Scale(const VECTOR,const TRANSFORM * tr)545 void Mesh::Scale(const VECTOR, const TRANSFORM *tr)
546 {
547 Transform(tr);
548 }
549
550
551
552 /*****************************************************************************
553 *
554 * FUNCTION
555 *
556 * Transfrom_Mesh
557 *
558 * INPUT
559 *
560 * OUTPUT
561 *
562 * RETURNS
563 *
564 * AUTHOR
565 *
566 * Dieter Bayer
567 *
568 * DESCRIPTION
569 *
570 * -
571 *
572 * CHANGES
573 *
574 * Feb 1995 : Creation.
575 *
576 ******************************************************************************/
577
Transform(const TRANSFORM * tr)578 void Mesh::Transform(const TRANSFORM *tr)
579 {
580 int i;
581
582 if (Trans == NULL)
583 {
584 Trans = Create_Transform();
585 }
586
587 Recompute_BBox(&BBox, tr);
588
589 Compose_Transforms(Trans, tr);
590
591 /* NK 1998 added if */
592 if (!Test_Flag(this, UV_FLAG))
593 for (i=0; i<Number_Of_Textures; i++)
594 Transform_Textures(Textures[i], tr);
595 }
596
597
598
599 /*****************************************************************************
600 *
601 * FUNCTION
602 *
603 * Invert_Mesh
604 *
605 * INPUT
606 *
607 * OUTPUT
608 *
609 * RETURNS
610 *
611 * AUTHOR
612 *
613 * Dieter Bayer
614 *
615 * DESCRIPTION
616 *
617 * -
618 *
619 * CHANGES
620 *
621 * Feb 1995 : Creation.
622 *
623 ******************************************************************************/
624
Invert()625 void Mesh::Invert()
626 {
627 Invert_Flag(this, INVERTED_FLAG);
628 }
629
630
631
632 /*****************************************************************************
633 *
634 * FUNCTION
635 *
636 * Create_Mesh
637 *
638 * INPUT
639 *
640 * OUTPUT
641 *
642 * RETURNS
643 *
644 * AUTHOR
645 *
646 * Dieter Bayer
647 *
648 * DESCRIPTION
649 *
650 * -
651 *
652 * CHANGES
653 *
654 * Feb 1995 : Creation.
655 *
656 ******************************************************************************/
657
Mesh()658 Mesh::Mesh() : ObjectBase(MESH_OBJECT)
659 {
660 Set_Flag(this, HIERARCHY_FLAG);
661
662 Trans = NULL;
663
664 Data = NULL;
665
666 has_inside_vector=false;
667
668 Number_Of_Textures=0; /* [LSK] these were uninitialized */
669 Textures=NULL;
670 }
671
672
673
674 /*****************************************************************************
675 *
676 * FUNCTION
677 *
678 * Copy_Mesh
679 *
680 * INPUT
681 *
682 * OUTPUT
683 *
684 * RETURNS
685 *
686 * AUTHOR
687 *
688 * Dieter Bayer
689 *
690 * DESCRIPTION
691 *
692 * Copy a mesh.
693 *
694 * NOTE: The components are not copied, only the number of references is
695 * counted, so that Destroy_Mesh() knows if they can be destroyed.
696 *
697 * -
698 *
699 * CHANGES
700 *
701 * Feb 1995 : Creation.
702 *
703 ******************************************************************************/
704
Copy()705 ObjectPtr Mesh::Copy()
706 {
707 Mesh *New = new Mesh();
708 int i;
709
710 Destroy_Transform(New->Trans);
711 *New = *this;
712 New->Trans = Copy_Transform(Trans);
713
714 New->Data = Data;
715 New->Data->References++;
716
717 /* NK 1999 copy textures */
718 if(Textures != NULL)
719 {
720 New->Textures = reinterpret_cast<TEXTURE **>(POV_MALLOC(Number_Of_Textures*sizeof(TEXTURE *), "triangle mesh data"));
721 for (i = 0; i < Number_Of_Textures; i++)
722 New->Textures[i] = Copy_Textures(Textures[i]);
723 }
724
725 return(New);
726 }
727
728
729
730 /*****************************************************************************
731 *
732 * FUNCTION
733 *
734 * Destroy_Mesh
735 *
736 * INPUT
737 *
738 * OUTPUT
739 *
740 * RETURNS
741 *
742 * AUTHOR
743 *
744 * Dieter Bayer
745 *
746 * DESCRIPTION
747 *
748 * -
749 *
750 * CHANGES
751 *
752 * Feb 1995 : Creation.
753 *
754 ******************************************************************************/
755
~Mesh()756 Mesh::~Mesh()
757 {
758 int i;
759
760 Destroy_Transform(Trans);
761
762 /* NK 1999 move texture outside of data block */
763 if (Textures != NULL)
764 {
765 for (i = 0; i < Number_Of_Textures; i++)
766 {
767 Destroy_Textures(Textures[i]);
768 }
769
770 POV_FREE(Textures);
771 }
772
773 if (--(Data->References) == 0)
774 {
775 Destroy_BBox_Tree(Data->Tree);
776
777 if (Data->Normals != NULL)
778 {
779 POV_FREE(Data->Normals);
780 }
781
782 /* NK 1998 */
783 if (Data->UVCoords != NULL)
784 {
785 POV_FREE(Data->UVCoords);
786 }
787 /* NK ---- */
788
789 if (Data->Vertices != NULL)
790 {
791 POV_FREE(Data->Vertices);
792 }
793
794 if (Data->Triangles != NULL)
795 {
796 POV_FREE(Data->Triangles);
797 }
798
799 POV_FREE(Data);
800 }
801 }
802
803
804
805 /*****************************************************************************
806 *
807 * FUNCTION
808 *
809 * Compute_Mesh_BBox
810 *
811 * INPUT
812 *
813 * Mesh - Mesh
814 *
815 * OUTPUT
816 *
817 * Mesh
818 *
819 * RETURNS
820 *
821 * AUTHOR
822 *
823 * Dieter Bayer
824 *
825 * DESCRIPTION
826 *
827 * Calculate the bounding box of a triangle.
828 *
829 * CHANGES
830 *
831 * Feb 1995 : Creation.
832 *
833 ******************************************************************************/
834
Compute_BBox()835 void Mesh::Compute_BBox()
836 {
837 int i;
838 VECTOR P1, P2, P3;
839 VECTOR mins, maxs;
840
841 Make_Vector(mins, BOUND_HUGE, BOUND_HUGE, BOUND_HUGE);
842 Make_Vector(maxs, -BOUND_HUGE, -BOUND_HUGE, -BOUND_HUGE);
843
844 for (i = 0; i < Data->Number_Of_Triangles; i++)
845 {
846 get_triangle_vertices(&Data->Triangles[i], P1, P2, P3);
847
848 mins[X] = min(mins[X], min3(P1[X], P2[X], P3[X]));
849 mins[Y] = min(mins[Y], min3(P1[Y], P2[Y], P3[Y]));
850 mins[Z] = min(mins[Z], min3(P1[Z], P2[Z], P3[Z]));
851
852 maxs[X] = max(maxs[X], max3(P1[X], P2[X], P3[X]));
853 maxs[Y] = max(maxs[Y], max3(P1[Y], P2[Y], P3[Y]));
854 maxs[Z] = max(maxs[Z], max3(P1[Z], P2[Z], P3[Z]));
855 }
856
857 Make_BBox_from_min_max(BBox, mins, maxs);
858 }
859
860
861
862 /*****************************************************************************
863 *
864 * FUNCTION
865 *
866 * Compute_Mesh
867 *
868 * INPUT
869 *
870 * OUTPUT
871 *
872 * RETURNS
873 *
874 * AUTHOR
875 *
876 * Dieter Bayer
877 *
878 * DESCRIPTION
879 *
880 * -
881 *
882 * CHANGES
883 *
884 * Feb 1995 : Creation.
885 *
886 ******************************************************************************/
887
Compute_Mesh_Triangle(MESH_TRIANGLE * Triangle,int Smooth,VECTOR P1,VECTOR P2,VECTOR P3,VECTOR S_Normal)888 bool Mesh::Compute_Mesh_Triangle(MESH_TRIANGLE *Triangle, int Smooth, VECTOR P1, VECTOR P2, VECTOR P3, VECTOR S_Normal)
889 {
890 int temp, swap;
891 DBL x, y, z;
892 VECTOR V1, V2, T1;
893 DBL Length;
894
895 VSub(V1, P2, P1);
896 VSub(V2, P3, P1);
897
898 VCross(S_Normal, V2, V1);
899
900 VLength(Length, S_Normal);
901
902 /* Set up a flag so we can ignore degenerate triangles */
903
904 if (Length == 0.0)
905 {
906 return(false);
907 }
908
909 /* Normalize the normal vector. */
910
911 VInverseScaleEq(S_Normal, Length);
912
913 VDot(Triangle->Distance, S_Normal, P1);
914
915 Triangle->Distance *= -1.0;
916
917 /* Find triangle's dominant axis. */
918
919 x = fabs(S_Normal[X]);
920 y = fabs(S_Normal[Y]);
921 z = fabs(S_Normal[Z]);
922
923 Triangle->Dominant_Axis = max3_coordinate(x, y, z);
924
925 swap = false;
926
927 switch (Triangle->Dominant_Axis)
928 {
929 case X:
930
931 if ((P2[Y] - P3[Y])*(P2[Z] - P1[Z]) < (P2[Z] - P3[Z])*(P2[Y] - P1[Y]))
932 {
933 swap = true;
934 }
935
936 break;
937
938 case Y:
939
940 if ((P2[X] - P3[X])*(P2[Z] - P1[Z]) < (P2[Z] - P3[Z])*(P2[X] - P1[X]))
941 {
942 swap = true;
943 }
944
945 break;
946
947 case Z:
948
949 if ((P2[X] - P3[X])*(P2[Y] - P1[Y]) < (P2[Y] - P3[Y])*(P2[X] - P1[X]))
950 {
951 swap = true;
952 }
953
954 break;
955 }
956
957 if (swap)
958 {
959 temp = Triangle->P2;
960 Triangle->P2 = Triangle->P1;
961 Triangle->P1 = temp;
962
963 /* NK 1998 */
964 temp = Triangle->UV2;
965 Triangle->UV2 = Triangle->UV1;
966 Triangle->UV1 = temp;
967
968 if (Triangle->ThreeTex)
969 {
970 temp = Triangle->Texture2;
971 Triangle->Texture2 = Triangle->Texture;
972 Triangle->Texture = temp;
973 }
974
975 Assign_Vector(T1, P1);
976 Assign_Vector(P1, P2);
977 Assign_Vector(P2, T1);
978
979 if (Smooth)
980 {
981 temp = Triangle->N2;
982 Triangle->N2 = Triangle->N1;
983 Triangle->N1 = temp;
984 }
985 }
986
987 if (Smooth)
988 {
989 // compute_smooth_triangle(Triangle, P1, P2, P3);
990 Triangle->Smooth = true;
991 }
992
993 compute_smooth_triangle(Triangle, P1, P2, P3);
994
995 return(true);
996 }
997
998
999
1000 /*****************************************************************************
1001 *
1002 * FUNCTION
1003 *
1004 * compute_smooth_triangle
1005 *
1006 * INPUT
1007 *
1008 * OUTPUT
1009 *
1010 * RETURNS
1011 *
1012 * AUTHOR
1013 *
1014 * Dieter Bayer
1015 *
1016 * DESCRIPTION
1017 *
1018 * -
1019 *
1020 * CHANGES
1021 *
1022 * Feb 1995 : Creation.
1023 *
1024 ******************************************************************************/
1025
compute_smooth_triangle(MESH_TRIANGLE * Triangle,const VECTOR P1,const VECTOR P2,const VECTOR P3)1026 void Mesh::compute_smooth_triangle(MESH_TRIANGLE *Triangle, const VECTOR P1, const VECTOR P2, const VECTOR P3)
1027 {
1028 VECTOR P3MinusP2, VTemp1, VTemp2;
1029 DBL x, y, z, uDenominator, Proj;
1030
1031 VSub(P3MinusP2, P3, P2);
1032
1033 x = fabs(P3MinusP2[X]);
1034 y = fabs(P3MinusP2[Y]);
1035 z = fabs(P3MinusP2[Z]);
1036
1037 Triangle->vAxis = max3_coordinate(x, y, z);
1038
1039 VSub(VTemp1, P2, P3);
1040
1041 VNormalize(VTemp1, VTemp1);
1042
1043 VSub(VTemp2, P1, P3);
1044
1045 VDot(Proj, VTemp2, VTemp1);
1046
1047 VScaleEq(VTemp1, Proj);
1048
1049 VSub(Triangle->Perp, VTemp1, VTemp2);
1050
1051 VNormalize(Triangle->Perp, Triangle->Perp);
1052
1053 VDot(uDenominator, VTemp2, Triangle->Perp);
1054
1055 VInverseScaleEq(Triangle->Perp, -uDenominator);
1056 }
1057
1058
1059
1060 /*****************************************************************************
1061 *
1062 * FUNCTION
1063 *
1064 * intersect_mesh_triangle
1065 *
1066 * INPUT
1067 *
1068 * OUTPUT
1069 *
1070 * RETURNS
1071 *
1072 * AUTHOR
1073 *
1074 * Dieter Bayer
1075 *
1076 * DESCRIPTION
1077 *
1078 * -
1079 *
1080 * CHANGES
1081 *
1082 * Feb 1995 : Creation.
1083 *
1084 ******************************************************************************/
1085
intersect_mesh_triangle(const Ray & ray,const MESH_TRIANGLE * Triangle,DBL * Depth) const1086 bool Mesh::intersect_mesh_triangle(const Ray &ray, const MESH_TRIANGLE *Triangle, DBL *Depth) const
1087 {
1088 DBL NormalDotOrigin, NormalDotDirection;
1089 DBL s, t;
1090 VECTOR P1, P2, P3, S_Normal;
1091
1092 Assign_Vector(S_Normal, Data->Normals[Triangle->Normal_Ind]);
1093
1094 VDot(NormalDotDirection, S_Normal, ray.Direction);
1095
1096 if (fabs(NormalDotDirection) < EPSILON)
1097 {
1098 return(false);
1099 }
1100
1101 VDot(NormalDotOrigin, S_Normal, ray.Origin);
1102
1103 *Depth = -(Triangle->Distance + NormalDotOrigin) / NormalDotDirection;
1104
1105 if ((*Depth < DEPTH_TOLERANCE) || (*Depth > MAX_DISTANCE))
1106 {
1107 return(false);
1108 }
1109
1110 get_triangle_vertices(Triangle, P1, P2, P3);
1111
1112 switch (Triangle->Dominant_Axis)
1113 {
1114 case X:
1115
1116 s = ray.Origin[Y] + *Depth * ray.Direction[Y];
1117 t = ray.Origin[Z] + *Depth * ray.Direction[Z];
1118
1119 if ((P2[Y] - s) * (P2[Z] - P1[Z]) < (P2[Z] - t) * (P2[Y] - P1[Y]))
1120 {
1121 return(false);
1122 }
1123
1124 if ((P3[Y] - s) * (P3[Z] - P2[Z]) < (P3[Z] - t) * (P3[Y] - P2[Y]))
1125 {
1126 return(false);
1127 }
1128
1129 if ((P1[Y] - s) * (P1[Z] - P3[Z]) < (P1[Z] - t) * (P1[Y] - P3[Y]))
1130 {
1131 return(false);
1132 }
1133
1134 return(true);
1135
1136 case Y:
1137
1138 s = ray.Origin[X] + *Depth * ray.Direction[X];
1139 t = ray.Origin[Z] + *Depth * ray.Direction[Z];
1140
1141 if ((P2[X] - s) * (P2[Z] - P1[Z]) < (P2[Z] - t) * (P2[X] - P1[X]))
1142 {
1143 return(false);
1144 }
1145
1146 if ((P3[X] - s) * (P3[Z] - P2[Z]) < (P3[Z] - t) * (P3[X] - P2[X]))
1147 {
1148 return(false);
1149 }
1150
1151 if ((P1[X] - s) * (P1[Z] - P3[Z]) < (P1[Z] - t) * (P1[X] - P3[X]))
1152 {
1153 return(false);
1154 }
1155
1156 return(true);
1157
1158 case Z:
1159
1160 s = ray.Origin[X] + *Depth * ray.Direction[X];
1161 t = ray.Origin[Y] + *Depth * ray.Direction[Y];
1162
1163 if ((P2[X] - s) * (P2[Y] - P1[Y]) < (P2[Y] - t) * (P2[X] - P1[X]))
1164 {
1165 return(false);
1166 }
1167
1168 if ((P3[X] - s) * (P3[Y] - P2[Y]) < (P3[Y] - t) * (P3[X] - P2[X]))
1169 {
1170 return(false);
1171 }
1172
1173 if ((P1[X] - s) * (P1[Y] - P3[Y]) < (P1[Y] - t) * (P1[X] - P3[X]))
1174 {
1175 return(false);
1176 }
1177
1178 return(true);
1179 }
1180
1181 return(false);
1182 }
1183
1184 /*
1185 * MeshUV - By Xander Enzmann
1186 *
1187 * Currently unused
1188 *
1189 */
1190
1191 const DBL BARY_VAL1 = -0.00001;
1192 const DBL BARY_VAL2 = 1.00001;
1193
MeshUV(const VECTOR P,const MESH_TRIANGLE * Triangle,UV_VECT Result) const1194 void Mesh::MeshUV(const VECTOR P, const MESH_TRIANGLE *Triangle, UV_VECT Result) const
1195 {
1196 DBL a, b, r;
1197 VECTOR Q, B[3], IB[3], P1, P2, P3;
1198 UV_VECT UV1, UV2, UV3;
1199
1200 get_triangle_vertices(Triangle, P1, P2, P3);
1201 VSub(B[0], P2, P1);
1202 VSub(B[1], P3, P1);
1203 Assign_Vector(B[2], Data->Normals[Triangle->Normal_Ind]);
1204
1205 if (!MInvers3(B, IB)) {
1206 // Failed to invert - that means this is a degenerate triangle
1207 Result[U] = P[X];
1208 Result[V] = P[Y];
1209 return;
1210 }
1211
1212 VSub(Q, P, P1);
1213 VDot(a, Q, IB[0]);
1214 VDot(b, Q, IB[1]);
1215
1216 if (a < BARY_VAL1 || b < BARY_VAL1 || a + b > BARY_VAL2)
1217 {
1218 // The use of BARY_VAL1 is an attempt to compensate for the
1219 // lack of precision in the floating point numbers used in
1220 // the matrices B and IB. Since floats only have around
1221 // 7 digits of precision, we make sure that we allow any
1222 // slop in a and b that is less than that. */
1223 Result[U] = P[X];
1224 Result[V] = P[Y];
1225 return;
1226 }
1227
1228 r = 1.0f - a - b;
1229
1230 get_triangle_uvcoords(Triangle, UV1, UV2, UV3);
1231 VScale(Q, UV1, r);
1232 VAddScaledEq(Q, a, UV2);
1233 VAddScaledEq(Q, b, UV3);
1234
1235 Result[U] = Q[U];
1236 Result[V] = Q[V];
1237 }
1238
1239
1240 /*****************************************************************************
1241 *
1242 * FUNCTION
1243 *
1244 * test_hit
1245 *
1246 * INPUT
1247 *
1248 * OUTPUT
1249 *
1250 * RETURNS
1251 *
1252 * AUTHOR
1253 *
1254 * Dieter Bayer
1255 *
1256 * DESCRIPTION
1257 *
1258 * Test if a hit is valid and push if on the intersection depth.
1259 *
1260 * CHANGES
1261 *
1262 * Feb 1995 : Creation.
1263 *
1264 ******************************************************************************/
1265
test_hit(const MESH_TRIANGLE * Triangle,const Ray & OrigRay,DBL Depth,DBL len,IStack & Depth_Stack,TraceThreadData * Thread)1266 bool Mesh::test_hit(const MESH_TRIANGLE *Triangle, const Ray &OrigRay, DBL Depth, DBL len, IStack& Depth_Stack, TraceThreadData *Thread)
1267 {
1268 VECTOR IPoint;
1269 DBL world_dist = Depth / len;
1270
1271 VEvaluateRay(IPoint, OrigRay.Origin, world_dist, OrigRay.Direction);
1272
1273 if (Clip.empty() || Point_In_Clip(IPoint, Clip, Thread))
1274 {
1275 /*
1276 don't bother calling MeshUV because we reclaculate it later (if needed) anyway
1277 UV_VECT uv;
1278 VECTOR P; // Object coordinates of intersection
1279 VEvaluateRay(P, ray.Origin, Depth, ray.Direction);
1280
1281 MeshUV(P, Triangle, Mesh, uv);
1282
1283 push_entry_pointer_uv(world_dist, IPoint, uv, Object, Triangle, Depth_Stack);
1284 */
1285
1286 Depth_Stack->push(Intersection(world_dist, IPoint, this, Triangle));
1287 return(true);
1288 }
1289
1290 return(false);
1291 }
1292
1293
1294
1295 /*****************************************************************************
1296 *
1297 * FUNCTION
1298 *
1299 * Init_Mesh_Triangle
1300 *
1301 * INPUT
1302 *
1303 * OUTPUT
1304 *
1305 * RETURNS
1306 *
1307 * AUTHOR
1308 *
1309 * Dieter Bayer
1310 *
1311 * DESCRIPTION
1312 *
1313 * -
1314 *
1315 * CHANGES
1316 *
1317 * Feb 1995 : Creation.
1318 *
1319 ******************************************************************************/
1320
Init_Mesh_Triangle(MESH_TRIANGLE * Triangle)1321 void Mesh::Init_Mesh_Triangle(MESH_TRIANGLE *Triangle)
1322 {
1323 Triangle->Smooth = false;
1324 Triangle->ThreeTex = false;
1325 Triangle->Dominant_Axis = 0;
1326 Triangle->vAxis = 0;
1327
1328 Triangle->P1 =
1329 Triangle->P2 =
1330 Triangle->P3 = -1;
1331
1332 Triangle->Normal_Ind = -1;
1333 Triangle->Texture2 =
1334 Triangle->Texture3 = -1;
1335
1336 Triangle->Texture = -1;
1337
1338 Triangle->N1 =
1339 Triangle->N2 =
1340 Triangle->N3 = -1;
1341
1342 Triangle->UV1 =
1343 Triangle->UV2 =
1344 Triangle->UV3 = -1;
1345
1346 Make_Vector(Triangle->Perp, 0.0, 0.0, 0.0);
1347
1348 Triangle->Distance = 0.0;
1349 }
1350
1351
1352
1353 /*****************************************************************************
1354 *
1355 * FUNCTION
1356 *
1357 * get_triangle_bbox
1358 *
1359 * INPUT
1360 *
1361 * Triangle - Pointer to triangle
1362 *
1363 * OUTPUT
1364 *
1365 * BBox - Bounding box
1366 *
1367 * RETURNS
1368 *
1369 * AUTHOR
1370 *
1371 * Dieter Bayer
1372 *
1373 * DESCRIPTION
1374 *
1375 * Calculate the bounding box of a triangle.
1376 *
1377 * CHANGES
1378 *
1379 * Sep 1994 : Creation.
1380 *
1381 ******************************************************************************/
1382
get_triangle_bbox(const MESH_TRIANGLE * Triangle,BBOX * BBox) const1383 void Mesh::get_triangle_bbox(const MESH_TRIANGLE *Triangle, BBOX *BBox) const
1384 {
1385 VECTOR P1, P2, P3;
1386 VECTOR Min, Max;
1387
1388 get_triangle_vertices(Triangle, P1, P2, P3);
1389
1390 Min[X] = min3(P1[X], P2[X], P3[X]);
1391 Min[Y] = min3(P1[Y], P2[Y], P3[Y]);
1392 Min[Z] = min3(P1[Z], P2[Z], P3[Z]);
1393
1394 Max[X] = max3(P1[X], P2[X], P3[X]);
1395 Max[Y] = max3(P1[Y], P2[Y], P3[Y]);
1396 Max[Z] = max3(P1[Z], P2[Z], P3[Z]);
1397
1398 Make_BBox_from_min_max(*BBox, Min, Max);
1399 }
1400
1401
1402
1403 /*****************************************************************************
1404 *
1405 * FUNCTION
1406 *
1407 * Build_Mesh_BBox_Tree
1408 *
1409 * INPUT
1410 *
1411 * OUTPUT
1412 *
1413 * RETURNS
1414 *
1415 * AUTHOR
1416 *
1417 * Dieter Bayer
1418 *
1419 * DESCRIPTION
1420 *
1421 * Create the bounding box hierarchy.
1422 *
1423 * CHANGES
1424 *
1425 * Feb 1995 : Creation. (Derived from the bounding slab creation code)
1426 *
1427 ******************************************************************************/
1428
Build_Mesh_BBox_Tree()1429 void Mesh::Build_Mesh_BBox_Tree()
1430 {
1431 int i, nElem, maxelements;
1432 BBOX_TREE **Triangles;
1433
1434 if (!Test_Flag(this, HIERARCHY_FLAG))
1435 {
1436 return;
1437 }
1438
1439 nElem = (int)Data->Number_Of_Triangles;
1440
1441 maxelements = 2 * nElem;
1442
1443 /* Now allocate an array to hold references to these elements. */
1444
1445 Triangles = reinterpret_cast<BBOX_TREE **>(POV_MALLOC(maxelements*sizeof(BBOX_TREE *), "mesh bbox tree"));
1446
1447 /* Init list with mesh elements. */
1448
1449 for (i = 0; i < nElem; i++)
1450 {
1451 Triangles[i] = reinterpret_cast<BBOX_TREE *>(POV_MALLOC(sizeof(BBOX_TREE), "mesh bbox tree"));
1452
1453 Triangles[i]->Infinite = false;
1454 Triangles[i]->Entries = 0;
1455 Triangles[i]->Node = reinterpret_cast<BBOX_TREE **>(&Data->Triangles[i]);
1456
1457 get_triangle_bbox(&Data->Triangles[i], &Triangles[i]->BBox);
1458 }
1459
1460 size_t maxfinitecount = 0;
1461 Build_BBox_Tree(&Data->Tree, nElem, Triangles, 0, NULL, maxfinitecount);
1462
1463 /* Get rid of the Triangles array. */
1464
1465 POV_FREE(Triangles);
1466 }
1467
1468
1469
1470 /*****************************************************************************
1471 *
1472 * FUNCTION
1473 *
1474 * intersect_bbox_tree
1475 *
1476 * INPUT
1477 *
1478 * Mesh - Mesh object
1479 * Ray - Current ray
1480 * Orig_Ray - Original, untransformed ray
1481 * len - Length of the transformed ray direction
1482 *
1483 * OUTPUT
1484 *
1485 * Depth_Stack - Stack of intersections
1486 *
1487 * RETURNS
1488 *
1489 * int - true if an intersection was found
1490 *
1491 * AUTHOR
1492 *
1493 * Dieter Bayer
1494 *
1495 * DESCRIPTION
1496 *
1497 * Intersect a ray with the bounding box tree of a mesh.
1498 *
1499 * CHANGES
1500 *
1501 * Feb 1995 : Creation.
1502 *
1503 ******************************************************************************/
1504
intersect_bbox_tree(const Ray & ray,const Ray & Orig_Ray,DBL len,IStack & Depth_Stack,TraceThreadData * Thread)1505 bool Mesh::intersect_bbox_tree(const Ray &ray, const Ray &Orig_Ray, DBL len, IStack& Depth_Stack, TraceThreadData *Thread)
1506 {
1507 bool found;
1508 int i;
1509 DBL Best, Depth;
1510 const BBOX_TREE *Node, *Root;
1511 short OldStyle= has_inside_vector;
1512
1513 /* Create the direction vectors for this ray. */
1514 Rayinfo rayinfo(ray);
1515
1516 /* Start with an empty priority queue. */
1517 Thread->Mesh_Queue.QSize = 0;
1518 found = false;
1519
1520 Best = BOUND_HUGE;
1521
1522 #ifdef BBOX_EXTRA_STATS
1523 Thread->Stats()[totalQueueResets]++;
1524 #endif
1525
1526 /* Check top node. */
1527
1528 Root = Data->Tree;
1529
1530 /* Set the root object infinite to avoid a test. */
1531
1532 Check_And_Enqueue(Thread->Mesh_Queue, Root, &Root->BBox, &rayinfo, Thread);
1533
1534 /* Check elements in the priority queue. */
1535
1536 while (Thread->Mesh_Queue.QSize != 0)
1537 {
1538 Priority_Queue_Delete(Thread->Mesh_Queue, &Depth, &Node);
1539
1540 /*
1541 * If current intersection is larger than the best intersection found
1542 * so far our task is finished, because all other bounding boxes in
1543 * the priority queue are further away.
1544 */
1545
1546 /* NK 1999 - had to comment this out for use with CSG
1547 if (Depth > Best)
1548 {
1549 break;
1550 }
1551 */
1552 if ( !OldStyle && Depth > Best)
1553 break;
1554
1555 /* Check current node. */
1556
1557 if (Node->Entries)
1558 {
1559 /* This is a node containing leaves to be checked. */
1560
1561 for (i = 0; i < Node->Entries; i++)
1562 Check_And_Enqueue(Thread->Mesh_Queue, Node->Node[i], &Node->Node[i]->BBox, &rayinfo, Thread);
1563 }
1564 else
1565 {
1566 /* This is a leaf so test the contained triangle. */
1567
1568 if (intersect_mesh_triangle(ray, reinterpret_cast<MESH_TRIANGLE *>(Node->Node), &Depth))
1569 {
1570 if (test_hit(reinterpret_cast<MESH_TRIANGLE *>(Node->Node), Orig_Ray, Depth, len, Depth_Stack, Thread))
1571 {
1572 found = true;
1573
1574 Best = Depth;
1575 }
1576 }
1577 }
1578 }
1579
1580 return(found);
1581 }
1582
1583
1584
1585 /*****************************************************************************
1586 *
1587 * FUNCTION
1588 *
1589 * mesh_hash
1590 *
1591 * INPUT
1592 *
1593 * aPoint - Normal/Vertex to store
1594 *
1595 * OUTPUT
1596 *
1597 * Hash_Table - Normal/Vertex hash table
1598 * Number - Number of normals/vertices
1599 * Max - Max. number of normals/vertices
1600 * Elements - List of normals/vertices
1601 *
1602 * RETURNS
1603 *
1604 * int - Index of normal/vertex into the normals/vertices list
1605 *
1606 * AUTHOR
1607 *
1608 * Dieter Bayer
1609 *
1610 * DESCRIPTION
1611 *
1612 * Try to locate a triangle normal/vertex in the normal/vertex list.
1613 * If the vertex is not found its stored in the normal/vertex list.
1614 *
1615 * CHANGES
1616 *
1617 * Feb 1995 : Creation. (With help from Steve Anger's RAW2POV code)
1618 *
1619 ******************************************************************************/
1620
mesh_hash(HASH_TABLE ** Hash_Table,int * Number,int * Max,SNGL_VECT ** Elements,const VECTOR aPoint)1621 int Mesh::mesh_hash(HASH_TABLE **Hash_Table, int *Number, int *Max, SNGL_VECT **Elements, const VECTOR aPoint)
1622 {
1623 int hash;
1624 SNGL_VECT D, P;
1625 HASH_TABLE *p;
1626
1627 Assign_Vector(P, aPoint);
1628
1629 /* Get hash value. */
1630
1631 hash = (unsigned)((int)(326.0*P[X])^(int)(694.7*P[Y])^(int)(1423.6*P[Z])) % HASH_SIZE;
1632
1633 /* Try to find normal/vertex. */
1634
1635 for (p = Hash_Table[hash]; p != NULL; p = p->Next)
1636 {
1637 VSub(D, p->P, P);
1638
1639 if ((fabs(D[X]) < EPSILON) && (fabs(D[Y]) < EPSILON) && (fabs(D[Z]) < EPSILON))
1640 {
1641 break;
1642 }
1643 }
1644
1645 if ((p != NULL) && (p->Index >= 0))
1646 {
1647 return(p->Index);
1648 }
1649
1650 /* Add new normal/vertex to the list and hash table. */
1651
1652 if ((*Number) >= (*Max))
1653 {
1654 if ((*Max) >= INT_MAX/2)
1655 {
1656 throw POV_EXCEPTION_STRING("Too many normals/vertices in mesh.");
1657 }
1658
1659 (*Max) *= 2;
1660
1661 (*Elements) = reinterpret_cast<SNGL_VECT *>(POV_REALLOC((*Elements), (*Max)*sizeof(SNGL_VECT), "mesh data"));
1662 }
1663
1664 Assign_Vector((*Elements)[*Number], P);
1665
1666 p = reinterpret_cast<HASH_TABLE *>(POV_MALLOC(sizeof(HASH_TABLE), "mesh data"));
1667
1668 Assign_Vector(p->P, P);
1669
1670 p->Index = *Number;
1671
1672 p->Next = Hash_Table[hash];
1673
1674 Hash_Table[hash] = p;
1675
1676 return((*Number)++);
1677 }
1678
1679
1680
1681 /*****************************************************************************
1682 *
1683 * FUNCTION
1684 *
1685 * Mesh_Hash_Vertex
1686 *
1687 * INPUT
1688 *
1689 * Vertex - Vertex to store
1690 *
1691 * OUTPUT
1692 *
1693 * Number_Of_Vertices - Number of vertices
1694 * Max_Vertices - Max. number of vertices
1695 * Vertices - List of vertices
1696 *
1697 * RETURNS
1698 *
1699 * int - Index of vertex into the vertices list
1700 *
1701 * AUTHOR
1702 *
1703 * Dieter Bayer
1704 *
1705 * DESCRIPTION
1706 *
1707 * Try to locate a triangle vertex in the vertex list.
1708 * If the vertex is not found its stored in the vertex list.
1709 *
1710 * CHANGES
1711 *
1712 * Feb 1995 : Creation. (With help from Steve Anger's RAW2POV code)
1713 *
1714 ******************************************************************************/
1715
Mesh_Hash_Vertex(int * Number_Of_Vertices,int * Max_Vertices,SNGL_VECT ** Vertices,const VECTOR Vertex)1716 int Mesh::Mesh_Hash_Vertex(int *Number_Of_Vertices, int *Max_Vertices, SNGL_VECT **Vertices, const VECTOR Vertex)
1717 {
1718 return(mesh_hash(Vertex_Hash_Table, Number_Of_Vertices, Max_Vertices, Vertices, Vertex));
1719 }
1720
1721
1722
1723 /*****************************************************************************
1724 *
1725 * FUNCTION
1726 *
1727 * Mesh_Hash_Normal
1728 *
1729 * INPUT
1730 *
1731 * Normal - Normal to store
1732 *
1733 * OUTPUT
1734 *
1735 * Number_Of_Normals - Number of normals
1736 * Max_Normals - Max. number of normals
1737 * Normals - List of normals
1738 *
1739 * RETURNS
1740 *
1741 * int - Index of normal into the normals list
1742 *
1743 * AUTHOR
1744 *
1745 * Dieter Bayer
1746 *
1747 * DESCRIPTION
1748 *
1749 * Try to locate a triangle normal in the normal list.
1750 * If the normal is not found its stored in the normal list.
1751 *
1752 * CHANGES
1753 *
1754 * Feb 1995 : Creation. (With help from Steve Anger's RAW2POV code)
1755 *
1756 ******************************************************************************/
1757
Mesh_Hash_Normal(int * Number_Of_Normals,int * Max_Normals,SNGL_VECT ** Normals,const VECTOR S_Normal)1758 int Mesh::Mesh_Hash_Normal(int *Number_Of_Normals, int *Max_Normals, SNGL_VECT **Normals, const VECTOR S_Normal)
1759 {
1760 return(mesh_hash(Normal_Hash_Table, Number_Of_Normals, Max_Normals, Normals, S_Normal));
1761 }
1762
1763
1764
1765 /*****************************************************************************
1766 *
1767 * FUNCTION
1768 *
1769 * Mesh_Hash_Texture
1770 *
1771 * INPUT
1772 *
1773 * Texture - Texture to store
1774 *
1775 * OUTPUT
1776 *
1777 * Number_Of_Textures - Number of textures
1778 * Max_Textures - Max. number of textures
1779 * Textures - List of textures
1780 *
1781 * RETURNS
1782 *
1783 * int - Index of texture into the texture list
1784 *
1785 * AUTHOR
1786 *
1787 * Dieter Bayer
1788 *
1789 * DESCRIPTION
1790 *
1791 * Try to locate a texture in the texture list.
1792 * If the texture is not found its stored in the texture list.
1793 *
1794 * CHANGES
1795 *
1796 * Feb 1995 : Creation.
1797 *
1798 ******************************************************************************/
1799
Mesh_Hash_Texture(int * Number_Of_Textures,int * Max_Textures,TEXTURE *** Textures,TEXTURE * Texture)1800 int Mesh::Mesh_Hash_Texture(int *Number_Of_Textures, int *Max_Textures, TEXTURE ***Textures, TEXTURE *Texture)
1801 {
1802 int i;
1803
1804 if (Texture == NULL)
1805 {
1806 return(-1);
1807 }
1808
1809 /* Just do a linear search. */
1810
1811 for (i = 0; i < *Number_Of_Textures; i++)
1812 {
1813 if ((*Textures)[i] == Texture)
1814 {
1815 break;
1816 }
1817 }
1818
1819 if (i == *Number_Of_Textures)
1820 {
1821 if ((*Number_Of_Textures) >= (*Max_Textures))
1822 {
1823 if ((*Max_Textures) >= INT_MAX/2)
1824 {
1825 throw POV_EXCEPTION_STRING("Too many textures in mesh.");
1826 }
1827
1828 (*Max_Textures) *= 2;
1829
1830 (*Textures) = reinterpret_cast<TEXTURE **>(POV_REALLOC((*Textures), (*Max_Textures)*sizeof(TEXTURE *), "mesh data"));
1831 }
1832
1833 (*Textures)[(*Number_Of_Textures)++] = Copy_Texture_Pointer(Texture);
1834 }
1835
1836 return(i);
1837 }
1838
1839 /*****************************************************************************
1840 *
1841 * FUNCTION
1842 *
1843 * Mesh_Hash_UV
1844 *
1845 * INPUT
1846 *
1847 * aPoint - UV vector to store
1848 *
1849 * OUTPUT
1850 *
1851 * Hash_Table - UV vector hash table
1852 * Number - Number of UV vectors
1853 * Max - Max. number of UV vectors
1854 * Elements - List of UV vectors
1855 *
1856 * RETURNS
1857 *
1858 * int - Index of UV vector into the UV vector list
1859 *
1860 * AUTHOR
1861 *
1862 * Dieter Bayer / Nathan Kopp
1863 *
1864 * DESCRIPTION
1865 *
1866 * adapted from mesh_hash
1867 *
1868 * CHANGES
1869 *
1870 *
1871 ******************************************************************************/
1872
Mesh_Hash_UV(int * Number,int * Max,UV_VECT ** Elements,const UV_VECT aPoint)1873 int Mesh::Mesh_Hash_UV(int *Number, int *Max, UV_VECT **Elements, const UV_VECT aPoint)
1874 {
1875 int hash;
1876 UV_VECT D, P;
1877 UV_HASH_TABLE *p;
1878
1879 Assign_UV_Vect(P, aPoint);
1880
1881 /* Get hash value. */
1882
1883 hash = (unsigned)((int)(326.0*P[U])^(int)(694.7*P[V])) % HASH_SIZE;
1884
1885 /* Try to find normal/vertex. */
1886
1887 for (p = UV_Hash_Table[hash]; p != NULL; p = p->Next)
1888 {
1889 /* VSub(D, p->P, P); */
1890 D[U] = p->P[U] - P[U];
1891 D[V] = p->P[V] - P[V];
1892
1893 if ((fabs(D[U]) < EPSILON) && (fabs(D[V]) < EPSILON))
1894 {
1895 break;
1896 }
1897 }
1898
1899 if ((p != NULL) && (p->Index >= 0))
1900 {
1901 return(p->Index);
1902 }
1903
1904 /* Add new normal/vertex to the list and hash table. */
1905
1906 if ((*Number) >= (*Max))
1907 {
1908 if ((*Max) >= INT_MAX/2)
1909 {
1910 throw POV_EXCEPTION_STRING("Too many normals/vertices in mesh.");
1911 }
1912
1913 (*Max) *= 2;
1914
1915 (*Elements) = reinterpret_cast<UV_VECT *>(POV_REALLOC((*Elements), (*Max)*sizeof(UV_VECT), "mesh data"));
1916 }
1917
1918 Assign_UV_Vect((*Elements)[*Number], P);
1919
1920 p = reinterpret_cast<UV_HASH_TABLE *>(POV_MALLOC(sizeof(UV_HASH_TABLE), "mesh data"));
1921
1922 Assign_UV_Vect(p->P, P);
1923
1924 p->Index = *Number;
1925
1926 p->Next = UV_Hash_Table[hash];
1927
1928 UV_Hash_Table[hash] = p;
1929
1930 return((*Number)++);
1931 }
1932
1933
1934
1935 /*****************************************************************************
1936 *
1937 * FUNCTION
1938 *
1939 * Create_Mesh_Hash_Tables
1940 *
1941 * INPUT
1942 *
1943 * OUTPUT
1944 *
1945 * RETURNS
1946 *
1947 * AUTHOR
1948 *
1949 * Dieter Bayer
1950 *
1951 * DESCRIPTION
1952 *
1953 * -
1954 *
1955 * CHANGES
1956 *
1957 * Feb 1995 : Creation.
1958 *
1959 ******************************************************************************/
1960
Create_Mesh_Hash_Tables()1961 void Mesh::Create_Mesh_Hash_Tables()
1962 {
1963 int i;
1964
1965 Vertex_Hash_Table = reinterpret_cast<HASH_TABLE **>(POV_MALLOC(HASH_SIZE*sizeof(HASH_TABLE *), "mesh hash table"));
1966
1967 for (i = 0; i < HASH_SIZE; i++)
1968 {
1969 Vertex_Hash_Table[i] = NULL;
1970 }
1971
1972 Normal_Hash_Table = reinterpret_cast<HASH_TABLE **>(POV_MALLOC(HASH_SIZE*sizeof(HASH_TABLE *), "mesh hash table"));
1973
1974 for (i = 0; i < HASH_SIZE; i++)
1975 {
1976 Normal_Hash_Table[i] = NULL;
1977 }
1978
1979 /* NK 1998 */
1980 UV_Hash_Table = reinterpret_cast<UV_HASH_TABLE **>(POV_MALLOC(HASH_SIZE*sizeof(UV_HASH_TABLE *), "mesh hash table"));
1981
1982 for (i = 0; i < HASH_SIZE; i++)
1983 {
1984 UV_Hash_Table[i] = NULL;
1985 }
1986 /* NK ---- */
1987 }
1988
1989
1990
1991 /*****************************************************************************
1992 *
1993 * FUNCTION
1994 *
1995 * Destroy_Mesh_Hash_Tables
1996 *
1997 * INPUT
1998 *
1999 * OUTPUT
2000 *
2001 * RETURNS
2002 *
2003 * AUTHOR
2004 *
2005 * Dieter Bayer
2006 *
2007 * DESCRIPTION
2008 *
2009 * -
2010 *
2011 * CHANGES
2012 *
2013 * Feb 1995 : Creation.
2014 *
2015 ******************************************************************************/
2016
Destroy_Mesh_Hash_Tables()2017 void Mesh::Destroy_Mesh_Hash_Tables()
2018 {
2019 int i;
2020 HASH_TABLE *Temp;
2021 /* NK 1998 */
2022 UV_HASH_TABLE *UVTemp;
2023 /* NK ---- */
2024
2025 for (i = 0; i < HASH_SIZE; i++)
2026 {
2027 while (Vertex_Hash_Table[i] != NULL)
2028 {
2029 Temp = Vertex_Hash_Table[i];
2030
2031 Vertex_Hash_Table[i] = Temp->Next;
2032
2033 POV_FREE(Temp);
2034 }
2035 }
2036
2037 POV_FREE(Vertex_Hash_Table);
2038
2039 for (i = 0; i < HASH_SIZE; i++)
2040 {
2041 while (Normal_Hash_Table[i] != NULL)
2042 {
2043 Temp = Normal_Hash_Table[i];
2044
2045 Normal_Hash_Table[i] = Temp->Next;
2046
2047 POV_FREE(Temp);
2048 }
2049 }
2050
2051 POV_FREE(Normal_Hash_Table);
2052
2053 /* NK 1998 */
2054 for (i = 0; i < HASH_SIZE; i++)
2055 {
2056 while (UV_Hash_Table[i] != NULL)
2057 {
2058 UVTemp = UV_Hash_Table[i];
2059
2060 UV_Hash_Table[i] = UVTemp->Next;
2061
2062 POV_FREE(UVTemp);
2063 }
2064 }
2065
2066 POV_FREE(UV_Hash_Table);
2067 /* NK ---- */
2068 }
2069
2070
2071
2072 /*****************************************************************************
2073 *
2074 * FUNCTION
2075 *
2076 * get_triangle_vertices
2077 *
2078 * INPUT
2079 *
2080 * Mesh - Mesh object
2081 * Triangle - Triangle
2082 *
2083 * OUTPUT
2084 *
2085 * RETURNS
2086 *
2087 * P1, P2, P3 - Vertices of the triangle
2088 *
2089 * AUTHOR
2090 *
2091 * Dieter Bayer
2092 *
2093 * DESCRIPTION
2094 *
2095 * -
2096 *
2097 * CHANGES
2098 *
2099 * Feb 1995 : Creation.
2100 *
2101 ******************************************************************************/
2102
get_triangle_vertices(const MESH_TRIANGLE * Triangle,VECTOR P1,VECTOR P2,VECTOR P3) const2103 void Mesh::get_triangle_vertices(const MESH_TRIANGLE *Triangle, VECTOR P1, VECTOR P2, VECTOR P3) const
2104 {
2105 Assign_Vector(P1, Data->Vertices[Triangle->P1]);
2106 Assign_Vector(P2, Data->Vertices[Triangle->P2]);
2107 Assign_Vector(P3, Data->Vertices[Triangle->P3]);
2108 }
2109
2110
2111
2112 /*****************************************************************************
2113 *
2114 * FUNCTION
2115 *
2116 * get_triangle_normals
2117 *
2118 * INPUT
2119 *
2120 * Mesh - Mesh object
2121 * Triangle - Triangle
2122 *
2123 * OUTPUT
2124 *
2125 * RETURNS
2126 *
2127 * N1, N2, N3 - Normals of the triangle
2128 *
2129 * AUTHOR
2130 *
2131 * Dieter Bayer
2132 *
2133 * DESCRIPTION
2134 *
2135 * -
2136 *
2137 * CHANGES
2138 *
2139 * Feb 1995 : Creation.
2140 *
2141 ******************************************************************************/
2142
get_triangle_normals(const MESH_TRIANGLE * Triangle,VECTOR N1,VECTOR N2,VECTOR N3) const2143 void Mesh::get_triangle_normals(const MESH_TRIANGLE *Triangle, VECTOR N1, VECTOR N2, VECTOR N3) const
2144 {
2145 Assign_Vector(N1, Data->Normals[Triangle->N1]);
2146 Assign_Vector(N2, Data->Normals[Triangle->N2]);
2147 Assign_Vector(N3, Data->Normals[Triangle->N3]);
2148 }
2149
2150
2151 /*****************************************************************************
2152 *
2153 * FUNCTION
2154 *
2155 * get_triangle_uvcoords
2156 *
2157 * INPUT
2158 *
2159 * Mesh - Mesh object
2160 * Triangle - Triangle
2161 *
2162 * OUTPUT
2163 *
2164 * RETURNS
2165 *
2166 * UV1, UV2, UV3 - UV coordinates of the triangle's corners
2167 *
2168 * AUTHOR
2169 *
2170 * Nathan Kopp
2171 *
2172 * DESCRIPTION
2173 *
2174 * adapted from get_triangle_normals
2175 *
2176 * CHANGES
2177 *
2178 ******************************************************************************/
2179
get_triangle_uvcoords(const MESH_TRIANGLE * Triangle,UV_VECT UV1,UV_VECT UV2,UV_VECT UV3) const2180 void Mesh::get_triangle_uvcoords(const MESH_TRIANGLE *Triangle, UV_VECT UV1, UV_VECT UV2, UV_VECT UV3) const
2181 {
2182 Assign_UV_Vect(UV1, Data->UVCoords[Triangle->UV1]);
2183 Assign_UV_Vect(UV2, Data->UVCoords[Triangle->UV2]);
2184 Assign_UV_Vect(UV3, Data->UVCoords[Triangle->UV3]);
2185 }
2186
2187
2188 /*****************************************************************************
2189 *
2190 * FUNCTION
2191 *
2192 * Mesh_Degenerate
2193 *
2194 * INPUT
2195 *
2196 * P1, P2, P3 - Triangle's vertices
2197 *
2198 * OUTPUT
2199 *
2200 * RETURNS
2201 *
2202 * int - true if degenerate
2203 *
2204 * AUTHOR
2205 *
2206 * Dieter Bayer
2207 *
2208 * DESCRIPTION
2209 *
2210 * Test if a triangle is degenerate.
2211 *
2212 * CHANGES
2213 *
2214 * Feb 1995 : Creation.
2215 *
2216 ******************************************************************************/
2217
Degenerate(const VECTOR P1,const VECTOR P2,const VECTOR P3)2218 bool Mesh::Degenerate(const VECTOR P1, const VECTOR P2, const VECTOR P3)
2219 {
2220 VECTOR V1, V2, Temp;
2221 DBL Length;
2222
2223 VSub(V1, P1, P2);
2224 VSub(V2, P3, P2);
2225
2226 VCross(Temp, V1, V2);
2227
2228 VLength(Length, Temp);
2229
2230 return(Length == 0.0);
2231 }
2232
2233
2234 /*****************************************************************************
2235 *
2236 * FUNCTION
2237 *
2238 * Test_Mesh_Opacity
2239 *
2240 * INPUT
2241 *
2242 * Mesh - Pointer to mesh structure
2243 *
2244 * OUTPUT
2245 *
2246 * Mesh
2247 *
2248 * RETURNS
2249 *
2250 * AUTHOR
2251 *
2252 * Dieter Bayer
2253 *
2254 * DESCRIPTION
2255 *
2256 * Set the opacity flag of the mesh according to the opacity
2257 * of the mesh's texture(s).
2258 *
2259 * CHANGES
2260 *
2261 * Apr 1996 : Creation.
2262 *
2263 ******************************************************************************/
2264
Test_Mesh_Opacity()2265 void Mesh::Test_Mesh_Opacity()
2266 {
2267 int i;
2268
2269 /* Initialize opacity flag to the opacity of the object's texture. */
2270
2271 if ((Texture == NULL) || (Test_Opacity(Texture)))
2272 {
2273 Set_Flag(this, OPAQUE_FLAG);
2274 }
2275
2276 if (Test_Flag(this, MULTITEXTURE_FLAG))
2277 {
2278 for (i = 0; i < Number_Of_Textures; i++)
2279 {
2280 if (Textures[i] != NULL)
2281 {
2282 /* If component's texture isn't opaque the mesh is neither. */
2283
2284 if (!Test_Opacity(Textures[i]))
2285 {
2286 Clear_Flag(this, OPAQUE_FLAG);
2287 }
2288 }
2289 }
2290 }
2291 }
2292
2293
2294
2295 /*****************************************************************************
2296 *
2297 * FUNCTION
2298 *
2299 * Mesh_UVCoord
2300 *
2301 * INPUT
2302 *
2303 * OUTPUT
2304 *
2305 * RETURNS
2306 *
2307 * AUTHOR
2308 *
2309 * Nathan Kopp
2310 *
2311 * DESCRIPTION
2312 *
2313 * computes the UV coordinates of the intersection for a mesh
2314 *
2315 ******************************************************************************/
2316
UVCoord(VECTOR Result,const Intersection * Inter,TraceThreadData *) const2317 void Mesh::UVCoord(VECTOR Result, const Intersection *Inter, TraceThreadData *) const
2318 {
2319 DBL w1, w2, w3, t1, t2;
2320 VECTOR vA, vB;
2321 VECTOR Side1, Side2;
2322 const MESH_TRIANGLE *Triangle;
2323 VECTOR P;
2324
2325 if (Trans != NULL)
2326 MInvTransPoint(P, Inter->IPoint, Trans);
2327 else
2328 Assign_Vector(P, Inter->IPoint);
2329
2330 Triangle = reinterpret_cast<const MESH_TRIANGLE *>(Inter->Pointer);
2331
2332 /* ---------------- this is for P1 ---------------- */
2333 /* Side1 is opposite side, Side2 is an adjacent side (vector pointing away) */
2334 VSub(Side1, Data->Vertices[Triangle->P3], Data->Vertices[Triangle->P2]);
2335 VSub(Side2, Data->Vertices[Triangle->P3], Data->Vertices[Triangle->P1]);
2336
2337 /* find A */
2338 /* A is a vector from this vertex to the intersection point */
2339 VSub(vA, P, Data->Vertices[Triangle->P1]);
2340
2341 /* find B */
2342 /* B is a vector from this intersection to the opposite side (Side1) */
2343 /* which is the exact length to get to the side */
2344 /* to do this we split Side2 into two components, but only keep the */
2345 /* one that's perp to Side2 */
2346 VDot(t1, Side2, Side1);
2347 VDot(t2, Side1, Side1);
2348 VScale(vB, Side1, t1/t2);
2349 VSubEq(vB, Side2);
2350
2351 /* finding the weight is the scale part of a projection of A onto B */
2352 VDot(t1, vA, vB);
2353 VDot(t2, vB, vB);
2354 /* w1 = 1-fabs(t1/t2); */
2355 w1 = 1+t1/t2;
2356
2357 /* ---------------- this is for P2 ---------------- */
2358 VSub(Side1, Data->Vertices[Triangle->P3], Data->Vertices[Triangle->P1]);
2359 VSub(Side2, Data->Vertices[Triangle->P3], Data->Vertices[Triangle->P2]);
2360
2361 /* find A */
2362 VSub(vA, P, Data->Vertices[Triangle->P2]);
2363
2364 /* find B */
2365 VDot(t1, Side2, Side1);
2366 VDot(t2, Side1, Side1);
2367 VScale(vB, Side1, t1/t2);
2368 VSubEq(vB, Side2);
2369
2370 VDot(t1, vA, vB);
2371 VDot(t2, vB, vB);
2372 /* w2 = 1-fabs(t1/t2); */
2373 w2 = 1+t1/t2;
2374
2375 /* ---------------- this is for P3 ---------------- */
2376 VSub(Side1, Data->Vertices[Triangle->P2], Data->Vertices[Triangle->P1]);
2377 VSub(Side2, Data->Vertices[Triangle->P2], Data->Vertices[Triangle->P3]);
2378
2379 /* find A */
2380 VSub(vA, P, Data->Vertices[Triangle->P3]);
2381
2382 /* find B */
2383 VDot(t1, Side2, Side1);
2384 VDot(t2, Side1, Side1);
2385 VScale(vB, Side1, t1/t2);
2386 VSubEq(vB, Side2);
2387
2388 VDot(t1, vA, vB);
2389 VDot(t2, vB, vB);
2390 /* w3 = 1-fabs(t1/t2); */
2391 w3 = 1+t1/t2;
2392
2393 Result[U] = w1 * Data->UVCoords[Triangle->UV1][U] +
2394 w2 * Data->UVCoords[Triangle->UV2][U] +
2395 w3 * Data->UVCoords[Triangle->UV3][U];
2396 Result[V] = w1 * Data->UVCoords[Triangle->UV1][V] +
2397 w2 * Data->UVCoords[Triangle->UV2][V] +
2398 w3 * Data->UVCoords[Triangle->UV3][V];
2399 }
2400
2401
2402 /*****************************************************************************
2403 *
2404 * FUNCTION
2405 *
2406 * inside_bbox_tree
2407 *
2408 * INPUT
2409 *
2410 * Mesh - Mesh object
2411 * Ray - Current ray
2412 *
2413 * OUTPUT
2414 *
2415 * RETURNS
2416 *
2417 * int - true if inside the object
2418 *
2419 * AUTHOR
2420 *
2421 * Nathan Kopp & Dieter Bayer
2422 *
2423 * DESCRIPTION
2424 *
2425 * Check if a point is within the bounding box tree of a mesh.
2426 *
2427 * CHANGES
2428 *
2429 * Oct 1998 : Creation.
2430 *
2431 ******************************************************************************/
2432
inside_bbox_tree(const Ray & ray,TraceThreadData * Thread) const2433 bool Mesh::inside_bbox_tree(const Ray &ray, TraceThreadData *Thread) const
2434 {
2435 int i, found;
2436 DBL Best, Depth;
2437 const BBOX_TREE *Node, *Root;
2438
2439 /* Create the direction vectors for this ray. */
2440 Rayinfo rayinfo(ray);
2441
2442 /* Start with an empty priority queue. */
2443 Thread->Mesh_Queue.QSize = 0;
2444 found = 0;
2445
2446 Best = BOUND_HUGE;
2447
2448 #ifdef BBOX_EXTRA_STATS
2449 Thread->Stats()[totalQueueResets]++;
2450 #endif
2451
2452 /* Check top node. */
2453 Root = Data->Tree;
2454
2455 /* Set the root object infinite to avoid a test. */
2456 Check_And_Enqueue(Thread->Mesh_Queue, Root, &Root->BBox, &rayinfo, Thread);
2457
2458 /* Check elements in the priority queue. */
2459 while (Thread->Mesh_Queue.QSize != 0)
2460 {
2461 Priority_Queue_Delete(Thread->Mesh_Queue, &Depth, &Node);
2462
2463 /* Check current node. */
2464 if (Node->Entries)
2465 {
2466 /* This is a node containing leaves to be checked. */
2467 for (i = 0; i < Node->Entries; i++)
2468 Check_And_Enqueue(Thread->Mesh_Queue, Node->Node[i], &Node->Node[i]->BBox, &rayinfo, Thread);
2469 }
2470 else
2471 {
2472 /* This is a leaf so test the contained triangle. */
2473
2474 if (intersect_mesh_triangle(ray, reinterpret_cast<MESH_TRIANGLE *>(Node->Node), &Depth))
2475 {
2476 /* actually, this should push onto a local depth stack and
2477 make sure that we don't have the same intersection point from
2478 two (or three) different triangles!!!!! */
2479 found++;
2480 }
2481 }
2482 }
2483
2484 /* odd number = inside, even number = outside */
2485 return ((found & 1) != 0);
2486 }
2487
Determine_Textures(Intersection * isect,bool hitinside,WeightedTextureVector & textures,TraceThreadData * Threaddata)2488 void Mesh::Determine_Textures(Intersection *isect, bool hitinside, WeightedTextureVector& textures, TraceThreadData *Threaddata)
2489 {
2490 const MESH_TRIANGLE *tri = reinterpret_cast<const MESH_TRIANGLE *>(isect->Pointer);
2491
2492 if((Interior_Texture != NULL) && (hitinside == true)) // useful feature for checking mesh orientation and other effects [trf]
2493 textures.push_back(WeightedTexture(1.0, Interior_Texture));
2494 else if(tri->ThreeTex)
2495 {
2496 VECTOR p1, p2, p3;
2497 VECTOR epoint;
2498 COLC w1, w2, w3;
2499 COLC wsum;
2500
2501 if(Trans != NULL)
2502 MInvTransPoint(epoint, isect->IPoint, Trans);
2503 else
2504 Assign_Vector(epoint, isect->IPoint);
2505
2506 Assign_Vector(p1, Data->Vertices[tri->P1]);
2507 Assign_Vector(p2, Data->Vertices[tri->P2]);
2508 Assign_Vector(p3, Data->Vertices[tri->P3]);
2509
2510 w1 = 1.0 - COLC(SmoothTriangle::Calculate_Smooth_T(epoint, p1, p2, p3));
2511 w2 = 1.0 - COLC(SmoothTriangle::Calculate_Smooth_T(epoint, p2, p3, p1));
2512 w3 = 1.0 - COLC(SmoothTriangle::Calculate_Smooth_T(epoint, p3, p1, p2));
2513
2514 wsum = 1.0 / (w1 + w2 + w3);
2515
2516 textures.push_back(WeightedTexture(w1 * wsum, Textures[tri->Texture]));
2517 textures.push_back(WeightedTexture(w2 * wsum, Textures[tri->Texture2]));
2518 textures.push_back(WeightedTexture(w3 * wsum, Textures[tri->Texture3]));
2519 }
2520 else if(tri->Texture >= 0) // TODO FIXME - make sure there always is some valid texture, also for code above! [trf]
2521 textures.push_back(WeightedTexture(1.0, Textures[tri->Texture]));
2522 else if(Texture != NULL)
2523 textures.push_back(WeightedTexture(1.0, Texture));
2524 }
2525
2526 }
2527