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