@@ -665,7 +665,7 @@ relative to the ray so we can early exit as soon as we have a hit.
665665//=============================================================================
666666/** Return intersection of a ray with the heightmap mesh.
667667This is a quick version that just checks every polygon inside
668- a 2D bounding rectangle of the ray projected onto the heightfield plane.
668+ a 2D bounding rectangle of the ray projected onto the height map plane.
669669For most of our view-picking cases the ray is almost perpendicular to the
670670map plane so this is very quick (small bounding box). But it can become slow
671671for arbitrary rays such as those used in AI visibility checks(2 units on
@@ -678,19 +678,22 @@ bool BaseHeightMapRenderObjClass::Cast_Ray(RayCollisionTestClass & raytest)
678678 Bool hit = false ;
679679 Int X,Y;
680680 Vector3 normal,P0 ,P1 ,P2 ,P3 ;
681+ Bool hasP0 = false ;
682+ Bool hasP1 = false ;
681683
682684 if (!m_map)
683685 return false ; // need valid pointer to heightmap samples
684- // HeightSampleType *pData = m_map->getDataPtr();
685- // Clip ray to extents of heightfield
686+
687+ // Clip ray to extents of height map
686688 AABoxClass hbox;
687689 LineSegClass lineseg,lineseg2;
688690 CastResultStruct result;
689- Int StartCellX = 0 ;
690- Int EndCellX = 0 ;
691- Int StartCellY = 0 ;
692- Int EndCellY = 0 ;
693- const Int overhang = 2 *VERTEX_BUFFER_TILE_LENGTH + m_map->getBorderSizeInline (); // Allow picking past the edge for scrolling & objects.
691+ Int startCellX = 0 ;
692+ Int startCellY = 0 ;
693+ Int endCellX = 0 ;
694+ Int endCellY = 0 ;
695+ const Int borderSize = m_map->getBorderSizeInline ();
696+ const Int overhang = 2 *VERTEX_BUFFER_TILE_LENGTH + borderSize; // Allow picking past the edge for scrolling & objects.
694697 Vector3 minPt (MAP_XY_FACTOR *(-overhang), MAP_XY_FACTOR *(-overhang), -MAP_XY_FACTOR );
695698 Vector3 maxPt (MAP_XY_FACTOR *(m_map->getXExtent ()+overhang),
696699 MAP_XY_FACTOR *(m_map->getYExtent ()+overhang), MAP_HEIGHT_SCALE *m_map->getMaxHeightValue ()+MAP_XY_FACTOR );
@@ -699,84 +702,94 @@ bool BaseHeightMapRenderObjClass::Cast_Ray(RayCollisionTestClass & raytest)
699702
700703 lineseg=raytest.Ray ;
701704
702- // Set initial ray endpoints
703- P0 = raytest.Ray .Get_P0 ();
704- P1 = raytest.Ray .Get_P1 ();
705- result.ComputeContactPoint =true ;
706-
707705 Int p;
708706 for (p=0 ; p<3 ; p++) {
709707 // find intersection point of ray and terrain bounding box
710708 result.Reset ();
711709 result.ComputeContactPoint =true ;
710+ Bool newP0 = false ;
711+ Bool newP1 = false ;
712+
712713 if (CollisionMath::Collide (lineseg,hbox,&result))
713- { // ray intersects terrain or starts inside the terrain.
714+ {
715+ // ray intersects terrain or starts inside the terrain.
714716 if (!result.StartBad ) // check if start point inside terrain
715- P0 = result.ContactPoint ; // make intersection point the new start of the ray.
717+ {
718+ newP0 = P0 != result.ContactPoint ;
719+ hasP0 = true ;
720+ P0 = result.ContactPoint ; // make intersection point the new start of the ray.
721+ }
716722
717- // reverse direction of original ray and clip again to extent of
718- // heightmap
723+ // reverse direction of original ray and clip again to extent of heightmap
719724 result.Fraction =1 .0f ; // reset the result
720725 result.StartBad =false ;
721726 lineseg2.Set (lineseg.Get_P1 (),lineseg.Get_P0 ()); // reverse line segment
722727 if (CollisionMath::Collide (lineseg2,hbox,&result))
723- { if (!result.StartBad ) // check if end point inside terrain
724- P1 = result.ContactPoint ; // make intersection point the new end pont of ray
728+ {
729+ if (!result.StartBad ) // check if end point inside terrain
730+ {
731+ newP1 = P1 != result.ContactPoint ;
732+ hasP1 = true ;
733+ P1 = result.ContactPoint ; // make intersection point the new end point of ray
734+ }
725735 }
726- } else {
727- if (p==0 ) return (false );
728- break ;
729736 }
730737
738+ if (!newP0 || !newP1)
739+ break ;
740+
731741 // Take the 2D bounding box of ray and check heights
732742 // inside this box for intersection.
733743 if (P0 .X > P1 .X ) { // flip start/end points
734- StartCellX = REAL_TO_INT_FLOOR (P1 .X /MAP_XY_FACTOR );
735- EndCellX = REAL_TO_INT_CEIL (P0 .X /MAP_XY_FACTOR );
744+ startCellX = REAL_TO_INT_FLOOR (P1 .X /MAP_XY_FACTOR );
745+ endCellX = REAL_TO_INT_CEIL (P0 .X /MAP_XY_FACTOR );
736746 } else {
737- StartCellX = REAL_TO_INT_FLOOR (P0 .X /MAP_XY_FACTOR );
738- EndCellX = REAL_TO_INT_CEIL (P1 .X /MAP_XY_FACTOR );
747+ startCellX = REAL_TO_INT_FLOOR (P0 .X /MAP_XY_FACTOR );
748+ endCellX = REAL_TO_INT_CEIL (P1 .X /MAP_XY_FACTOR );
739749 }
740750 if (P0 .Y > P1 .Y ) { // flip start/end points
741- StartCellY = REAL_TO_INT_FLOOR (P1 .Y /MAP_XY_FACTOR );
742- EndCellY = REAL_TO_INT_CEIL (P0 .Y /MAP_XY_FACTOR );
751+ startCellY = REAL_TO_INT_FLOOR (P1 .Y /MAP_XY_FACTOR );
752+ endCellY = REAL_TO_INT_CEIL (P0 .Y /MAP_XY_FACTOR );
743753 } else {
744- StartCellY = REAL_TO_INT_FLOOR (P0 .Y /MAP_XY_FACTOR );
745- EndCellY = REAL_TO_INT_CEIL (P1 .Y /MAP_XY_FACTOR );
754+ startCellY = REAL_TO_INT_FLOOR (P0 .Y /MAP_XY_FACTOR );
755+ endCellY = REAL_TO_INT_CEIL (P1 .Y /MAP_XY_FACTOR );
746756 }
747757
748758 Int i, j, minHt, maxHt;
749759
750760 minHt = m_map->getMaxHeightValue ();
751761 maxHt = 0 ;
752762
753- for (j=StartCellY ; j<=EndCellY ; j++) {
754- for (i=StartCellX ; i<=EndCellX ; i++) {
755- Short cur = getClipHeight (i+m_map-> getBorderSizeInline () ,j+m_map-> getBorderSizeInline () );
763+ for (j=startCellY ; j<=endCellY ; j++) {
764+ for (i=startCellX ; i<=endCellX ; i++) {
765+ Short cur = getClipHeight (i+borderSize ,j+borderSize );
756766 if (cur<minHt) minHt = cur;
757767 if (maxHt<cur) maxHt = cur;
758768 }
759769 }
760- Vector3 minPt (MAP_XY_FACTOR *(StartCellX -1 ), MAP_XY_FACTOR *(StartCellY -1 ), MAP_HEIGHT_SCALE *(minHt-1 ));
761- Vector3 maxPt (MAP_XY_FACTOR *(EndCellX +1 ), MAP_XY_FACTOR *(EndCellY +1 ), MAP_HEIGHT_SCALE *(maxHt+1 ));
770+ Vector3 minPt (MAP_XY_FACTOR *(startCellX -1 ), MAP_XY_FACTOR *(startCellY -1 ), MAP_HEIGHT_SCALE *(minHt-1 ));
771+ Vector3 maxPt (MAP_XY_FACTOR *(endCellX +1 ), MAP_XY_FACTOR *(endCellY +1 ), MAP_HEIGHT_SCALE *(maxHt+1 ));
762772 MinMaxAABoxClass mmbox (minPt, maxPt);
763773 hbox.Init (mmbox);
764774 }
765775
776+ if (!hasP0 || !hasP1)
777+ return false ;
778+
766779 raytest.Result ->ComputeContactPoint =true ; // tell CollisionMath that we need point.
767780
768781 // Adjust indexes into the bordered height map.
769782
770- StartCellX += m_map-> getBorderSizeInline () ;
771- EndCellX += m_map-> getBorderSizeInline () ;
772- StartCellY += m_map-> getBorderSizeInline () ;
773- EndCellY += m_map-> getBorderSizeInline () ;
783+ startCellX += borderSize ;
784+ endCellX += borderSize ;
785+ startCellY += borderSize ;
786+ endCellY += borderSize ;
774787
775788 Int offset;
776789 for (offset = 1 ; offset < 5 ; offset *= 3 ) {
777- for (Y=StartCellY -offset; Y<=EndCellY +offset; Y++) {
790+ for (Y=startCellY -offset; Y<=endCellY +offset; Y++) {
778791
779- for (X=StartCellX -offset; X<=EndCellX +offset; X++) {
792+ for (X=startCellX -offset; X<=endCellX +offset; X++) {
780793 // test the 2 triangles in this cell
781794 // 3-----2
782795 // | /|
0 commit comments