#include <osgViewer/Viewer>
#include <osgDB/WriteFile>
const
int GRID_WIDTH = 1024;
const
int GRID_HEIGHT = 800;
#pragma comment(lib, "osgd.lib")
#pragma comment(lib, "osgViewerd.lib")
#pragma comment(lib, "osgDBd.lib")
class
CRay
{
public :
CRay(osg::Vec3 orgin, osg::Vec3 direction)
:_orgin(orgin)
,_direction(direction)
{
}
osg::Vec3 GetOrgin()
{
return
_orgin;
}
void
SetOrgin(osg::Vec3 orgin)
{
_orgin = orgin;
}
osg::Vec3 GetDirection()
{
return
_direction;
}
void
SetDirection(osg::Vec3 dir)
{
_direction = dir;
}
osg::Vec3 GetPoint( float
t)
{
return
_orgin + _direction * t;
}
private :
osg::Vec3 _orgin;
osg::Vec3 _direction;
float
_t;
};
class
CIntersectResult
{
public :
CIntersectResult()
:_isHit( false )
{
}
static
CIntersectResult NoHit()
{
return
CIntersectResult();
}
public :
bool
_isHit;
float
_distance;
osg::Vec3 _position;
osg::Vec3 _normal;
};
class
CGeometry
{
public :
CGeometry()
{
}
virtual
CIntersectResult IsIntersect(CRay ray) = 0;
};
class
CSphere : public
CGeometry
{
public :
CSphere()
:CGeometry()
{
}
CSphere(osg::Vec3 center, double
radius)
:CGeometry()
,_center(center)
,_radius(radius)
{
}
CSphere(CSphere & s)
{
_center = s.GetCenter();
_radius = s.GetRadius();
}
void
SetCenter(osg::Vec3 & center)
{
_center = center;
}
void
SetRadius( float
radius)
{
_radius = radius;
}
osg::Vec3 GetCenter()
{
return
_center;
}
float
GetRadius()
{
return
_radius;
}
osg::Vec3 GetNormal(osg::Vec3 p)
{
return
p - _center;
}
virtual
CIntersectResult IsIntersect(CRay ray)
{
CIntersectResult result = CIntersectResult::NoHit();
osg::Vec3 v = ray.GetOrgin() - _center;
float
a0 = v * v - _radius * _radius;
float
dir_dot_v = ray.GetDirection() * v;
if
(dir_dot_v < 0)
{
float
discr = dir_dot_v * dir_dot_v - a0;
if
(discr >= 0)
{
result._isHit = true ;
result._distance = -dir_dot_v - std:: sqrt (discr);
result._position = ray.GetPoint(result._distance);
result._normal = result._position - _center;
result._normal.normalize();
}
}
return
result;
}
private :
osg::Vec3 _center;
float
_radius;
};
class
CPerspectiveCamera
{
public :
CPerspectiveCamera()
{
}
~CPerspectiveCamera()
{
}
CPerspectiveCamera( const
osg::Vec3 & eye, const
osg::Vec3 & front, const
osg::Vec3 & refUp, float
fov)
{
_eye = eye;
_front = front;
_refUp = refUp;
_fov = fov;
_right = _front ^ _refUp;
_up = _right ^ _front;
_fovScale = std:: tan (fov * osg::PI * 0.5 / 180.0) * 2.0;
}
CRay GenerateRay( float
x, float
y)
{
osg::Vec3 r = _right * ((x - 0.5f) * _fovScale);
osg::Vec3 u = _up * ((y - 0.5f) * _fovScale);
osg::Vec3 temp = _front + r + u;
temp.normalize();
return
CRay(_eye, temp);
}
private :
osg::Vec3 _eye;
osg::Vec3 _front;
osg::Vec3 _refUp;
float
_fov;
osg::Vec3 _right;
osg::Vec3 _up;
float
_fovScale;
};
osg::ref_ptr<osg::Image> CreateImage()
{
osg::ref_ptr<osg::Image> image = new
osg::Image;
image->allocateImage(1024, 800, 1, GL_RGBA, GL_UNSIGNED_BYTE);
unsigned char
* data = image->data();
CPerspectiveCamera camera(osg::Vec3(0.0, 10.0, 10), osg::Vec3(0.0, 0.0, -1.0), osg::Vec3(0.0, 1.0, 0.0), 90);
float
depth = 7.0;
float
maxDepth = 18.0;
CSphere sphere(osg::Vec3(0.0, 10, -10.0), 10.0);
float
dx = 1.0f/GRID_WIDTH;
float
dy = 1.0f/GRID_HEIGHT;
float
dDepth = 255.0f/maxDepth;
int
i = 0;
for
( int
y = 0; y < GRID_HEIGHT; ++y)
{
float
sy = 1 - dy * y;
for
( int
x = 0; x < GRID_WIDTH; ++x)
{
float
sx = dx * x;
CRay ray(camera.GenerateRay(sx, sy));
CIntersectResult result = sphere.IsIntersect(ray);
if
(result._isHit)
{
float
t = std::min(result._distance * dDepth, 255.0f);
int
depth = ( int )(255 - t);
data[i] = depth;
data[i+1] = depth;
data[i+2] = depth;
data[i+3] = 255;
}
i += 4;
}
}
return
image.get();
}
int
main()
{
osg::ref_ptr<osg::Image> image = CreateImage();
osgDB::writeImageFile(*image.get(), "H:/1.png" );
return
0;
}
|