This 'little' program behaves bad when compiled with -O. It works fine
when no -O or -O0 is used.

The function is from Graphics Gem I and has been ported from C to C++
http://www.acm.org/pubs/tog/GraphicsGems/gems.html#gems  
Woo, Andrew, Fast Ray-Box Intersection, p. 395-396, code: p. 736-737

This is how things went when compiling on my Debian unstable (current as
of 2006-06-18).  
The problem has also been encountererd on redhat rhel (3?) but not
investigated there.

No flags were used except -On  (The program do compile cleanly with
-Wall -W -pedantic)
 

         -O0  -O1   -O2   -O3
g++-2.95  ok error error error
g++-3.3   ok error error error
g++-3.4   ok  ok   error error
g++-4.0   ok error error error
g++-4.1   ok error error error

g++ -v output for each compiler it further down.

Have I done something wrong or is this something for the bugzilla?

minus



// ********** Start of program

#include <iostream>
#include <vector>

using namespace std;

class GeoPoint
{
public:
  inline GeoPoint(double east, double north, double height)
  {elt_[0]=east;elt_[1]=north;elt_[2]=height;}

  GeoPoint& operator-=(const GeoPoint& p) {
    elt_[0] -= p[0]; elt_[1] -= p[1]; elt_[2] -= p[2];    
    return *this;
  }
  GeoPoint& operator-=(const double p) {
    elt_[0]-=p; elt_[1]-=p; elt_[2]-=p;    
    return *this;
  }
  GeoPoint& operator+=(const double p) {
    elt_[0]+=p; elt_[1]+=p; elt_[2]+=p;    
    return *this;
  }
  double &operator[](int i) { return elt_[i]; }
  const double &operator[](int i) const { return elt_[i]; }

private:
  double elt_[3];
  
private:
  friend std::ostream& operator<<(std::ostream& s,const GeoPoint& a);  
};

std::ostream& operator<<(std::ostream& s,const GeoPoint& a)
{
  s << " ( " << a[0] << " " << a[1] << " " << a[2] << " ) ";
  return s;
}


/*********************************************************************/

bool rayBoxIntersection(const GeoPoint& ll,
                        const GeoPoint& ur,
                        const GeoPoint& start,
                        const GeoPoint& end,
                        GeoPoint& coord)
{
  typedef enum {RIGHT,LEFT,MIDDLE} PlaneRelative;
  const int NumberOfDimensions=3;

  bool inside=true;
  PlaneRelative quadrant[NumberOfDimensions];
  GeoPoint candidatePlane(0.0,0.0,0.0);
  
  GeoPoint dir(end);
  dir-=start;

  GeoPoint maxT(-1,-1,-1);

  // Find candidate planes
  for (int i=0; i<NumberOfDimensions; i++) {
    if (start[i]<ll[i]) {
      quadrant[i] = LEFT;
      candidatePlane[i]=ll[i];
      inside=false;
    } else if (start[i]>ur[i]) {
      quadrant[i] = RIGHT;
      candidatePlane[i]=ur[i];
      inside=false;;
      
    } else {
      quadrant[i] = MIDDLE;
    }
  }

  if (inside) {
    coord=start;
    return true;
  }
  
  // calculate T distances to candidate planes
  for (int i=0; i<NumberOfDimensions; i++) {
    if (quadrant[i]!=MIDDLE && dir[i] !=0.0) {
      maxT[i]=(candidatePlane[i]-start[i])/dir[i];
    } else {
      maxT[i]=-1.0;
    }
  }
  
  //get largest maxT for final choice of intersection
  int whichPlane=0;
  for (int i=1; i<NumberOfDimensions; i++) {
    if (maxT[whichPlane]<maxT[i]) {
      whichPlane=i;
    }
  }
  
  if (maxT[whichPlane]<0.0) {
    // didn't hit the box
    return (false);
  }
  
  for (int i=0; i<NumberOfDimensions; i++) {
    if (whichPlane==i) {
      coord[i]=candidatePlane[i];
    } else {
      coord[i]=start[i]+maxT[whichPlane]*dir[i];
      // **** Uncomment one of these to make the program work.
      //sleep(0);
      //cerr << "";
      if ((coord[i]<ll[i]) || (coord[i]>ur[i])) {
        // outside box
        return false;
      } 
    } 
  }
  return true;
}

/*********************************************************************/

int main(void)
{
  vector<GeoPoint> p;

  // define three boxes.
  p.push_back(GeoPoint(1.004,1.004,1.004));   // at start of line
  p.push_back(GeoPoint(1.020,1.020,1.020));   // middle of line
  p.push_back(GeoPoint(1.046,1.046,1.046));   // at end of line

  GeoPoint start(1.000,1.000,1.000);
  GeoPoint end(1.050,1.050,1.050);

  for (vector<GeoPoint>::const_iterator iter=p.begin();
       iter!=p.end();
       ++iter)
  {
    GeoPoint ll(*iter);
    GeoPoint ur(*iter);
    
    ll-=0.005;
    ur+=0.005;

    GeoPoint hit(-1,-1,-1);
    GeoPoint hitreverse(-1,-1,-1);
    
    // find where the first hit inside the box (ll,ur) of the 
    // line between start and end
    bool res1=rayBoxIntersection(ll,ur,start,end,hit);
    
    // find where the first hit inside the box (ll,ur) of the 
    // line between end and start  (the reverse direction compared
    // to the previous call)
    bool res2=rayBoxIntersection(ll,ur,end,start,hitreverse);
    
    if (res1 && res2) {
      cout << "ok: " << endl;
    } else {
      cout << "error" << endl;
    }
  }

  return 0;
}

// ********** End of program






// **********  output from g++ -v for each compiler used.

Reading specs from /usr/lib/gcc-lib/i486-linux-gnu/2.95.4/specs
gcc version 2.95.4 20011002 (Debian prerelease)

Reading specs from /usr/lib/gcc-lib/i486-linux-gnu/3.3.6/specs
Configured with: ../src/configure -v --enable-languages=c,c++
--prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info
--with-gxx-include-dir=/usr/include/c++/3.3 --enable-shared
--enable-__cxa_atexit --with-system-zlib --enable-nls
--without-included-gettext --enable-clocale=gnu --enable-debug
i486-linux-gnu
Thread model: posix
gcc version 3.3.6 (Debian 1:3.3.6-13)


Reading specs from /usr/lib/gcc/i486-linux-gnu/3.4.6/specs
Configured with: ../src/configure -v --enable-languages=c,c++,f77,pascal
--prefix=/usr --libexecdir=/usr/lib
--with-gxx-include-dir=/usr/include/c++/3.4 --enable-shared
--with-system-zlib --enable-nls --without-included-gettext
--program-suffix=-3.4 --enable-__cxa_atexit --enable-clocale=gnu
--enable-libstdcxx-debug --with-tune=i686 i486-linux-gnu
Thread model: posix
gcc version 3.4.6 (Debian 3.4.6-2)


Using built-in specs.
Target: i486-linux-gnu
Configured with: ../src/configure -v --enable-languages=c,c
++,java,f95,objc,ada,treelang --prefix=/usr --enable-shared
--with-system-zlib --libexecdir=/usr/lib --without-included-gettext
--enable-threads=posix --enable-nls --program-suffix=-4.0
--enable-__cxa_atexit --enable-clocale=gnu --enable-libstdcxx-debug
--enable-java-awt=gtk-default --enable-gtk-cairo
--with-java-home=/usr/lib/jvm/java-1.4.2-gcj-4.0-1.4.2.0/jre
--enable-mpfr --disable-werror --with-tune=i686
--enable-checking=release i486-linux-gnu
Thread model: posix
gcc version 4.0.4 20060507 (prerelease) (Debian 4.0.3-3)


Using built-in specs.
Target: i486-linux-gnu
Configured with: ../src/configure -v --enable-languages=c,c
++,java,fortran,objc,obj-c++,ada,treelang --prefix=/usr --enable-shared
--with-system-zlib --libexecdir=/usr/lib --without-included-gettext
--enable-threads=posix --enable-nls --program-suffix=-4.1
--enable-__cxa_atexit --enable-clocale=gnu --enable-libstdcxx-debug
--enable-java-awt=gtk --enable-gtk-cairo
--with-java-home=/usr/lib/jvm/java-1.4.2-gcj-4.1-1.4.2.0/jre
--enable-mpfr --with-tune=i686 --enable-checking=release i486-linux-gnu
Thread model: posix
gcc version 4.1.2 20060613 (prerelease) (Debian 4.1.1-5)


-- 

Reply via email to