Geometry* createTexturedQuadGeometry(const Vec3& corner,const Vec3& widthVec,const Vec3& heightVec, float s=1.0f, float t=1.0f)
{
return createTexturedQuadGeometry(corner,widthVec,heightVec, 0.0f, 0.0f, s, t);
}
Geometry* osg::createTexturedQuadGeometry(const Vec3& corner,const Vec3& widthVec,const Vec3& heightVec, float l, float b, float r, float t)
{
Geometry* geom = new Geometry;
Vec3Array* coords = new Vec3Array(4);
(*coords)[0] = corner+heightVec;
(*coords)[1] = corner;
(*coords)[2] = corner+widthVec;
(*coords)[3] = corner+widthVec+heightVec;
geom->setVertexArray(coords);
Vec2Array* tcoords = new Vec2Array(4);
(*tcoords)[0].set(l,t);
(*tcoords)[1].set(l,b);
(*tcoords)[2].set(r,b);
(*tcoords)[3].set(r,t);
geom->setTexCoordArray(0,tcoords);
osg::Vec4Array* colours = new osg::Vec4Array(1);
(*colours)[0].set(1.0f,1.0f,1.0,1.0f);
geom->setColorArray(colours, osg::Array::BIND_OVERALL);
osg::Vec3Array* normals = new osg::Vec3Array(1);
(*normals)[0] = widthVec^heightVec;
(*normals)[0].normalize();
geom->setNormalArray(normals, osg::Array::BIND_OVERALL);
#if defined(OSG_GLES1_AVAILABLE) || !defined(OSG_GLES2_AVAILABLE)
DrawElementsUByte* elems = new DrawElementsUByte(PrimitiveSet::TRIANGLES);
elems->push_back(0);
elems->push_back(1);
elems->push_back(2);
elems->push_back(2);
elems->push_back(3);
elems->push_back(0);
geom->addPrimitiveSet(elems);
#else
geom->addPrimitiveSet(new DrawArrays(PrimitiveSet::QUADS,0,4));
#endif
return geom;
}
inline Matrixd Matrixd::lookAt(const Vec3f& eye,
const Vec3f& center,
const Vec3f& up)
{
Matrixd m;
m.makeLookAt(eye,center,up);
return m;
}
void Matrix_implementation::makeLookAt(const Vec3d& eye,const Vec3d& center,const Vec3d& up)
{
Vec3d f(center-eye);
f.normalize();
Vec3d s(f^up);
s.normalize();
Vec3d u(s^f);
u.normalize();
set(
s[0], u[0], -f[0], 0.0,
s[1], u[1], -f[1], 0.0,
s[2], u[2], -f[2], 0.0,
0.0, 0.0, 0.0, 1.0);
preMultTranslate(-eye);
}
inline void Matrixd::preMultTranslate( const Vec3d& v )
{
for (unsigned i = 0; i < 3; ++i)
{
double tmp = v[i];
if (tmp == 0)
continue;
_mat[3][0] += tmp*_mat[i][0];
_mat[3][1] += tmp*_mat[i][1];
_mat[3][2] += tmp*_mat[i][2];
_mat[3][3] += tmp*_mat[i][3];
}
}
void Matrix_implementation::set( value_type a00, value_type a01, value_type a02, value_type a03,
value_type a10, value_type a11, value_type a12, value_type a13,
value_type a20, value_type a21, value_type a22, value_type a23,
value_type a30, value_type a31, value_type a32, value_type a33)
{
SET_ROW(0, a00, a01, a02, a03 )
SET_ROW(1, a10, a11, a12, a13 )
SET_ROW(2, a20, a21, a22, a23 )
SET_ROW(3, a30, a31, a32, a33 )
}
/** Normalize the vector so that it has length unity.
* Returns the previous length of the vector.
* If the vector is zero length, it is left unchanged and zero is returned.
*/
inline value_type normalize()
{
value_type norm = Vec3d::length();
if (norm>0.0)
{
value_type inv = 1.0/norm;
_v[0] *= inv;
_v[1] *= inv;
_v[2] *= inv;
}
return( norm );
}
#define SET_ROW(row, v1, v2, v3, v4 ) \
_mat[(row)][0] = (v1); \
_mat[(row)][1] = (v2); \
_mat[(row)][2] = (v3); \
_mat[(row)][3] = (v4);
inline Matrixd Matrixd::perspective(double fovy, double aspectRatio,
double zNear, double zFar)
{
Matrixd m;
m.makePerspective(fovy,aspectRatio,zNear,zFar);
return m;
}
void Matrix_implementation::makePerspective(double fovy,double aspectRatio,
double zNear, double zFar)
{
// calculate the appropriate left, right etc.
double tan_fovy = tan(DegreesToRadians(fovy*0.5));
double right = tan_fovy * aspectRatio * zNear;
double left = -right;
double top = tan_fovy * zNear;
double bottom = -top;
makeFrustum(left,right,bottom,top,zNear,zFar);
}
void Matrix_implementation::makeFrustum(double left, double right,
double bottom, double top,
double zNear, double zFar)
{
// note transpose of Matrix_implementation wr.t OpenGL documentation, since the OSG use post multiplication rather than pre.
double A = (right+left)/(right-left);
double B = (top+bottom)/(top-bottom);
double C = (fabs(zFar)>DBL_MAX) ? -1. : -(zFar+zNear)/(zFar-zNear);
double D = (fabs(zFar)>DBL_MAX) ? -2.*zNear : -2.0*zFar*zNear/(zFar-zNear);
SET_ROW(0, 2.0*zNear/(right-left), 0.0, 0.0, 0.0 )
SET_ROW(1, 0.0, 2.0*zNear/(top-bottom), 0.0, 0.0 )
SET_ROW(2, A, B, C, -1.0 )
SET_ROW(3, 0.0, 0.0, D, 0.0 )
}
inline double DegreesToRadians(double angle) { return angle*PI/180.0; }
#define DBL_MAX 1.7976931348623158e+308 // max value