forked from 0ad/0ad
janwas
5bf9bca9ef
there are too many W4 and "potentially uninitialized", so those are disabled by 0ad_warning_disable.h. the silly "int x = strlen" and very dangerous "int x = (void*)p" (and vice versa) problems are fixed. This was SVN commit r5526.
204 lines
4.7 KiB
C++
204 lines
4.7 KiB
C++
#include "precompiled.h"
|
|
#include "0ad_warning_disable.h"
|
|
# include <math.h>
|
|
# include "sr_box.h"
|
|
# include "sr_plane.h"
|
|
# include "sr_camera.h"
|
|
|
|
//# define SR_USE_TRACE1 // ray
|
|
# include "sr_trace.h"
|
|
|
|
//=================================== SrCamera ===================================
|
|
|
|
SrCamera::SrCamera ()
|
|
{
|
|
init ();
|
|
}
|
|
|
|
SrCamera::SrCamera ( const SrCamera &c )
|
|
:eye(c.eye), center(c.center), up(c.up)
|
|
{
|
|
fovy = c.fovy;
|
|
znear = c.znear;
|
|
zfar = c.zfar;
|
|
aspect = c.aspect;
|
|
scale = c.scale;
|
|
}
|
|
|
|
SrCamera::SrCamera ( const SrPnt& e, const SrPnt& c, const SrVec& u )
|
|
: eye(e), center(c), up(u)
|
|
{
|
|
fovy = SR_TORAD(60);
|
|
znear = 0.1f;
|
|
zfar = 1000.0f;
|
|
aspect = 1.0f;
|
|
}
|
|
|
|
void SrCamera::init ()
|
|
{
|
|
eye.set ( 0, 0, 2.0f );
|
|
center = SrVec::null;
|
|
up = SrVec::j;
|
|
fovy = SR_TORAD(60);
|
|
znear = 0.1f;
|
|
zfar = 1000.0f;
|
|
aspect = 1.0f;
|
|
scale = 1.0f;
|
|
}
|
|
|
|
SrMat& SrCamera::get_view_mat ( SrMat &m ) const
|
|
{
|
|
m.look_at ( eye, center, up );
|
|
return m;
|
|
}
|
|
|
|
SrMat& SrCamera::get_perspective_mat ( SrMat &m ) const
|
|
{
|
|
m.perspective ( fovy, aspect, znear, zfar );
|
|
return m;
|
|
}
|
|
|
|
// screenpt coords range in [-1,1]
|
|
void SrCamera::get_ray ( float winx, float winy, SrVec &p1, SrVec &p2 ) const
|
|
{
|
|
p1.set ( winx, winy, znear ); // p1 is in the near clip plane
|
|
|
|
SrMat M(SrMat::NotInitialized), V(SrMat::NotInitialized), P(SrMat::NotInitialized);
|
|
|
|
V.look_at ( eye, center, up );
|
|
P.perspective ( fovy, aspect, znear, zfar );
|
|
|
|
M.mult ( V, P ); // equiv to M = V * P
|
|
|
|
M.invert();
|
|
|
|
p1 = p1 * M;
|
|
p2 = p1-eye; // ray is in object coordinates, but before the scaling
|
|
|
|
p2.normalize();
|
|
p2 *= (zfar-znear);
|
|
p2 += p1;
|
|
|
|
float inv_scale = 1.0f/scale;
|
|
p1*= inv_scale;
|
|
p2*= inv_scale;
|
|
|
|
SR_TRACE1 ( "Ray: "<< p1 <<" : "<< p2 );
|
|
}
|
|
|
|
/* - -------- \
|
|
| | | \
|
|
h | bbox |--------------.eye
|
|
| | | dist /
|
|
- -------- / tan(viewang/2)=(h/2)/dist
|
|
*/
|
|
void SrCamera::view_all ( const SrBox &box, float fovy_radians )
|
|
{
|
|
SrVec size = box.size();
|
|
float h = SR_MAX(size.x,size.y);
|
|
|
|
fovy = fovy_radians;
|
|
up = SrVec::j;
|
|
center = box.center();
|
|
eye = center;
|
|
|
|
float dist = (h/2)/tanf(fovy/2);
|
|
eye.z = box.b.z + dist;
|
|
|
|
float delta = box.max_size() + 0.0001f;
|
|
zfar = SR_ABS(eye.z)+delta;
|
|
|
|
scale = 1.0f;
|
|
}
|
|
|
|
void SrCamera::apply_translation_from_mouse_motion ( float lwinx, float lwiny, float winx, float winy )
|
|
{
|
|
SrVec p1, p2, x, inc;
|
|
|
|
SrPlane plane ( center, eye-center );
|
|
|
|
get_ray ( lwinx, lwiny, p1, x );
|
|
p1 = plane.intersect ( p1, x );
|
|
get_ray ( winx, winy, p2, x );
|
|
p2 = plane.intersect ( p2, x );
|
|
|
|
inc = p1-p2;
|
|
|
|
inc *= scale;
|
|
|
|
*this += inc;
|
|
}
|
|
|
|
void SrCamera::operator*= ( const SrQuat& q )
|
|
{
|
|
eye -= center;
|
|
eye = eye * q;
|
|
eye += center;
|
|
up -= center;
|
|
up = up * q;
|
|
up += center;
|
|
}
|
|
|
|
void SrCamera::operator+= ( const SrVec& v )
|
|
{
|
|
eye += v;
|
|
center += v;
|
|
}
|
|
|
|
void SrCamera::operator-= ( const SrVec& v )
|
|
{
|
|
eye -= v;
|
|
center -= v;
|
|
}
|
|
|
|
//=============================== friends ==========================================
|
|
|
|
SrCamera operator* ( const SrCamera& c, const SrQuat& q )
|
|
{
|
|
SrCamera cam(c);
|
|
cam *= q;
|
|
return cam;
|
|
}
|
|
|
|
SrCamera operator+ ( const SrCamera& c, const SrVec& v )
|
|
{
|
|
SrCamera cam(c);
|
|
cam += v;
|
|
return cam;
|
|
}
|
|
|
|
SrOutput& operator<< ( SrOutput& out, const SrCamera& c )
|
|
{
|
|
// out << "eye:" << c.eye << " center:" << c.center << " up:" << c.up << srnl;
|
|
|
|
out << "eye " << c.eye << srnl <<
|
|
"center " << c.center << srnl <<
|
|
"up " << c.up << srnl <<
|
|
"fovy " << c.fovy << srnl <<
|
|
"znear " << c.znear << srnl <<
|
|
"zfar " << c.zfar << srnl <<
|
|
"aspect " << c.aspect << srnl <<
|
|
"scale " << c.scale << srnl;
|
|
|
|
return out;
|
|
}
|
|
|
|
SrInput& operator>> ( SrInput& inp, SrCamera& c )
|
|
{
|
|
while ( 1 )
|
|
{ if ( inp.get_token()==SrInput::EndOfFile ) break;
|
|
if ( inp.last_token()=="eye" ) inp>>c.eye;
|
|
else if ( inp.last_token()=="center" ) inp>>c.center;
|
|
else if ( inp.last_token()=="up" ) inp>>c.up;
|
|
else if ( inp.last_token()=="fovy" ) inp>>c.fovy;
|
|
else if ( inp.last_token()=="znear" ) inp>>c.znear;
|
|
else if ( inp.last_token()=="zfar" ) inp>>c.zfar;
|
|
else if ( inp.last_token()=="aspect" ) inp>>c.aspect;
|
|
else if ( inp.last_token()=="scale" ) inp>>c.scale;
|
|
else { inp.unget_token(); break; }
|
|
}
|
|
return inp;
|
|
}
|
|
|
|
//================================ End of File =========================================
|