Select Git revision
Forked from
Nettle / nettle
Source project has a limited visibility.
GLU.pmod 7.80 KiB
/*
* GL Utilities module.
*/
#pike __REAL_VERSION__
#require constant(GL.glOrtho)
//! The GL Utilities module is a partial implementation of the
//! GLU library. This module only contains functions that someone
//! at some point actually needed to get his work done. If you
//! need a GLU function that isn't in here, copy the C code from
//! the GLU library (Mesa was used last time), tweak it so that
//! it compiles as Pike code and then check it in into the CVS.
import GL;
#ifndef M_PI
#define M_PI 3.1415926536
#endif
//! @decl void gluLookAt(float eyex, float eyey, float eyez,@
//! float centerx, float centery, float centerz,@
//! float upx, float upy, float upz)
//! @decl void gluLookAt(Math.Matrix eye, Math.Matrix center, Math.Matrix up)
//!
//! gluLookAt creates a viewing matrix derived from an @[eye] point,
//! a reference point indicating the @[center] of the scene, and an
//! @[up] vector. The matrix maps the reference point to the negative
//! z axis and the eye point to the origin, so that, when a typical
//! projection matrix is used, the center of the scene maps to the
//! center of the viewport. Similarly, the direction described by the
//! up vector projected onto the viewing plane is mapped to the positive
//! y axis so that it points upward in the viewport. The up vector must
//! not be parallel to the line of sight from the eye to the reference
//! point.
//!
//! The matrix generated by gluLookAt postmultiplies the current matrix.
//!
//! The relation between the matrix objects and the float values are
//! @code
//! Math.Matrix eye = Math.Matrix( ({ eyex, eyey, eyez }) );
//! @endcode
//!
//! @seealso
//! @[GL.glFrustum], @[gluPerspective]
void gluLookAt(float|object eye,float|object center,float|object up,
float ... old_api)
{
Math.Matrix x,y,z;
if (!objectp(eye))
{
eye=Math.Matrix( ({eye,center,up }) );
center=Math.Matrix( old_api[..2] );
up=Math.Matrix( old_api[3..5] );
}
/* Make rotation matrix */
z=(eye-center)->normv(); /* Z vector */
y=up; /* Y vector */
x=y->cross(z); /* X vector = Y cross Z */
y=z->cross(x); /* Recompute Y = Z cross X */
/* mpichler, 19950515 */
/* cross product gives area of parallelogram, which is < 1.0 for
* non-perpendicular unit-length vectors; so normalize x, y here
*/
x=x->normv(); // normalize
y=y->normv(); // normalize
array m=Array.transpose(({ @(x->vect()), 0.0,
@(y->vect()), 0.0,
@(z->vect()), 0.0,
0.0, 0.0, 0.0, 1.0 })/4)*({});
glMultMatrix( m );
/* Translate Eye to Origin */
glTranslate( ((array)(-1*eye))[0] );
}
//! gluOrtho2D sets up a two-dimensional orthographic viewing region.
//! This is equivalent to calling
//! @code
//! glOrtho(left, right, bottom, top, -1.0, 1.0);
//! @endcode
//! @fixme
//! The GLU manual says @expr{glOrtho(a,b,c,d, 0, 1)@}.
//! @seealso
//! @[GL.glOrtho], @[gluPerspective]
void gluOrtho2D(float left, float right,
float bottom, float top)
{
glOrtho( left, right, bottom, top, -1.0, 1.0 );
}
//! gluPerspective specifies a viewing frustum into the world coordinate
//! system. In general, the aspect ratio in gluPerspective should match
//! the aspect ratio of the associated viewport. For example, aspect =
//! 2.0 means the viewer's angle of view is twice as wide in x as it is
//! in y. If the viewport is twice as wide as it is tall, it displays the
//! image without distortion.
//!
//! The matrix generated by gluPerspective is multipled by the current
//! matrix, just as if @[GL.glMultMatrix] were called with the generated
//! matrix. To load the perspective matrix onto the current matrix stack
//! instead, precede the call to gluPerspective with a call to
//! @[GL.glLoadIdentity].
void gluPerspective(float fovy, float aspect,
float zNear, float zFar)
{
float xmin, xmax, ymin, ymax;
ymax = zNear * tan( fovy * M_PI / 360.0 );
ymin = -ymax;
xmin = ymin * aspect;
xmax = ymax * aspect;
glFrustum( xmin, xmax, ymin, ymax, zNear, zFar );
}
//! gluPickMatrix creates a projection matrix that can be used to
//! restrict drawing to a small region of the viewport. This is
//! typically useful to determine what objects are being drawn
//! near the cursor. Use gluPickMatrix to restrict drawing to a
//! small region around the cursor. Then, enter selection mode
//! (with @[GL.glRenderMode] and rerender the scene. All primitives
//! that would have been drawn near the cursor are identified and
//! stored in the selection buffer.
//!
//! The matrix created by gluPickMatrix is multiplied by the current
//! matrix just as if @[GL.glMultMatrix] is called with the generated
//! matrix. To effectively use the generated pick matrix for picking,
//! first call @[GL.glLoadIdentity] to load an identity matrix onto
//! the perspective matrix stack. Then call gluPickMatrix, and
//! finally, call a command (such as @[gluPerspective]) to multiply
//! the perspective matrix by the pick matrix.
//!
//! When using gluPickMatrix to pick NURBS, be careful to turn off the
//! NURBS property GLU_AUTO_LOAD_MATRIX. If GLU_AUTO_LOAD_MATRIX is not
//! turned off, then any NURBS surface rendered is subdivided
//! differently with the pick matrix than the way it was subdivided
//! without the pick matrix.
//!
//! @param viewport
//! The viewport is an array with four integers.
//!
//! @fixme
//! Does the NURB remark apply?
//!
//! @seealso
//! @[GL.glGet], @[gluLoadIdentity], @[gluMultMatrix], @[gluRenderMode],
//! @[gluPerspective]
void gluPickMatrix(float x, float y,
float width, float height,
array(int) viewport)
{
array(float) m=allocate(16);
float sx, sy;
float tx, ty;
sx = viewport[2] / width;
sy = viewport[3] / height;
tx = (viewport[2] + 2.0 * (viewport[0] - x)) / width;
ty = (viewport[3] + 2.0 * (viewport[1] - y)) / height;
#define M(row,col) m[col*4+row]
M(0,0) = sx; M(0,1) = 0.0; M(0,2) = 0.0; M(0,3) = tx;
M(1,0) = 0.0; M(1,1) = sy; M(1,2) = 0.0; M(1,3) = ty;
M(2,0) = 0.0; M(2,1) = 0.0; M(2,2) = 1.0; M(2,3) = 0.0;
M(3,0) = 0.0; M(3,1) = 0.0; M(3,2) = 0.0; M(3,3) = 1.0;
#undef M
glMultMatrix( m );
}
protected void transform_point(array(float) out, array(float)m,
array(float) in)
{
#define M(row,col) m[col*4+row]
out[0] = M(0,0) * in[0] + M(0,1) * in[1] + M(0,2) * in[2] + M(0,3) * in[3];
out[1] = M(1,0) * in[0] + M(1,1) * in[1] + M(1,2) * in[2] + M(1,3) * in[3];
out[2] = M(2,0) * in[0] + M(2,1) * in[1] + M(2,2) * in[2] + M(2,3) * in[3];
out[3] = M(3,0) * in[0] + M(3,1) * in[1] + M(3,2) * in[2] + M(3,3) * in[3];
#undef M
}
//! gluProject transforms the specified object coordinates into window
//! coordinates using @[model], @[proj], and @[viewport]. The result is
//! returned in a three valued array.
array(float) gluProject(float objx, float objy,
float objz, array(float) model,
array(float) proj, array(int) viewport)
{
array(float) in=allocate(4),out=allocate(4);
in[0]=objx; in[1]=objy; in[2]=objz; in[3]=1.0;
transform_point(out,model,in);
transform_point(in,proj,out);
if (in[3]==0.0)
return 0;
in[0]/=in[3]; in[1]/=in[3]; in[2]/=in[3];
return ({ viewport[0]+(1+in[0])*viewport[2]/2,
viewport[1]+(1+in[1])*viewport[3]/2,
(1+in[2])/2 });
}
// array(float) gluUnProject(float winx,float winy,float winz,
// array(float) model, array(float) proj,
// array(int) viewport)
// {
// array(float)
// m=allocate(16),
// A=allocate(16),
// in=allocate(4),
// out=allocate(4);
// in[0]=(winx-viewport[0])*2/viewport[2] - 1.0;
// in[1]=(winy-viewport[1])*2/viewport[3] - 1.0;
// in[2]=2*winz - 1.0;
// in[3]=1.0;
// matmul(A,proj,model);
// invert_matrix(A,m);
// transform_point(out,m,in);
// if (out[3]==0.0)
// return GL_FALSE;
// return ({ out[0]/out[3], out[1]/out[3], out[2]/out[3] });
// }