diff options
author | Michele Calgaro <[email protected]> | 2020-09-11 14:38:47 +0900 |
---|---|---|
committer | Michele Calgaro <[email protected]> | 2020-09-11 14:38:47 +0900 |
commit | 884c8093d63402a1ad0b502244b791e3c6782be3 (patch) | |
tree | a600d4ab0d431a2bdfe4c15b70df43c14fbd8dd0 /debian/fireflies/fireflies-2.08/libgfx/src | |
parent | 14e1aa2006796f147f3f4811fb908a6b01e79253 (diff) | |
download | extra-dependencies-884c8093d63402a1ad0b502244b791e3c6782be3.tar.gz extra-dependencies-884c8093d63402a1ad0b502244b791e3c6782be3.zip |
Added debian extra dependency packages.
Signed-off-by: Michele Calgaro <[email protected]>
Diffstat (limited to 'debian/fireflies/fireflies-2.08/libgfx/src')
25 files changed, 3500 insertions, 0 deletions
diff --git a/debian/fireflies/fireflies-2.08/libgfx/src/Makefile b/debian/fireflies/fireflies-2.08/libgfx/src/Makefile new file mode 100644 index 00000000..7993f971 --- /dev/null +++ b/debian/fireflies/fireflies-2.08/libgfx/src/Makefile @@ -0,0 +1,29 @@ +include ../gfx-config + +CXXFLAGS += -DGFX_NAMESPACE + +VEC_SRCS = mat2.cxx mat3.cxx mat4.cxx quat.cxx \ + symmat2.cxx symmat3.cxx symmat4.cxx +GEO_SRCS = geom3d.cxx +IMG_SRCS = raster.cxx raster-pnm.cxx raster-tiff.cxx raster-jpeg.cxx \ + raster-png.cxx +MISC_SRCS = time.cxx script.cxx color.cxx +GUI_SRCS = gui.cxx gltools.cxx baseball.cxx trackball.cxx arcball.cxx + +SRCS = $(VEC_SRCS) $(GEO_SRCS) $(IMG_SRCS) $(MISC_SRCS) $(GUI_SRCS) +OBJS = $(SRCS:.cxx=.o) + +libgfx.a: $(OBJS) + $(AR) cru libgfx.a $(OBJS) + $(RANLIB) libgfx.a + +tags: $(SRCS) ../include/gfx/*.h + ctags $(SRCS) ../include/gfx/*.h + +clean: + -$(RM) $(OBJS) libgfx.a + +depend: + $(CXX_DEPEND) $(SRCS) > Makefile.dep + +-include Makefile.dep diff --git a/debian/fireflies/fireflies-2.08/libgfx/src/arcball.cxx b/debian/fireflies/fireflies-2.08/libgfx/src/arcball.cxx new file mode 100644 index 00000000..3eab9a29 --- /dev/null +++ b/debian/fireflies/fireflies-2.08/libgfx/src/arcball.cxx @@ -0,0 +1,192 @@ +/************************************************************************ + + Arcball rotation control. See the original article + + "Arcball Rotation Control" + by Ken Shoemake <[email protected]> + in "Graphics Gems IV", Academic Press, 1994. + + for more details. + + $Id: arcball.cxx 427 2004-09-27 04:45:31Z garland $ + + ************************************************************************/ + +#include <gfx/arcball.h> +#include <gfx/gl.h> +#include <sstream> + +namespace gfx +{ + +// Converts a unit quaternion to two points on the unit sphere +static void quat_to_sphere(const Quat& q, Vec3& from, Vec3& to) +{ + const Vec3& v = q.vector(); + + double s = sqrt(v[0]*v[0] + v[1]*v[1]); + if( s==0.0 ) + from = Vec3(0.0, 1.0, 0.0); + else + from = Vec3(-v[1]/s, v[0]/s, 0.0); + + to[0] = q.scalar()*from[0] - v[2]*from[1]; + to[1] = q.scalar()*from[1] + v[2]*from[2]; + to[2] = v[0]*from[1] - v[1]*from[0]; + + if(q.scalar() < 0.0) from = -from; +} + +// Converts to points on unit sphere into a unit quaternion +static Quat quat_from_sphere(const Vec3& from, const Vec3& to) +{ + Vec3 v; + v[0] = from[1]*to[2] - from[2]*to[1]; + v[1] = from[2]*to[0] - from[0]*to[2]; + v[2] = from[0]*to[1] - from[1]*to[0]; + + double s = from*to; + + return Quat(v, s); +} + + +Vec3 Arcball::proj_to_sphere(const Vec2& mouse) +{ + Vec2 p = (mouse - ball_ctr) / ball_radius; + double mag = p*p; + + if( mag > 1.0 ) + { + double s = sqrt(mag); + return Vec3(p[0]/s, p[1]/s, 0.0); + } + else + { + return Vec3(p[0], p[1], sqrt(1-mag)); + } +} + +void Arcball::update() +{ + // constrain v_from & v_to to axes here, if necessary + + if( is_dragging ) + { + q_drag = quat_from_sphere(v_from, v_to); + q_now = q_drag * q_down; + } +} + +Arcball::Arcball() +{ + ball_ctr = Vec2(0, 0); + ball_radius = 1.0; + + q_now = Quat::ident(); + q_down = Quat::ident(); + q_drag = Quat::ident(); + + is_dragging = false; +} + +bool Arcball::mouse_down(int *where, int which) +{ + float vp[4]; + glGetFloatv(GL_VIEWPORT, vp); + float W=vp[2], H=vp[3]; + + if( which==1 ) + { + is_dragging = true; + Vec2 v( (2.0 * where[0] - W)/W, (H - 2.0 * where[1])/H ); + v_from = proj_to_sphere(v); + v_to = v_from; + } + + return true; +} + +bool Arcball::mouse_up(int *where, int which) +{ + is_dragging = false; + q_down = q_now; + q_drag = Quat::ident(); + + return false; +} + +bool Arcball::mouse_drag(int *where, int *last, int which) +{ + float vp[4]; + glGetFloatv(GL_VIEWPORT, vp); + float W=vp[2], H=vp[3]; + + float diam = 2*radius; + + if( which==1 ) + { + Vec2 v( (2.0 * where[0] - W)/W, (H - 2.0 * where[1])/H ); + v_to = proj_to_sphere(v); + } + else if( which==2 ) + { + trans[0] += diam * (where[0] - last[0]) / W; + trans[1] += diam * (last[1] - where[1]) / H; + } + else if( which==3 ) + { + trans[2] += 0.02*diam*(where[1] - last[1]); + } + else + return false; + + return true; +} + +void Arcball::apply_transform() +{ + update(); + curquat = conjugate(q_now); + Baseball::apply_transform(); +} + + +void Arcball::update_animation() +{ +} + +void Arcball::get_transform(Vec3 & c, Vec3 &t, Quat & q) +{ + c = ctr; + t = trans; + q = q_now; +} + +void Arcball::set_transform(const Vec3 & c, const Vec3 &t, const Quat & q) +{ + ctr = c; + trans = t; + q_now = q; + q_down = q; + q_drag = q; +} + +void Arcball::write(std::ostream& out) +{ + out << "arcball "; + out << ball_ctr << " " << ball_radius << " "; + out << q_now << " " << q_down << " " << q_drag << std::endl; + Baseball::write(out); +} + +void Arcball::read(std::istream& in) +{ + std::string name; + in >> name; + in >> ball_ctr >> ball_radius; + in >> q_now >> q_down >> q_drag; + Baseball::read(in); +} + +} // namespace gfx diff --git a/debian/fireflies/fireflies-2.08/libgfx/src/baseball.cxx b/debian/fireflies/fireflies-2.08/libgfx/src/baseball.cxx new file mode 100644 index 00000000..8a94cd3c --- /dev/null +++ b/debian/fireflies/fireflies-2.08/libgfx/src/baseball.cxx @@ -0,0 +1,59 @@ +/************************************************************************ + + Common code for ball-based rotation controllers. + + $Id: baseball.cxx 427 2004-09-27 04:45:31Z garland $ + + ************************************************************************/ + +#include <gfx/gfx.h> +#include <gfx/gl.h> +#include <gfx/baseball.h> +#include <sstream> + +namespace gfx +{ + +Baseball::Baseball() +{ + curquat = Quat::ident(); + + trans=0.0; + ctr=0.0; + radius=1; +} + +void Baseball::apply_transform() +{ + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glTranslated(trans[0], trans[1], trans[2]); + glTranslated(ctr[0], ctr[1], ctr[2]); + + const Mat4 M=unit_quat_to_matrix(curquat); + glMultMatrixd(M); + + glTranslated(-ctr[0], -ctr[1], -ctr[2]); +} + +void Baseball::unapply_transform() +{ + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); +} + +void Baseball::write(std::ostream& out) +{ + out << "baseball "; + out << curquat << " " << trans << " " << ctr << " " << radius << std::endl; +} + +void Baseball::read(std::istream& in) +{ + std::string name; + + in >> name; + in >> curquat >> trans >> ctr >> radius; +} + +} // namespace gfx diff --git a/debian/fireflies/fireflies-2.08/libgfx/src/color.cxx b/debian/fireflies/fireflies-2.08/libgfx/src/color.cxx new file mode 100644 index 00000000..96fdba72 --- /dev/null +++ b/debian/fireflies/fireflies-2.08/libgfx/src/color.cxx @@ -0,0 +1,128 @@ +#include <gfx/color.h> +#include <gfx/mat3.h> + +namespace gfx +{ + // + // HSV conversion code based on Foley et al (2nd ed. in C, pp. 592-593) + // + + static double max3(double x, double y, double z) + { + if( x>=y && x>=z ) return x; + else if( y>=x && y>=z ) return y; + else return z; + } + + static double min3(double x, double y, double z) + { + if( x<=y && x<=z ) return x; + else if( y<=x && y<=z ) return y; + else return z; + } + + hsvColor RGBtoHSV(const rgbColor& rgb) + { + double r=rgb[0], g=rgb[1], b=rgb[2]; + + double max = max3(r,g,b); + double min = min3(r,g,b); + double delta = max - min; + + double h = -1; // undefined value for case where v outside [0,360] + double v = max; + double s = (max!=0) ? (delta/max) : 0; + + if( s != 0 ) + { + if( r==max ) h = (g-b)/delta; + else if( g==max ) h = 2 + (b-r)/delta; + else if( b==max ) h = 4 + (r-g)/delta; + + h *= 60; + if( h<0 ) h+=360; + } + + return hsvColor(h, s, v); + } + + rgbColor HSVtoRGB(const hsvColor& hsv) + { + double h = hsv[0], s=hsv[1], v=hsv[2]; + + // Unsaturated means pure gray + if(s == 0) return rgbColor(v, v, v); + + if( h==360.0 ) h=0.0; // these are equivalent hues + h /= 60.0; // convert to sector [0, 6) + int i = (int)floor( h ); // integral part of h + float f = h - i; // fractional part of h + + // Compute RGB components + float p = v * ( 1 - s ); + float q = v * ( 1 - s * f ); + float t = v * ( 1 - s * ( 1 - f ) ); + + // Map PQT to RGB based on sector of the color cone + switch( i ) + { + case 0: return rgbColor(v, t, p); break; + case 1: return rgbColor(q, v, p); break; + case 2: return rgbColor(p, v, t); break; + case 3: return rgbColor(p, q, v); break; + case 4: return rgbColor(t, p, v); break; + default: return rgbColor(v, p, q); break; + } + } + + // Paul Haeberli's comments on luminance coefficients: + // + // Where rwgt is 0.3086, gwgt is 0.6094, and bwgt is 0.0820. This + // is the luminance vector. Notice here that we do not use the + // standard NTSC weights of 0.299, 0.587, and 0.114. The NTSC + // weights are only applicable to RGB colors in a gamma 2.2 color + // space. For linear RGB colors the values above are better. + // + // Grafica Obscura -- Matrix Operations for Image Processing + // http://www.sgi.com/misc/grafica/matrix/index.html + // + const rgbColor haeberli_factor(0.3086, 0.6094, 0.0820); + const rgbColor ntsc_factor(0.299, 0.587, 0.114); + + float rgb_luminance_ntsc(const rgbColor& rgb) { return rgb*ntsc_factor; } + float rgb_luminance_alt(const rgbColor& rgb) { return rgb*haeberli_factor; } + + + const Mat3 M_yiq(ntsc_factor, + Vec3(0.596, -0.275, -0.321), + Vec3(0.212, -0.523, 0.311)); + + yiqColor RGBtoYIQ(const rgbColor& rgb) + { + return yiqColor(M_yiq * Vec3(rgb)); + } + + // Matrix conversions taken from the ColorFAQ by Charles Poynton + const Mat3 M_rgb(Vec3( 3.240479, -1.537150, -0.498535), + Vec3(-0.969256, 1.875992, 0.041556), + Vec3( 0.055648, -0.204043, 1.057311)); + + const Mat3 M_xyz(Vec3(0.412453, 0.357580, 0.180423), + Vec3(0.212671, 0.715160, 0.072169), + Vec3(0.019334, 0.119193, 0.950227)); + + // Derived from equations provided by EasyRGB: + // http://www.easyrgb.com/math.php + // + xyzColor RGBtoXYZ(const rgbColor& rgb) + { return xyzColor(M_xyz * Vec3(rgb)); } + + rgbColor XYZtoRGB(const xyzColor& xyz) + { return rgbColor(M_rgb * Vec3(xyz)); } + + xyChromaticity xyz_chromaticity(const xyzColor& xyz) + { + float w = xyz[0] + xyz[1] + xyz[2]; + return xyChromaticity(xyz[0]/w, xyz[1]/w); + } +} diff --git a/debian/fireflies/fireflies-2.08/libgfx/src/geom3d.cxx b/debian/fireflies/fireflies-2.08/libgfx/src/geom3d.cxx new file mode 100644 index 00000000..ff9e8e44 --- /dev/null +++ b/debian/fireflies/fireflies-2.08/libgfx/src/geom3d.cxx @@ -0,0 +1,33 @@ +/************************************************************************ + + Handy 3D geometrical primitives + + $Id: geom3d.cxx 427 2004-09-27 04:45:31Z garland $ + + ************************************************************************/ + +#include <gfx/gfx.h> +#include <gfx/geom3d.h> +#include <gfx/mat4.h> + +namespace gfx +{ + +double tetrahedron_determinant(const Vec3& v0, const Vec3& v1, + const Vec3& v2, const Vec3& v3) +{ + Mat4 A( Vec4(v0, 1), + Vec4(v1, 1), + Vec4(v2, 1), + Vec4(v3, 1)); + + return det(A); +} + +double tetrahedron_volume(const Vec3& v0, const Vec3& v1, + const Vec3& v2, const Vec3& v3) +{ + return fabs(tetrahedron_determinant(v0,v1,v2,v3)/6); +} + +} diff --git a/debian/fireflies/fireflies-2.08/libgfx/src/geom4d.cxx b/debian/fireflies/fireflies-2.08/libgfx/src/geom4d.cxx new file mode 100644 index 00000000..2973f966 --- /dev/null +++ b/debian/fireflies/fireflies-2.08/libgfx/src/geom4d.cxx @@ -0,0 +1,14 @@ +/************************************************************************ + + Handy 4D geometrical primitives + + $Id: geom4d.cxx 427 2004-09-27 04:45:31Z garland $ + + ************************************************************************/ + +#include <gfx/gfx.h> +#include <gfx/geom4d.h> + +namespace gfx +{ +} diff --git a/debian/fireflies/fireflies-2.08/libgfx/src/gltools.cxx b/debian/fireflies/fireflies-2.08/libgfx/src/gltools.cxx new file mode 100644 index 00000000..565a382e --- /dev/null +++ b/debian/fireflies/fireflies-2.08/libgfx/src/gltools.cxx @@ -0,0 +1,192 @@ +/************************************************************************ + + Handy functions for common OpenGL tasks + + $Id: gltools.cxx 446 2005-06-18 13:58:15Z garland $ + + ************************************************************************/ + + +#include <gfx/gfx.h> + +#ifdef HAVE_OPENGL + +#include <gfx/gltools.h> + +#include <cassert> + +namespace gfx +{ + +using std::cerr; +using std::endl; + +GLuint opengl_pick_nil = (~0); +GLuint opengl_pick_zmax = (~0); + +void begin_opengl_pick(int *where, double radius, GLuint *buffer, int size) +{ + GLint vp[4]; + glGetIntegerv(GL_VIEWPORT, vp); + + glSelectBuffer(size, buffer); + glRenderMode(GL_SELECT); + glInitNames(); + glPushName(opengl_pick_nil); + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); // Save the current transformation + glLoadIdentity(); + gluPickMatrix(where[0], vp[3] - where[1], radius, radius, vp); +} + +GLuint complete_opengl_pick(GLuint *buffer) +{ + glMatrixMode(GL_PROJECTION); + glPopMatrix(); // get rid of the pick matrix + glFlush(); + + GLint nhits = glRenderMode(GL_RENDER); + GLuint *hit = NULL; + GLuint hit_nnames = 0; + GLuint zmin = opengl_pick_zmax; + GLuint *ptr = buffer; + + for(int i=0; i<nhits; i++) + { + GLuint nnames = *ptr++; + GLuint cur_zmin = *ptr++; + /* GLuint cur_zmax = */ *ptr++; + + if( cur_zmin < zmin ) + { + zmin = cur_zmin; + hit = ptr; + hit_nnames = nnames; + } + ptr+=nnames; + } + + + buffer[0] = hit_nnames; + if( hit ) + { + for(int k=0; k<hit_nnames; k++) + buffer[k+1] = hit[k]; + + return *hit; + } + else + return opengl_pick_nil; +} + +void report_opengl_stacks() +{ + GLint depth; + + glGetIntegerv(GL_PROJECTION_STACK_DEPTH, &depth); + cerr << " Projection stack depth = " << depth; + glGetIntegerv(GL_MAX_PROJECTION_STACK_DEPTH, &depth); + cerr << " (" << depth << " max)" << endl; + + glGetIntegerv(GL_MODELVIEW_STACK_DEPTH, &depth); + cerr << " ModelView stack depth = " << depth; + glGetIntegerv(GL_MAX_MODELVIEW_STACK_DEPTH, &depth); + cerr << " (" << depth << " max)" << endl; + + glGetIntegerv(GL_TEXTURE_STACK_DEPTH, &depth); + cerr << " Texture stack depth = " << depth; + glGetIntegerv(GL_MAX_TEXTURE_STACK_DEPTH, &depth); + cerr << " (" << depth << " max)" << endl; +} + +void check_opengl_errors(const char *msg) +{ + bool stack_error = false; + + for(GLenum err=glGetError(); err!=GL_NO_ERROR; err=glGetError()) + { + cerr << "GL ERROR "; + if( msg ) cerr << msg; + cerr << ": " << (const char *)gluErrorString(err) << endl; + + if( err==GL_STACK_OVERFLOW || err==GL_STACK_UNDERFLOW ) + stack_error = true; + } + + if( stack_error ) report_opengl_stacks(); +} + +void camera_lookat(const Vec3& min, const Vec3& max, double aspect) +{ + Vec3 up(0, 1, 0); + double fovy = 60.0; + + Vec3 at = (max + min)/2.0; // look at the center of the bbox + double radius = norm(max - at); // radius of a bounding sphere + double d = 3*radius / tan(fovy * M_PI/180.0); + + Vec3 from = at; + from[2] += d; + + double znear = d/20; + double zfar = 10*d; + + glMatrixMode(GL_PROJECTION); + gluPerspective(fovy, aspect, znear, zfar); + + + glMatrixMode(GL_MODELVIEW); + gluLookAt(from[0], from[1], from[2], + at[0], at[1], at[2], + up[0], up[1], up[2]); +} + +void ortho_camera_lookat(const Vec3& min, const Vec3& max, double aspect) +{ + Vec3 up(0, 1, 0); + double fovy = 60.0; + + Vec3 at = (max + min)/2.0; // look at the center of the bbox + double radius = norm(max - at); // radius of a bounding sphere + double d = 3*radius / tan(fovy * M_PI/180.0); + + Vec3 from = at; + from[2] += d; + + Vec3 diag = max-min; + double width = MAX(diag[0], diag[1]); width=MAX(width, diag[2]); + width *= 1.1; + + double znear = d/20; + double zfar = 10*d; + glMatrixMode(GL_PROJECTION); + glOrtho(-aspect/2*width, aspect/2*width, -0.5*width, 0.5*width, znear, zfar); + + glMatrixMode(GL_MODELVIEW); + gluLookAt(from[0], from[1], from[2], + at[0], at[1], at[2], + up[0], up[1], up[2]); +} + +int unproject_pixel(int *pixel, double *world, double z) +{ + GLdouble modelMatrix[16]; + GLdouble projMatrix[16]; + GLint viewport[4]; + + glGetDoublev(GL_PROJECTION_MATRIX, projMatrix); + glGetDoublev(GL_MODELVIEW_MATRIX, modelMatrix); + glGetIntegerv(GL_VIEWPORT, viewport); + + // Notice that we have to correct the y pixel coordinate. GL + // assigns the origin to the lower left corner, while FLTK assigns + // the origin to the upper left corner. + return gluUnProject(pixel[0], viewport[3]-pixel[1], z, + modelMatrix, projMatrix, viewport, + world, world+1, world+2); +} + +} // namespace gfx + +#endif /* HAVE_OPENGL */ diff --git a/debian/fireflies/fireflies-2.08/libgfx/src/gui-mfc.cxx b/debian/fireflies/fireflies-2.08/libgfx/src/gui-mfc.cxx new file mode 100644 index 00000000..a9ab22e5 --- /dev/null +++ b/debian/fireflies/fireflies-2.08/libgfx/src/gui-mfc.cxx @@ -0,0 +1,297 @@ +/************************************************************************ + + MxGUI-like emulation in MFC. + + $Id: gui-mfc.cxx 427 2004-09-27 04:45:31Z garland $ + + ************************************************************************/ + +#include <gfx/win/gui-mfc.h> + +namespace gfx +{ + +static inline MfcGUI *GuiGetApp() { return (MfcGUI *)AfxGetApp(); } + +MfcGUI::MfcGUI() +{ + canvas = NULL; + timer_id = 0; + default_fps = 24.0f; + target_fps = 0.0f; +} + +void MfcGUI::status(const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + CString str; + str.FormatV(fmt, args); + va_end(args); + + if( canvas && canvas->status_line ) + canvas->status_line->SetPaneText(0, str); +} + +static VOID CALLBACK cb_timeout(HWND w, UINT msg, UINT id, DWORD system_time) +{ + GuiGetApp()->update_animation(); + GuiGetApp()->canvas->post_redraw(); +} + +void MfcGUI::animate(bool will) +{ + if( will ) + { + target_fps = default_fps; + + float millisecs = 1000 / target_fps; + timer_id = ::SetTimer(NULL, 0, (UINT)millisecs, cb_timeout); + } + else + { + target_fps = 0; + if( timer_id ) ::KillTimer(NULL, timer_id); + timer_id = 0; + } +} + +BOOL MfcGUI::InitInstance() +{ + m_pMainWnd = canvas = new Canvas; + m_pMainWnd->ShowWindow(m_nCmdShow); + m_pMainWnd->UpdateWindow(); + return TRUE; +} + + + +BEGIN_MESSAGE_MAP(Canvas, CFrameWnd) + ON_WM_CREATE() + ON_WM_DESTROY() + ON_WM_SIZE() + + //ON_WM_ACTIVATE() + ON_WM_PAINT() + ON_WM_ERASEBKGND() + + ON_WM_LBUTTONDOWN() + ON_WM_LBUTTONUP() + ON_WM_RBUTTONDOWN() + ON_WM_RBUTTONUP() + ON_WM_MBUTTONDOWN() + ON_WM_MBUTTONUP() + ON_WM_MOUSEMOVE() + ON_WM_CHAR() +END_MESSAGE_MAP() + +Canvas::Canvas() +{ + last_click[0] = last_click[1] = -1; + glcontext = NULL; + pixfmt = 0; + + + Create(NULL, "Sample Application"); + + CMenu menu; + menu.CreateMenu(); + + CMenu popup; + popup.CreatePopupMenu(); + popup.AppendMenu(MF_STRING, 0, "&New\tCtrl+N"); + menu.AppendMenu(MF_POPUP, (UINT)popup.Detach(), "&File"); + + SetMenu(&menu); + menu.Detach(); + + status_line = new CStatusBar(); + status_line->Create(this); + UINT indicator = ID_SEPARATOR; + status_line->SetIndicators(&indicator, 1); +} + +BOOL Canvas::PreCreateWindow(CREATESTRUCT &cs) +{ + // Need to set special style requirements for OpenGL windows + cs.style |= WS_CLIPSIBLINGS | WS_CLIPCHILDREN; + return CFrameWnd::PreCreateWindow(cs); +} + + +int Canvas::OnCreate(LPCREATESTRUCT lpcs) +{ + if( CFrameWnd::OnCreate(lpcs) == -1 ) return -1; + + HWND wnd = GetSafeHwnd(); + HDC dc = ::GetDC(wnd); + + pixfmt = set_pixel_format(dc); + if( !pixfmt ) + MessageBox("Failed to set up proper pixel format."); + + glcontext = create_glcontext(dc); + if( !glcontext ) + MessageBox("Failed to create GL context."); + + return 0; +} + +void Canvas::OnPaint() +{ + CPaintDC dc(this); + + HDC hdc = dc.GetSafeHdc(); + make_current(hdc); + + GuiGetApp()->draw_contents(); + + finish(hdc); +} + +void Canvas::OnDestroy() +{ + if( wglGetCurrentContext() ) + wglMakeCurrent(NULL, NULL); + + if( glcontext ) + { + wglDeleteContext(glcontext); + glcontext = NULL; + } + + CFrameWnd::OnDestroy(); +} + +void Canvas::OnSize(UINT type, int width, int height) +{ + CFrameWnd::OnSize(type, width, height); + glViewport(0, 0, width, height); + GuiGetApp()->setup_for_drawing(); +} + +BOOL Canvas::OnEraseBkgnd(CDC *dc) +{ + return FALSE; // Don't want background to be erased thank you +} + +void Canvas::immediate_redraw() +{ + SendMessage(WM_PAINT); +} + +void Canvas::post_redraw() +{ + InvalidateRect(NULL, FALSE); +} + +int Canvas::decode_mouse_button(UINT flags, int which) +{ + if( which==0 ) + { + if( flags&MK_MBUTTON ) which = 2; + else if( flags&MK_LBUTTON ) which = 1; + else if( flags&MK_RBUTTON ) which = 3; + } + + // Emulate middle button by double click + if( flags&MK_LBUTTON && flags&MK_RBUTTON ) which = 2; + + return which; +} + +void Canvas::do_mouse_down(int which, UINT flags, CPoint point) +{ + which = decode_mouse_button(flags, which); + + int where[2]; where[0]=point.x; where[1]=point.y; + last_click[0]=point.x; last_click[1]=point.y; + + SetCapture(); + if( GuiGetApp()->mouse_down(where, which) ) + post_redraw(); +} + +void Canvas::do_mouse_up(int which, UINT flags, CPoint point) +{ + which = decode_mouse_button(flags, which); + + int where[2]; where[0]=point.x; where[1]=point.y; + + ReleaseCapture(); + if( GuiGetApp()->mouse_up(where, which) ) + post_redraw(); +} + +void Canvas::do_mouse_move(UINT flags, CPoint point) +{ + int which = decode_mouse_button(flags); + + int where[2]; where[0]=point.x; where[1]=point.y; + + if( GuiGetApp()->mouse_drag(where, last_click, which) ) + post_redraw(); + + last_click[0]=point.x; last_click[1]=point.y; +} + +// Each mouse handler is given a set of flags 'f' and a position 'p' +void Canvas::OnLButtonDown(UINT f, CPoint p) { do_mouse_down(1, f, p); } +void Canvas::OnRButtonDown(UINT f, CPoint p) { do_mouse_down(3, f, p); } +void Canvas::OnMButtonDown(UINT f, CPoint p) { do_mouse_down(2, f, p); } +void Canvas::OnLButtonUp(UINT f, CPoint p) { do_mouse_up(1, f, p); } +void Canvas::OnRButtonUp(UINT f, CPoint p) { do_mouse_up(3, f, p); } +void Canvas::OnMButtonUp(UINT f, CPoint p) { do_mouse_up(2, f, p); } +void Canvas::OnMouseMove(UINT f, CPoint p) { do_mouse_move(f, p); } + +void Canvas::OnChar(UINT ch, UINT repcount, UINT flags) +{ + GuiGetApp()->key_press(ch); +} + +#if 0 +void Canvas::OnActivate(UINT state, CWnd *other, BOOL is_minimized) +{ + if( state==WA_ACTIVE || state==WA_CLICKACTIVE ) + { + wglMakeCurrent(dc, glcontext); + } +} +#endif + + + +/***************************************** + +NOTES: + + AfxGetApp() returns a CWinApp* to the current application + AfxGetAppName() returns a const char* to application name + + + ****************************************/ + +void MfcGUI::setup_for_drawing() +{ + status("Hello There"); +} + +void MfcGUI::draw_contents() +{ + glClearColor(0.8f, 0.2f, 0.2f, 0.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); +} + +bool MfcGUI::mouse_down(int *where, int which) { return false; } + +bool MfcGUI::mouse_up(int *where, int which) { return false; } + +bool MfcGUI::mouse_drag(int *where, int *last, int which) { return false; } + +bool MfcGUI::key_press(int key) { return false; } + +void MfcGUI::update_animation() { } + + +} // namespace gfx diff --git a/debian/fireflies/fireflies-2.08/libgfx/src/gui.cxx b/debian/fireflies/fireflies-2.08/libgfx/src/gui.cxx new file mode 100644 index 00000000..7102aed2 --- /dev/null +++ b/debian/fireflies/fireflies-2.08/libgfx/src/gui.cxx @@ -0,0 +1,509 @@ +/************************************************************************ + + MxGUI + + $Id: gui.cxx 447 2005-06-18 14:01:16Z garland $ + + ************************************************************************/ + +#include <gfx/gfx.h> + +#ifdef HAVE_FLTK + +#include <gfx/gui.h> +#include <gfx/raster.h> + +#include <FL/Fl_File_Chooser.H> +#include <FL/fl_ask.H> + +#include <cstdio> +#include <cstdarg> +#include <fstream> + +namespace gfx +{ + +MxGUI *MxGUI::current = NULL; + +MxGLCanvas::MxGLCanvas(int x, int y, int w, int h, const char *l) + : Fl_Gl_Window(x, y, w, h, l) +{ + last_click[0] = last_click[1] = -1; + app = NULL; +} + +void MxGLCanvas::attach_app(MxGUI *a) +{ + if( !app ) + app = a; +} + +void MxGLCanvas::resize(int x, int y, int w, int h) +{ + Fl_Gl_Window::resize(x, y, w, h); + + if( shown() ) + { + make_current(); + glViewport(0, 0, w, h); + invalidate(); + } +} + +void MxGLCanvas::draw() +{ + if( !valid() ) + { + valid(1); + if(app) app->setup_for_drawing(); + } + + if(app) app->draw_contents(); +} + +int MxGLCanvas::handle(int event) +{ + bool need_redraw = false; + + int where[2]; where[0] = Fl::event_x(); where[1] = Fl::event_y(); + + // NOTE: Normally, we examine event_state() rather than + // event_button() because it is valid no matter what the generating + // event whereas event_button() is only valid for PUSH and RELEASE + // events. However, since event_state() only tells us what buttons + // are *pressed*, we need to revert to event_button() on RELEASE + // events. + // + int which = Fl::event_button(); + + if( event != FL_RELEASE ) + { + if( Fl::event_state(FL_BUTTON1) ) + { + // emulate middle button by combination of left & right buttons + if( Fl::event_state(FL_BUTTON3) ) which = 2; + else which = 1; + } + else if( Fl::event_state(FL_BUTTON2) ) which = 2; + else if( Fl::event_state(FL_BUTTON3) ) which = 3; + } + + switch( event ) + { + case FL_PUSH: + need_redraw = app && app->mouse_down(where, which); + last_click[0]=where[0]; last_click[1]=where[1]; + break; + + case FL_RELEASE: + need_redraw = app && app->mouse_up(where, which); + break; + + case FL_DRAG: + need_redraw = app && app->mouse_drag(where, last_click, which); + last_click[0]=where[0]; last_click[1]=where[1]; + break; + + case FL_FOCUS: + case FL_UNFOCUS: + // Do nothing special + break; + + case FL_KEYBOARD: + if( !app || !app->key_press(Fl::event_key()) ) + return 0; + break; + + default: + return Fl_Gl_Window::handle(event); + } + + if( need_redraw ) + redraw(); + + return 1; +} + +//////////////////////////////////////////////////////////////////////// +// +// Default menu system. Although the application can completely +// override this, it's expected that most programs will just add their +// own additional entries. +// + +void MxGUI::cb_new() { } + +void MxGUI::cb_exit() { cleanup_for_exit(); exit(0); } + +void MxGUI::cb_animate(Fl_Menu_ *m) + { animate(m->mvalue()->value()!=0); } + +void MxGUI::cb_fps() +{ + // Convert default_fps to a string + static char fps[64]; sprintf(fps, "%.1f", default_fps); + + const char *result = fl_input("Number of frames per second to draw", fps); + if( result ) + { + default_fps = atof(result); + if( target_fps>0 ) target_fps=default_fps; + } +} + +void MxGUI::cb_snapshot(int format) +{ + canvas->redraw(); // don't want to snap menu + snapshot_to_file(format); // snapshot what's drawn +} + +void MxGUI::cb_vga_size(int xw) +{ + if( toplevel->resizable() ) + resize_canvas(xw, (3*xw)/4); +} + +void MxGUI::cb_hdtv_size(int xw) +{ + if( toplevel->resizable() ) + MxGUI::current->resize_canvas(xw, (9*xw)/16); +} + +void MxGUI::cb_dv_size(int xw) +{ + if( toplevel->resizable() ) + MxGUI::current->resize_canvas(xw, (2*xw)/3); +} + +void MxGUI::cb_toggle(Fl_Menu_ *m, bool *flag) +{ + *flag = m->mvalue()->value()!=0; + current->canvas->redraw(); +} + +void MxGUI::cb_save_view_to_file() { save_view_to_file(); } +void MxGUI::cb_load_view_from_file() { load_view_from_file(); } + +bool MxGUI::save_view_to_file() +{ + fl_alert("This application has not defined a scheme for saving the view."); + return false; +} + +bool MxGUI::load_view_from_file() +{ + fl_alert("This application has not defined a scheme for loading the view."); + return false; +} + +int MxGUI::add_menu(const std::string& s, int key, Fl_Callback *cb, int flags) +{ + return menu_bar->add(s.c_str(), key, cb, this, flags); +} + +int MxGUI::add_toggle_menu(const std::string& s, int key, bool& val, int flags) +{ + return menu_bar->add(s.c_str(), key, (Fl_Callback *)cb_toggle, &val, + FL_MENU_TOGGLE|(val?FL_MENU_VALUE:0)|flags); +} + +//////////////////////////////////////////////////////////////////////// + +#ifdef __CYGWIN__ +extern "C"{ + extern int mainCRTStartup(); + int WinMainCRTStartup() { mainCRTStartup(); return 1; } +} +#endif + +MxGUI::MxGUI() +{ + canvas = NULL; + status_line = NULL; + default_fps = 24.0f; + target_fps = 0.0f; + MxGUI::current = this; +} + +Fl_Window *MxGUI::create_window(int xw, int yw, int pad) +{ + int yfill = 0; + + Fl_Window *w = new Fl_Window(xw+2*pad, 0); + toplevel = w; + w->box(FL_UP_BOX); + + menu_bar = new Fl_Menu_Bar(0, yfill, w->w(), 30); + menu_bar->menu(menu_layout); + yfill += menu_bar->h(); + + add_upper_controls(yfill, pad); + + yfill += pad; + canvas = new MxGLCanvas(pad, yfill, xw, yw); + canvas->box(FL_DOWN_FRAME); + canvas->attach_app(this); + + int glmode = 0; + if(canvas->can_do(FL_RGB8)) glmode|=FL_RGB8; + if(canvas->can_do(FL_DOUBLE)) glmode|=FL_DOUBLE; + if(canvas->can_do(FL_DEPTH)) glmode|=FL_DEPTH; + if(canvas->can_do(FL_ALPHA)) glmode|=FL_ALPHA; + if(glmode) canvas->mode(glmode); + + yfill += canvas->h(); + + add_lower_controls(yfill, pad); + + yfill += pad; + status_line = new Fl_Output(pad, yfill, xw, 25); + status_line->color(48); + status_line->labeltype(FL_NO_LABEL); + yfill += status_line->h(); + + w->end(); + + w->size(w->w(), yfill+pad); // adjust window height + w->resizable(*canvas); // resize canvas with window + + // These are used by resize_canvas() to resize the window based on + // the target size of the canvas. + w_offset = w->w() - xw; + h_offset = w->h() - yw; + + return w; +} + +static +int arg_redirect(int argc, char **argv, int& index) +{ + MxGUI *app = MxGUI::current; + return app?app->cmdline_option(argc, argv, index):0; +} + +void MxGUI::initialize(int argc, char **argv, Fl_Menu_Item *m, int xw, int yw) +{ + Fl::visual(FL_RGB8); + menu_layout = m?m:NULL; + + int index = 0; + if( argv ) + Fl::args(argc, argv, index, arg_redirect); + + create_window(xw, yw); + toplevel->label("Graphics Program"); + + // Add dynamic entries + typedef MxBinder<MxGUI> CB; + std::string snap = "&File/Snapshot to/"; + std::string view = "&View/"; + std::string size = "&View/Display &size/"; + + add_menu("&File/&New", FL_CTRL+'n', CB::to<&MxGUI::cb_new>); + +#if defined(HAVE_LIBPNG) + add_menu(snap+"&PNG", + FL_CTRL+'p', CB::to_arg<&MxGUI::cb_snapshot, IMG_PNG>); +#endif +#if defined(HAVE_LIBTIFF) + add_menu("&File/Snapshot to/&TIFF", + FL_CTRL+'P', CB::to_arg<&MxGUI::cb_snapshot, IMG_TIFF>); +#endif +#if defined(HAVE_LIBJPEG) + add_menu("&File/Snapshot to/&JPEG", 0, CB::to_arg<&MxGUI::cb_snapshot, IMG_JPEG>); +#endif + add_menu("&File/Snapshot to/PP&M", 0, CB::to_arg<&MxGUI::cb_snapshot, IMG_PNM>); + + add_menu("&File/E&xit", FL_CTRL+'q', CB::to<&MxGUI::cb_exit>); + + add_menu(view+"Animation speed ...", FL_CTRL+'r', CB::to<&MxGUI::cb_fps>); + add_menu(view+"&Animate", FL_CTRL+'a', CB::to_menu<&MxGUI::cb_animate>, FL_MENU_TOGGLE); + + add_menu(view+"Save view ...", 0, CB::to<&MxGUI::cb_save_view_to_file>); + add_menu(view+"Load view ...", 0, CB::to<&MxGUI::cb_load_view_from_file>); + + add_menu(size+"320x240",0, CB::to_arg<&MxGUI::cb_vga_size, 320>); + add_menu(size+"640x480",0, CB::to_arg<&MxGUI::cb_vga_size, 640>); + add_menu(size+"800x600",0, CB::to_arg<&MxGUI::cb_vga_size, 800>); + add_menu(size+"1024x768",0,CB::to_arg<&MxGUI::cb_vga_size, 1024>,FL_MENU_DIVIDER); + add_menu(size+"720x480",0, CB::to_arg<&MxGUI::cb_dv_size, 720>,FL_MENU_DIVIDER); + + add_menu(size+"480x270",0, CB::to_arg<&MxGUI::cb_hdtv_size, 480>); + add_menu(size+"960x540",0, CB::to_arg<&MxGUI::cb_hdtv_size, 960>); + add_menu(size+"1920x1080",0, CB::to_arg<&MxGUI::cb_hdtv_size, 1920>); + + if( argv ) + { + if( index==argc ) + cmdline_file(NULL); + else + for(; index<argc; index++) + cmdline_file(argv[index]); + } +} + +int MxGUI::run() +{ + toplevel->show(); + return Fl::run(); +} + +static +void cb_timeout(void *) +{ + MxGUI *app = MxGUI::current; + + if(!app || app->target_fps==0.0f) return; + + app->update_animation(); + app->canvas->redraw(); + Fl::repeat_timeout(1/app->target_fps, cb_timeout); +} + +void MxGUI::animate(bool will) +{ + if( will ) + { + target_fps = default_fps; + Fl::add_timeout(1/target_fps, cb_timeout); + } + else + target_fps = 0; +} + +int MxGUI::status(const char *fmt, ...) +{ + static char strbuf[1000]; + + va_list args; + va_start(args, fmt); + int n = vsprintf(strbuf, fmt, args); + + status_line->value(strbuf); + return n; +} + +bool MxGUI::snapshot_to_file(int format, const char *filenamep) +{ + canvas->make_current(); + Fl::flush(); + + GLint vp[4]; glGetIntegerv(GL_VIEWPORT, vp); + + glPushAttrib(GL_PIXEL_MODE_BIT); + glReadBuffer(GL_FRONT); + glPixelStorei(GL_PACK_ALIGNMENT, 1); + + int nchan = 3; + if( format==IMG_PNG || format==IMG_TIFF ) + // Currently, only TIFF and PNG writers support the alpha channel + nchan = 4; + + ByteRaster img(vp[2]-vp[0], vp[3]-vp[1], nchan); + glReadPixels(vp[0],vp[1],vp[2],vp[3], + nchan==4 ? GL_RGBA : GL_RGB, + GL_UNSIGNED_BYTE,img.head()); + + glPopAttrib(); + img.vflip(); + + if ( filenamep == NULL ) + { + char msg[80], pat[8], name[16]; + sprintf(msg, "Save %s Snapshot", image_type_name(format)); + sprintf(pat, "*.%s", image_type_ext(format)); + sprintf(name, "snap.%s", image_type_ext(format)); + + filenamep = fl_file_chooser(msg, pat, name); + } + + if( filenamep ) + return write_image(filenamep, img, format); + else + return false; +} + +void MxGUI::lock_size() +{ + toplevel->size_range(toplevel->w(), toplevel->h(), + toplevel->w(), toplevel->h()); + toplevel->resizable(NULL); +} + +void MxGUI::unlock_size() +{ + toplevel->resizable(*canvas); + toplevel->size_range(100, 100, 0, 0); +} + + +void MxGUI::resize_canvas(int width, int height) +{ + toplevel->size(width+w_offset, height+h_offset); + toplevel->redraw(); +} + +//////////////////////////////////////////////////////////////////////// + +void MxGUI::setup_for_drawing() +{ + glClearColor(0.65f, 0.65f, 0.65f, 0.0f); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluOrtho2D(-1.0, 1.0, -1.0, 1.0); +} + +void MxGUI::draw_contents() +{ + glClear(GL_COLOR_BUFFER_BIT); + + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + + glColor3f(0.0, 0.0, 0.0); + glBegin(GL_LINES); + glVertex2f(-1.0, 0.0); glVertex2f(1.0, 0.0); + glVertex2f(0.0, -1.0); glVertex2f(0.0, 1.0); + glEnd(); + + glPopMatrix(); +} + +void MxGUI::update_animation() +{ +} + +bool MxGUI::mouse_down(int *where, int which) +{ + return false; +} + +bool MxGUI::mouse_up(int *where, int which) +{ + return false; +} + +bool MxGUI::mouse_drag(int *where, int *last, int which) +{ + return false; +} + +bool MxGUI::key_press(int key) +{ + return false; +} + +int MxGUI::cmdline_option(int argc, char **argv, int& index) +{ + return 0; +} + +void MxGUI::cmdline_file(const char *file) +{ +} + +} // namespace gfx + +#endif /* HAVE_FLTK */ diff --git a/debian/fireflies/fireflies-2.08/libgfx/src/mat2.cxx b/debian/fireflies/fireflies-2.08/libgfx/src/mat2.cxx new file mode 100644 index 00000000..42ed3e1a --- /dev/null +++ b/debian/fireflies/fireflies-2.08/libgfx/src/mat2.cxx @@ -0,0 +1,89 @@ +/************************************************************************ + + 2x2 Matrix class + + $Id: mat2.cxx 427 2004-09-27 04:45:31Z garland $ + + ************************************************************************/ + +#include <gfx/gfx.h> +#include <gfx/mat2.h> + +namespace gfx +{ + +Mat2 Mat2::I() { return Mat2(1,0, 0,1); } + +Mat2 &Mat2::diag(double d) +{ + row[0][0] = d; row[0][1] = 0; + row[1][0] = 0; row[1][1] = d; + + return *this; +} + +Mat2 operator*(const Mat2 &n, const Mat2& m) +{ + Mat2 A; + int i,j; + + for(i=0;i<2;i++) + for(j=0;j<2;j++) + A(i,j) = n[i]*m.col(j); + + return A; +} + +double invert(Mat2 &inv, const Mat2 &m) +{ + double d = det(m); + + if( d==0.0 ) + return 0.0; + + inv(0, 0) = m(1,1)/d; + inv(0, 1) = -m(0,1)/d; + inv(1, 0) = -m(1,0)/d; + inv(1, 1) = m(0,0)/d; + + return d; +} + +bool eigenvalues(const Mat2& M, Vec2& evals) +{ + double B = -M(0,0)-M(1,1); + double C = det(M); + + double dis = B*B - 4.0*C; + if( dis<FEQ_EPS ) + return false; + else + { + double s = sqrt(dis); + + evals[0] = 0.5*(-B + s); + evals[1] = 0.5*(-B - s); + return true; + } +} + +bool eigenvectors(const Mat2& M, const Vec2& evals, Vec2 evecs[2]) +{ + evecs[0] = Vec2(-M(0,1), M(0,0)-evals[0]); + evecs[1] = Vec2(-M(0,1), M(0,0)-evals[1]); + + unitize(evecs[0]); + unitize(evecs[1]); + + return true; +} + +bool eigen(const Mat2& M, Vec2& evals, Vec2 evecs[2]) +{ + bool result = eigenvalues(M, evals); + if( result ) + eigenvectors(M, evals, evecs); + return result; +} + +} // namespace gfx diff --git a/debian/fireflies/fireflies-2.08/libgfx/src/mat3.cxx b/debian/fireflies/fireflies-2.08/libgfx/src/mat3.cxx new file mode 100644 index 00000000..eda9fe3c --- /dev/null +++ b/debian/fireflies/fireflies-2.08/libgfx/src/mat3.cxx @@ -0,0 +1,82 @@ +/************************************************************************ + + 3x3 Matrix class + + $Id: mat3.cxx 427 2004-09-27 04:45:31Z garland $ + + ************************************************************************/ + +#include <gfx/gfx.h> +#include <gfx/mat3.h> + +namespace gfx +{ + +Mat3 Mat3::I() { return Mat3(Vec3(1,0,0), Vec3(0,1,0), Vec3(0,0,1)); } + +Mat3 &Mat3::diag(double d) +{ + *this = 0.0; + row[0][0] = row[1][1] = row[2][2] = d; + return *this; +} + +Mat3 diag(const Vec3& v) +{ + return Mat3(Vec3(v[0],0,0), Vec3(0,v[1],0), Vec3(0,0,v[2])); +} + +Mat3 Mat3::outer_product(const Vec3& v) +{ + Mat3 A; + double x=v[0], y=v[1], z=v[2]; + + A(0,0) = x*x; A(0,1) = x*y; A(0,2) = x*z; + A(1,0)=A(0,1); A(1,1) = y*y; A(1,2) = y*z; + A(2,0)=A(0,2); A(2,1)=A(1,2); A(2,2) = z*z; + + return A; +} + +Mat3 Mat3::outer_product(const Vec3& u, const Vec3& v) +{ + Mat3 A; + + for(int i=0; i<3; i++) + for(int j=0; j<3; j++) + A(i, j) = u[i]*v[j]; + + return A; +} + +Mat3 operator*(const Mat3& n, const Mat3& m) +{ + Mat3 A; + + for(int i=0;i<3;i++) + for(int j=0;j<3;j++) + A(i,j) = n[i]*m.col(j); + + return A; +} + +Mat3 adjoint(const Mat3& m) +{ + return Mat3(m[1]^m[2], + m[2]^m[0], + m[0]^m[1]); +} + +double invert(Mat3& inv, const Mat3& m) +{ + Mat3 A = adjoint(m); + double d = A[0] * m[0]; + + if( d==0.0 ) + return 0.0; + + inv = transpose(A) / d; + return d; +} + +} // namespace gfx diff --git a/debian/fireflies/fireflies-2.08/libgfx/src/mat4.cxx b/debian/fireflies/fireflies-2.08/libgfx/src/mat4.cxx new file mode 100644 index 00000000..0ad2a271 --- /dev/null +++ b/debian/fireflies/fireflies-2.08/libgfx/src/mat4.cxx @@ -0,0 +1,206 @@ +/************************************************************************ + + 4x4 Matrix class + + $Id: mat4.cxx 427 2004-09-27 04:45:31Z garland $ + + ************************************************************************/ + +#include <gfx/gfx.h> +#include <gfx/mat4.h> + +namespace gfx +{ + +Mat4 Mat4::I() +{ + return Mat4(Vec4(1,0,0,0),Vec4(0,1,0,0),Vec4(0,0,1,0),Vec4(0,0,0,1)); +} + +Mat4 translation_matrix(const Vec3& d) +{ + return Mat4(Vec4(1, 0, 0, d[0]), + Vec4(0, 1, 0, d[1]), + Vec4(0, 0, 1, d[2]), + Vec4(0, 0, 0, 1)); +} + +Mat4 scaling_matrix(const Vec3& s) +{ + return Mat4(Vec4(s[0], 0, 0, 0), + Vec4(0, s[1], 0, 0), + Vec4(0, 0, s[2], 0), + Vec4(0, 0, 0, 1)); +} + +Mat4 rotation_matrix_rad(double theta, const Vec3& axis) +{ + double c=cos(theta), s=sin(theta), + xx=axis[0]*axis[0], yy=axis[1]*axis[1], zz=axis[2]*axis[2], + xy=axis[0]*axis[1], yz=axis[1]*axis[2], xz=axis[0]*axis[2]; + + double xs=axis[0]*s, ys=axis[1]*s, zs=axis[2]*s; + + Mat4 M; + M(0,0)=xx*(1-c)+c; M(0,1)=xy*(1-c)-zs; M(0,2)=xz*(1-c)+ys; M(0,3) = 0; + M(1,0)=xy*(1-c)+zs; M(1,1)=yy*(1-c)+c; M(1,2)=yz*(1-c)-xs; M(1,3)=0; + M(2,0)=xz*(1-c)-ys; M(2,1)=yz*(1-c)+xs; M(2,2)=zz*(1-c)+c; M(2,3)=0; + M(3,0)=0; M(3,1)=0; M(3,2)=0; M(3,3)=1; + + return M; +} + +Mat4 perspective_matrix(double fovy, double aspect, double zmin, double zmax) +{ + double A, B; + Mat4 M; + + if( zmax==0.0 ) + { + A = B = 1.0; + } + else + { + A = (zmax+zmin)/(zmin-zmax); + B = (2*zmax*zmin)/(zmin-zmax); + } + + double f = 1.0/tan(fovy*M_PI/180.0/2.0); + M(0,0) = f/aspect; + M(1,1) = f; + M(2,2) = A; + M(2,3) = B; + M(3,2) = -1; + M(3,3) = 0; + + return M; +} + +Mat4 lookat_matrix(const Vec3& from, const Vec3& at, const Vec3& v_up) +{ + Vec3 up = v_up; unitize(up); + Vec3 f = at - from; unitize(f); + + Vec3 s=f^up; + Vec3 u=s^f; + + // NOTE: These steps are left out of the GL man page!! + unitize(s); + unitize(u); + + Mat4 M(Vec4(s, 0), Vec4(u, 0), Vec4(-f, 0), Vec4(0, 0, 0, 1)); + + return M * translation_matrix(-from); +} + +Mat4 viewport_matrix(double w, double h) +{ + return scaling_matrix(Vec3(w/2.0, -h/2.0, 1)) * + translation_matrix(Vec3(1, -1, 0)); +} + +Mat4 operator*(const Mat4& n, const Mat4& m) +{ + Mat4 A; + int i,j; + + for(i=0;i<4;i++) + for(j=0;j<4;j++) + A(i,j) = n[i]*m.col(j); + + return A; +} + +Mat4 adjoint(const Mat4& m) +{ + Mat4 A; + + A[0] = cross( m[1], m[2], m[3]); + A[1] = cross(-m[0], m[2], m[3]); + A[2] = cross( m[0], m[1], m[3]); + A[3] = cross(-m[0], m[1], m[2]); + + return A; +} + +double invert_cramer(Mat4& inv, const Mat4& m) +{ + Mat4 A = adjoint(m); + double d = A[0] * m[0]; + + if( d==0.0 ) + return 0.0; + + inv = transpose(A) / d; + return d; +} + + + +// Matrix inversion code for 4x4 matrices using Gaussian elimination +// with partial pivoting. This is a specialized version of a +// procedure originally due to Paul Heckbert <[email protected]>. +// +// Returns determinant of A, and B=inverse(A) +// If matrix A is singular, returns 0 and leaves trash in B. +// +#define SWAP(a, b, t) {t = a; a = b; b = t;} +double invert(Mat4& B, const Mat4& m) +{ + Mat4 A = m; + int i, j, k; + double max, t, det, pivot; + + /*---------- forward elimination ----------*/ + + for (i=0; i<4; i++) /* put identity matrix in B */ + for (j=0; j<4; j++) + B(i, j) = (double)(i==j); + + det = 1.0; + for (i=0; i<4; i++) { /* eliminate in column i, below diag */ + max = -1.; + for (k=i; k<4; k++) /* find pivot for column i */ + if (fabs(A(k, i)) > max) { + max = fabs(A(k, i)); + j = k; + } + if (max<=0.) return 0.; /* if no nonzero pivot, PUNT */ + if (j!=i) { /* swap rows i and j */ + for (k=i; k<4; k++) + SWAP(A(i, k), A(j, k), t); + for (k=0; k<4; k++) + SWAP(B(i, k), B(j, k), t); + det = -det; + } + pivot = A(i, i); + det *= pivot; + for (k=i+1; k<4; k++) /* only do elems to right of pivot */ + A(i, k) /= pivot; + for (k=0; k<4; k++) + B(i, k) /= pivot; + /* we know that A(i, i) will be set to 1, so don't bother to do it */ + + for (j=i+1; j<4; j++) { /* eliminate in rows below i */ + t = A(j, i); /* we're gonna zero this guy */ + for (k=i+1; k<4; k++) /* subtract scaled row i from row j */ + A(j, k) -= A(i, k)*t; /* (ignore k<=i, we know they're 0) */ + for (k=0; k<4; k++) + B(j, k) -= B(i, k)*t; + } + } + + /*---------- backward elimination ----------*/ + + for (i=4-1; i>0; i--) { /* eliminate in column i, above diag */ + for (j=0; j<i; j++) { /* eliminate in rows above i */ + t = A(j, i); /* we're gonna zero this guy */ + for (k=0; k<4; k++) /* subtract scaled row i from row j */ + B(j, k) -= B(i, k)*t; + } + } + + return det; +} + +} // namespace gfx diff --git a/debian/fireflies/fireflies-2.08/libgfx/src/quat.cxx b/debian/fireflies/fireflies-2.08/libgfx/src/quat.cxx new file mode 100644 index 00000000..a3db2a68 --- /dev/null +++ b/debian/fireflies/fireflies-2.08/libgfx/src/quat.cxx @@ -0,0 +1,136 @@ +/************************************************************************ + + Quaternion class + + $Id: quat.cxx 427 2004-09-27 04:45:31Z garland $ + + ************************************************************************/ + +#include <gfx/quat.h> + +namespace gfx +{ + +// Based on code from the Appendix of +// Quaternion Calculus for Computer Graphics, by Ken Shoemake +// Computes the exponential of a quaternion, assuming scalar part w=0 +Quat exp(const Quat& q) +{ + double theta = norm(q.vector()); + double c = cos(theta); + + if( theta > FEQ_EPS ) + { + double s = sin(theta) / theta; + return Quat( s*q.vector(), c); + } + else + return Quat(q.vector(), c); +} + +// Based on code from the Appendix of +// Quaternion Calculus for Computer Graphics, by Ken Shoemake +// Computes the natural logarithm of a UNIT quaternion +Quat log(const Quat& q) +{ + double scale = norm(q.vector()); + double theta = atan2(scale, q.scalar()); + + if( scale > 0.0 ) scale=theta/scale; + + return Quat(scale*q.vector(), 0.0); +} + +Quat axis_to_quat(const Vec3& a, double phi) +{ + Vec3 u = a; + unitize(u); + + double s = sin(phi/2.0); + return Quat(u[0]*s, u[1]*s, u[2]*s, cos(phi/2.0)); +} + +Mat4 quat_to_matrix(const Quat& q) +{ + Mat4 M; + + const double x = q.vector()[0]; + const double y = q.vector()[1]; + const double z = q.vector()[2]; + const double w = q.scalar(); + const double s = 2/norm(q); + + M(0,0)=1-s*(y*y+z*z); M(0,1)=s*(x*y-w*z); M(0,2)=s*(x*z+w*y); M(0,3)=0; + M(1,0)=s*(x*y+w*z); M(1,1)=1-s*(x*x+z*z); M(1,2)=s*(y*z-w*x); M(1,3)=0; + M(2,0)=s*(x*z-w*y); M(2,1)=s*(y*z+w*x); M(2,2)=1-s*(x*x+y*y); M(2,3)=0; + M(3,0)=0; M(3,1)=0; M(3,2)=0; M(3,3)=1; + + return M; +} + +Mat4 unit_quat_to_matrix(const Quat& q) +{ + Mat4 M; + + const double x = q.vector()[0]; + const double y = q.vector()[1]; + const double z = q.vector()[2]; + const double w = q.scalar(); + + M(0,0)=1-2*(y*y+z*z); M(0,1)=2*(x*y-w*z); M(0,2)=2*(x*z+w*y); M(0,3)=0; + M(1,0)=2*(x*y+w*z); M(1,1)=1-2*(x*x+z*z); M(1,2)=2*(y*z-w*x); M(1,3)=0; + M(2,0)=2*(x*z-w*y); M(2,1)=2*(y*z+w*x); M(2,2)=1-2*(x*x+y*y); M(2,3)=0; + M(3,0)=0; M(3,1)=0; M(3,2)=0; M(3,3)=1; + + return M; +} + +Quat slerp(const Quat& from, const Quat& to, double t) +{ + const Vec3& v_from = from.vector(); + const Vec3& v_to = to.vector(); + const double s_from = from.scalar(); + const double s_to = to.scalar(); + + double cosine = v_from*v_to + s_from*s_to; + + if( (1+cosine) < FEQ_EPS ) + { + // The quaternions are (nearly) diametrically opposed. We + // treat this specially (based on suggestion in Watt & Watt). + // + double A = sin( (1-t)*M_PI/2.0 ); + double B = sin( t*M_PI/2.0 ); + + return Quat( A*v_from[0] + B*(-v_from[1]), + A*v_from[1] + B*(v_from[0]), + A*v_from[2] + B*(-s_from), + A*s_from + B*(v_from[2]) ); + } + + double A, B; + if( (1-cosine) < FEQ_EPS ) + { + // The quaternions are very close. Approximate with normal + // linear interpolation. This is cheaper and avoids division + // by very small numbers. + // + A = 1.0 - t; + B = t; + } + else + { + // This is the normal case. Perform SLERP. + // + double theta = acos(cosine); + double sine = sqrt(1 - cosine*cosine); + + A = sin( (1-t)*theta ) / sine; + B = sin( t*theta ) / sine; + + } + + return Quat( A*v_from + B*v_to, A*s_from + B*s_to); +} + +} // namespace gfx diff --git a/debian/fireflies/fireflies-2.08/libgfx/src/raster-jpeg.cxx b/debian/fireflies/fireflies-2.08/libgfx/src/raster-jpeg.cxx new file mode 100644 index 00000000..d6612ed4 --- /dev/null +++ b/debian/fireflies/fireflies-2.08/libgfx/src/raster-jpeg.cxx @@ -0,0 +1,113 @@ +/************************************************************************ + + JPEG image file format support. + + The I/O code in this file was originally based on the example.c + skeleton code distributed with the JPEG library (release 6b). + + $Id: raster-jpeg.cxx 427 2004-09-27 04:45:31Z garland $ + + ************************************************************************/ + +#include <gfx/gfx.h> +#include <gfx/raster.h> + +namespace gfx { +// Quality factors are expressed on a 0--100 scale +int jpeg_output_quality = 100; +} + +#ifdef HAVE_LIBJPEG + +#include <stdio.h> +extern "C" { +#include <jpeglib.h> +} + +namespace gfx +{ + +bool write_jpeg_image(const char *filename, const ByteRaster& img) +{ + FILE *outfile = fopen(filename, "wb"); + if( !outfile ) return false; + + struct jpeg_compress_struct cinfo; + struct jpeg_error_mgr jerr; + + cinfo.err = jpeg_std_error(&jerr); + jpeg_create_compress(&cinfo); + jpeg_stdio_dest(&cinfo, outfile); + + cinfo.image_width = img.width(); + cinfo.image_height = img.height(); + cinfo.input_components = img.channels(); + + if(img.channels()==1) cinfo.in_color_space = JCS_GRAYSCALE; + else if(img.channels()==3) cinfo.in_color_space = JCS_RGB; + else cinfo.in_color_space = JCS_UNKNOWN; + + jpeg_set_defaults(&cinfo); + jpeg_set_quality(&cinfo, jpeg_output_quality, TRUE); + + jpeg_start_compress(&cinfo, TRUE); + + int row_stride = img.width() * img.channels(); + const unsigned char *scanline = img.head(); + while( cinfo.next_scanline < cinfo.image_height ) + { + (void) jpeg_write_scanlines(&cinfo, (JSAMPLE **)&scanline, 1); + scanline += row_stride; + } + + jpeg_finish_compress(&cinfo); + jpeg_destroy_compress(&cinfo); + fclose(outfile); + + return true; +} + +ByteRaster *read_jpeg_image(const char *filename) +{ + FILE *infile = fopen(filename, "rb"); + if( !infile ) return NULL; + + struct jpeg_decompress_struct cinfo; + struct jpeg_error_mgr jerr; + cinfo.err = jpeg_std_error(&jerr); + + jpeg_create_decompress(&cinfo); + jpeg_stdio_src(&cinfo, infile); + + (void) jpeg_read_header(&cinfo, TRUE); + (void) jpeg_start_decompress(&cinfo); + + ByteRaster *img = new ByteRaster(cinfo.output_width, + cinfo.output_height, + cinfo.output_components); + + int row_stride = cinfo.output_width * cinfo.output_components; + unsigned char *scanline = img->head(); + while( cinfo.output_scanline < cinfo.output_height) + { + (void) jpeg_read_scanlines(&cinfo, (JSAMPLE **)&scanline, 1); + scanline += row_stride; + } + + (void) jpeg_finish_decompress(&cinfo); + jpeg_destroy_decompress(&cinfo); + fclose(infile); + return img; +} + +} // namespace gfx + +#else + +namespace gfx +{ +bool write_jpeg_image(const char *, const ByteRaster&) { return false; } +ByteRaster *read_jpeg_image(const char *) { return NULL; } +} + +#endif diff --git a/debian/fireflies/fireflies-2.08/libgfx/src/raster-png.cxx b/debian/fireflies/fireflies-2.08/libgfx/src/raster-png.cxx new file mode 100644 index 00000000..c98da9b1 --- /dev/null +++ b/debian/fireflies/fireflies-2.08/libgfx/src/raster-png.cxx @@ -0,0 +1,180 @@ +/************************************************************************ + + PNG image file format support. + + The I/O code in this file was originally based on the example.c + skeleton code distributed with the PNG library. + + $Id: raster-png.cxx 427 2004-09-27 04:45:31Z garland $ + + ************************************************************************/ + +#include <vector> +#include <gfx/gfx.h> +#include <gfx/raster.h> + +#ifdef HAVE_LIBPNG + +#include <png.h> + +namespace gfx +{ + +ByteRaster *read_png_image(const char *file_name) +{ + FILE *fp = fopen(file_name, "rb"); + if( !fp ) return NULL; + + // The last three arguments can be used to set up error handling callbacks. + png_structp png_ptr = + png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if( !png_ptr ) { fclose(fp); return NULL; } + + // Allocate required structure to hold memory information. + png_infop info_ptr = png_create_info_struct(png_ptr); + if( !info_ptr ) + { + fclose(fp); + png_destroy_read_struct(&png_ptr, NULL, NULL); + return NULL; + } + + // Because we didn't set up any error handlers, we need to be + // prepared to handle longjmps out of the library on error + // conditions. + if( setjmp(png_ptr->jmpbuf) ) + { + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + fclose(fp); + return NULL; + } + + png_init_io(png_ptr, fp); + + // Read in all the image information + png_read_info(png_ptr, info_ptr); + + // Get the header for the first image chunk + png_uint_32 width, height; + int bit_depth, color_type, interlace_type; + + png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, + &interlace_type, NULL, NULL); + + + //////////////////////////////////////////////////////////////// + // the following tell the PNG library how to transform the image + // during input + + if( bit_depth == 16 ) + // truncate 16 bits/pixel to 8 bits/pixel + png_set_strip_16(png_ptr); + + if( color_type == PNG_COLOR_TYPE_PALETTE ) + // expand paletted colors into RGB color values + png_set_expand(png_ptr); + else if( color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8 ) + // expand grayscale images to full 8 bits/pixel + png_set_expand(png_ptr); + + // Expand paletted or RGB images with transparency to full alpha + // channels so the data will be available as RGBA quartets. + if( png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS) ) + png_set_expand(png_ptr); + + // update the palette and info structure + png_read_update_info(png_ptr, info_ptr); + + + // read the image data + std::vector<png_bytep> row_pointers(height); + int row; + int nchan = png_get_channels(png_ptr, info_ptr); + int nbytes = png_get_rowbytes(png_ptr, info_ptr); + + for (row = 0; row < height; row++) + row_pointers[row] = (png_bytep)malloc(nbytes); + + png_read_image(png_ptr, &row_pointers.front()); + png_read_end(png_ptr, info_ptr); + + // Read it into a ByteRaster structure + ByteRaster *img = new ByteRaster(width, height, nchan); + + unsigned char *pixel = img->pixel(0,0); + for(row=0; row<height; row++) + { + memcpy(pixel, row_pointers[row], nbytes); + pixel += nbytes; + } + + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + for(row=0; row<height; row++) free(row_pointers[row]); + + fclose(fp); + return img; +} + +bool write_png_image(const char *file_name, const ByteRaster& img) +{ + FILE *fp = fopen(file_name, "wb"); + if( !fp ) return false; + + png_structp png_ptr = + png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if( !png_ptr ) { fclose(fp); return false; } + + png_infop info_ptr = png_create_info_struct(png_ptr); + if( !info_ptr ) + { + fclose(fp); + png_destroy_write_struct(&png_ptr, (png_infopp)NULL); + return false; + } + + if( setjmp(png_ptr->jmpbuf) ) + { + fclose(fp); + png_destroy_write_struct(&png_ptr, (png_infopp)NULL); + return false; + } + + png_init_io(png_ptr, fp); + + int img_type = PNG_COLOR_TYPE_RGB; + switch( img.channels() ) + { + case 1: img_type=PNG_COLOR_TYPE_GRAY; break; + case 2: img_type=PNG_COLOR_TYPE_GRAY_ALPHA; break; + case 4: img_type=PNG_COLOR_TYPE_RGB_ALPHA; break; + } + + png_set_IHDR(png_ptr, info_ptr, + img.width(), img.height(), 8, img_type, PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); + + png_write_info(png_ptr, info_ptr); + + std::vector<png_bytep> row_pointers(img.height()); + for(int k=0; k<img.height(); k++) + row_pointers[k] = (png_bytep)img.head() +k*img.width()*img.channels(); + + png_write_image(png_ptr, &row_pointers.front()); + png_write_end(png_ptr, info_ptr); + + png_destroy_write_struct(&png_ptr, (png_infopp)NULL); + fclose(fp); + return true; +} + +} // namespace gfx + +#else + +namespace gfx +{ +bool write_png_image(const char *, const ByteRaster&) { return false; } +ByteRaster *read_png_image(const char *) { return NULL; } +} // namespace gfx + +#endif diff --git a/debian/fireflies/fireflies-2.08/libgfx/src/raster-pnm.cxx b/debian/fireflies/fireflies-2.08/libgfx/src/raster-pnm.cxx new file mode 100644 index 00000000..75a88990 --- /dev/null +++ b/debian/fireflies/fireflies-2.08/libgfx/src/raster-pnm.cxx @@ -0,0 +1,174 @@ +/************************************************************************ + + PNM image file format support + + $Id: raster-pnm.cxx 427 2004-09-27 04:45:31Z garland $ + + ************************************************************************/ + +#include <gfx/gfx.h> +#include <gfx/raster.h> + +#include <fstream> + +namespace gfx +{ + +using namespace std; + +bool will_write_raw_pnm = true; + +//////////////////////////////////////////////////////////////////////// +// +// PNM output routine +// + +bool write_pnm_image(const char *filename, const ByteRaster& img) +{ + ofstream out(filename, ios::out|ios::binary); + if( !out.good() ) return false; + + bool is_raw = will_write_raw_pnm; + + // + // First, write the PNM header. + // + char magic; + if(img.channels() == 1) magic = is_raw ? '5':'2'; // PGM + else if(img.channels() < 3) return false; // unsupported + else magic = is_raw ? '6':'3'; // truncate to PPM + + out << "P" << magic << " " + << img.width() << " " << img.height() << " 255" << endl; + + // + // Now, write the PNM data. If there are more than 3 channels, + // we'll just write out the first 3 as RGB and ignore the rest. + // + if( is_raw ) + { + if( img.channels() > 3 ) + for(int i=0; i<img.length(); i+=img.channels()) + out.write((const char *)img.pixel(0,0)+i, 3); + else + out.write((const char *)img.pixel(0,0), img.length()); + } + else + { + for(int i=0; i<img.length(); i+=img.channels()) + { + out << (int)(img[i]) << " " + << (int)(img[i+1]) << " " + << (int)(img[i+2]) << endl; + } + } + + return true; +} + +//////////////////////////////////////////////////////////////////////// +// +// PNM input routines +// + +static +istream& pnm_skip(istream& in) +{ + for(;;) + { + in >> ws; + if( in.peek() == '#' ) + in.ignore(65535, '\n'); + else + return in; + } +} + +static +void pnm_read_ascii(istream& in, ByteRaster& img) +{ + unsigned char *current = img.head(); + int val; + + for(int j=0; j<img.height(); j++) for(int i=0; i<img.width(); i++) + for(int k=0; k<img.channels(); k++) + { + pnm_skip(in) >> val; + *current++ = (unsigned char)val; + } +} + +static +void pnm_read_ascii(istream& in, ByteRaster& img, float scale) +{ + unsigned char *current = img.head(); + float val; + + for(int j=0; j<img.height(); j++) for(int i=0; i<img.width(); i++) + for(int k=0; k<img.channels(); k++) + { + pnm_skip(in) >> val; + *current++ = (unsigned char)(val*scale); + } +} + +static +void pnm_read_raw(istream& in, ByteRaster& img) +{ + char c; in.get(c); // extract 1 whitespace character + + // + // Is this guaranteed to read all the requested bytes? + // + in.read((char *)img.head(), img.length()); +} + +ByteRaster *read_pnm_image(const char *filename) +{ + ifstream in(filename, ios::in|ios::binary); + if( !in.good() ) return NULL; + + // + // Read the PNM header and allocate and appropriate raster. + // + + unsigned char P, N; + in >> P >> N; + + if( P!='P' ) return NULL; + + int width, height, maxval; + pnm_skip(in) >> width; + pnm_skip(in) >> height; + pnm_skip(in) >> maxval; + + int magic = N - '0'; + bool is_raw = magic > 3; + + int channels = 1; + if( magic==3 || magic==6 ) + channels = 3; + + ByteRaster *img = new ByteRaster(width, height, channels); + + // + // Read the image data into the raster + // + + if( is_raw ) + { + if( maxval>255 ) return NULL; + + // BUG: We ignore the scaling implied by maxval<255 + + pnm_read_raw(in, *img); + } + else if( maxval==255 ) + pnm_read_ascii(in, *img); + else + pnm_read_ascii(in, *img, 255.0f/(float)maxval); + + return img; +} + +} // namespace gfx diff --git a/debian/fireflies/fireflies-2.08/libgfx/src/raster-tiff.cxx b/debian/fireflies/fireflies-2.08/libgfx/src/raster-tiff.cxx new file mode 100644 index 00000000..a0005849 --- /dev/null +++ b/debian/fireflies/fireflies-2.08/libgfx/src/raster-tiff.cxx @@ -0,0 +1,158 @@ +/************************************************************************ + + TIFF image file format support. + + $Id: raster-tiff.cxx 427 2004-09-27 04:45:31Z garland $ + + ************************************************************************/ + +#include <gfx/gfx.h> +#include <gfx/raster.h> +#include <cstring> + +#ifdef HAVE_LIBTIFF +#include <tiffio.h> + +namespace gfx +{ + +//////////////////////////////////////////////////////////////////////// +// +// TIFF output +// +static +bool __tiff_write(TIFF *tif, const ByteRaster& img) +{ + TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, img.width()); + TIFFSetField(tif, TIFFTAG_IMAGELENGTH, img.height()); + + TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT); + TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, img.channels()); + TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8); + TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); + TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, + img.channels()==1 ? PHOTOMETRIC_MINISBLACK : PHOTOMETRIC_RGB); + +#ifdef HAVE_LIBTIFF_LZW + // + // LZW compression is problematic because it is patented by Unisys. + TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_LZW); + // + // Predictors: + // 1 (default) -- No predictor + // 2 -- Horizontal differencing + TIFFSetField(tif, TIFFTAG_PREDICTOR, 2); +#endif + + uint32 scanline_size = img.channels() * img.width(); + if( TIFFScanlineSize(tif) != scanline_size ) + // ??BUG: Can this mismatch of scanline sizes every occur? + return false; + + + TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, TIFFDefaultStripSize(tif, 0)); + + char *scanline_buf = new char[scanline_size]; + + const unsigned char *scanline = img.head(); + for(int y=0; y<img.height(); y++) + { + memcpy(scanline_buf, scanline, scanline_size); + // NOTE: TIFFWriteScanline modifies the buffer you pass it. + // Thus, we need to copy stuff out of the raster first. + TIFFWriteScanline(tif, scanline_buf, y, 0); + scanline += scanline_size; + } + delete[] scanline_buf; + + return true; +} + +bool write_tiff_image(const char *filename, const ByteRaster& img) +{ + TIFF *tif = TIFFOpen(filename, "w"); + if( !tif ) return false; + + bool result = __tiff_write(tif, img); + + TIFFClose(tif); + + return result; +} + +//////////////////////////////////////////////////////////////////////// +// +// TIFF input +// +static +void unpack_tiff_raster(uint32 *raster, ByteRaster *img, int npixels) +{ + unsigned char *pix = img->head(); + + for(int i=0; i<npixels; i++) + { + *pix++ = TIFFGetR(raster[i]); + if( img->channels() >= 3 ) + { + *pix++ = TIFFGetG(raster[i]); + *pix++ = TIFFGetB(raster[i]); + if( img->channels() == 4 ) + *pix++ = TIFFGetA(raster[i]); + } + } +} + +static +ByteRaster *__tiff_read(TIFF *tif) +{ + uint32 w, h; + uint16 nchan; + TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &w); + TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &h); + TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &nchan); + + int npixels = w*h; + + uint32 *raster = (uint32 *)_TIFFmalloc(npixels * sizeof(uint32)); + if( !raster ) return NULL; + + TIFFReadRGBAImage(tif, w, h, raster, true); + + ByteRaster *img = new ByteRaster(w, h, nchan); + unpack_tiff_raster(raster, img, npixels); + // + // libtiff returned the pixels with the origin in the lower left + // rather than the upper left corner. We fix that by flipping the + // pixels. + // + img->vflip(); + + + _TIFFfree(raster); + + return img; +} + +ByteRaster *read_tiff_image(const char *filename) +{ + TIFF *tif = TIFFOpen(filename, "r"); + if( !tif ) return NULL; + + ByteRaster *img = __tiff_read(tif); + + TIFFClose(tif); + + return img; +} + +} // namespace gfx + +#else + +namespace gfx +{ +bool write_tiff_image(const char *, const ByteRaster&) { return false; } +ByteRaster *read_tiff_image(const char *) { return NULL; } +} + +#endif diff --git a/debian/fireflies/fireflies-2.08/libgfx/src/raster.cxx b/debian/fireflies/fireflies-2.08/libgfx/src/raster.cxx new file mode 100644 index 00000000..e5a15228 --- /dev/null +++ b/debian/fireflies/fireflies-2.08/libgfx/src/raster.cxx @@ -0,0 +1,113 @@ +/************************************************************************ + + Raster image support. + + $Id: raster.cxx 427 2004-09-27 04:45:31Z garland $ + + ************************************************************************/ + +#include <gfx/gfx.h> +#include <gfx/raster.h> + +#include <string> +#include <cctype> +#include <cstring> + +namespace gfx +{ + +ByteRaster::ByteRaster(const ByteRaster &img) + : Raster<unsigned char>(img.width(), img.height(), img.channels()) +{ + memcpy(head(), img.head(), img.length()*sizeof(unsigned char)); +} + +ByteRaster::ByteRaster(const FloatRaster &img) + : Raster<unsigned char>(img.width(), img.height(), img.channels()) +{ + for(int i=0; i<length(); i++ ) + (*this)[i] = (unsigned char) (255.0f * img[i]); +} + +FloatRaster::FloatRaster(const ByteRaster &img) + : Raster<float>(img.width(), img.height(), img.channels()) +{ + for(int i=0; i<length(); i++) + (*this)[i] = (float)img[i] / 255.0f; +} + +FloatRaster::FloatRaster(const FloatRaster &img) + : Raster<float>(img.width(), img.height(), img.channels()) +{ + memcpy(head(), img.head(), img.length()*sizeof(float)); +} + +//////////////////////////////////////////////////////////////////////// +// +// Table of supported formats +// + + + +static char *img_names[] = {"PPM", "PNG", "TIFF", "JPEG"}; +static char *img_ext[] = {"ppm", "png", "tif", "jpg"}; + +const char *image_type_name(int type) + { return type>=IMG_LIMIT ? NULL : img_names[type]; } + +const char *image_type_ext(int type) + { return type>=IMG_LIMIT ? NULL : img_ext[type]; } + + +int infer_image_type(const char *filename) +{ + const char *ext = strrchr(filename, '.'); + if( !ext ) return -1; + + // Make sure extension is lower case + std::string lo(ext+1); + for(int i=0; i<lo.length(); i++) lo[i] = tolower(lo[i]); + + // Search for extension in the table + for(int typ=0; typ<IMG_LIMIT; typ++) + if(lo == img_ext[typ]) return typ; + + // Test for alternatives + if(lo=="tiff") return IMG_TIFF; + + // Unknown type + return -1; +} + + +bool write_image(const char *filename, const ByteRaster& img, int type) +{ + if( type<0 ) + type = infer_image_type(filename); + + switch( type ) + { + case IMG_PNM: return write_pnm_image(filename, img); + case IMG_PNG: return write_png_image(filename, img); + case IMG_TIFF: return write_tiff_image(filename, img); + case IMG_JPEG: return write_jpeg_image(filename, img); + default: return false; + } +} + +ByteRaster *read_image(const char *filename, int type) +{ + if( type<0 ) + type = infer_image_type(filename); + + switch( type ) + { + case IMG_PNM: return read_pnm_image(filename); + case IMG_PNG: return read_png_image(filename); + case IMG_TIFF: return read_tiff_image(filename); + case IMG_JPEG: return read_jpeg_image(filename); + default: return NULL; + } +} + +} // namespace gfx diff --git a/debian/fireflies/fireflies-2.08/libgfx/src/script.cxx b/debian/fireflies/fireflies-2.08/libgfx/src/script.cxx new file mode 100644 index 00000000..5f1bdff2 --- /dev/null +++ b/debian/fireflies/fireflies-2.08/libgfx/src/script.cxx @@ -0,0 +1,295 @@ +#include <gfx/script.h> +#include <fstream> + +#if !defined(HAVE_SSTREAM) && defined(HAVE_STRSTREAM) +# include <strstream> +typedef istrstream istringstream; +#else +# include <sstream> +#endif + +#ifdef HAVE_GZSTREAM +# include <gzstream.h> +#endif + +namespace gfx +{ + +using namespace std; + + +//////////////////////////////////////////////////////////////////////// +// +// CmdLine methods -- These implement all the basic line manipulations +// + +string CmdLine::token_to_string(int i) const { return substr(tokens[i]); } + +string CmdLine::rest_to_string(int i) const +{ + return line.substr(tokens[i].first); +} + +double CmdLine::token_to_double(int i) const + { string str = substr(tokens[i]); return atof(str.c_str()); } + +float CmdLine::token_to_float(int i) const + { string str = substr(tokens[i]); return atof(str.c_str()); } + +int CmdLine::token_to_int(int i) const + { string str = substr(tokens[i]); return atoi(str.c_str()); } + +string CmdLine::argline() const +{ + if( argcount() == 0 ) return ""; + + index_type start = tokens.front().first; + index_type end = tokens.back().second; + return substr(range_type(start, end)); +} + +int CmdLine::collect_as_strings(vector<string> &v, int offset) const +{ + for(int i=offset; i<tokens.size(); i++) + v.push_back( substr(tokens[i]) ); + return tokens.size(); +} + +int CmdLine::collect_as_numbers(vector<double> &v, int offset) const +{ + for(int i=offset; i<tokens.size(); i++) + v.push_back(token_to_double(i)); + return tokens.size(); +} + +int CmdLine::collect_as_numbers(vector<int> &v, int offset) const +{ + for(int i=offset; i<tokens.size(); i++) + v.push_back(token_to_int(i)); + return tokens.size(); +} + +int CmdLine::collect_as_numbers(double *v, int size, int offset) const +{ + int i; + for(i=0; (i+offset)<tokens.size() && i<size; i++) + v[i] = token_to_double(i+offset); + return i; +} + +int CmdLine::collect_as_numbers(float *v, int size, int offset) const +{ + int i; + for(i=0; (i+offset)<tokens.size() && i<size; i++) + v[i] = token_to_float(i+offset); + return i; +} + +int CmdLine::collect_as_numbers(int *v, int size, int offset) const +{ + int i; + for(i=0; (i+offset)<tokens.size() && i<size; i++) + v[i] = token_to_int(i+offset); + return i; +} + +//////////////////////////////////////////////////////////////////////// +// +// CmdEnv methods -- Minimal interface supported by all environments +// + +void CmdEnv::register_command(const std::string& name, CmdObject *fn) +{ + script_commands[name] = fn; +} + +void CmdEnv::register_command(const std::string& name, CmdHandler proc) +{ + register_command(name, new CmdFunction(proc)); +} + +CmdObject *CmdEnv::lookup_command(const std::string& name) +{ + CmdTable::const_iterator iter = script_commands.find(name); + + return iter!=script_commands.end() ? iter->second : NULL; +} + +static int ignored(const CmdLine& line) { return SCRIPT_OK; } + +void CmdEnv::ignore_command(const std::string& name) +{ + register_command(name, ignored); +} + +void CmdEnv::register_vocabulary(const std::string& name, CmdEnv *env) +{ + register_method(name, env, &CmdEnv::script_eval); +} + +CmdEnv::CmdEnv() +{ + register_method("include", this, &CmdEnv::script_include); + register_method("ignore", this, &CmdEnv::script_ignore); + register_method("end", this, &CmdEnv::script_end); +} + +CmdEnv::~CmdEnv() +{ + // Free all the CmdObject's held by script_commands + // + for(CmdTable::iterator i = script_commands.begin(); + i != script_commands.end(); ++i) + { + CmdObject *obj = i->second; + delete obj; + } +} + +int CmdEnv::script_include(const CmdLine& cmd) +{ + if( cmd.argcount() != 1 ) return SCRIPT_ERR_SYNTAX; + + string filename = cmd.token_to_string(0); + return do_file(cmd.token_to_string(0)); +} + +int CmdEnv::script_ignore(const CmdLine& cmd) +{ + for(int i=0; i<cmd.argcount(); ++i) + { + string name = cmd.token_to_string(i); + ignore_command(name); + } + + return SCRIPT_OK; +} + +int CmdEnv::script_end(const CmdLine& cmd) +{ + return SCRIPT_END; +} + +int CmdEnv::script_eval(const CmdLine& cmd) +{ + return do_line(cmd.argline()); +} + +void CmdEnv::begin_scope(CmdEnv *sub) { scopes.push_back(sub); } + +void CmdEnv::end_scope() +{ + if( scopes.size() > 0 ) + { + CmdEnv *sub = scopes.back(); + scopes.pop_back(); + delete sub; + } +} + +//////////////////////////////////////////////////////////////////////// +// +// Toplevel functions -- extract and execute scripting commands +// + +int CmdEnv::do_line(const string &line) +{ + CmdEnv& env = *this; + + // Pass this line off to the sub-scope (if any) + if( scopes.size() > 0 && scopes.back() ) + { + int rc = scopes.back()->do_line(line); + if( rc==SCRIPT_END ) + { + end_scope(); + rc = SCRIPT_OK; + } + return rc; + } + + const char *ws = " \t\n\r"; + string::size_type start, end; + + // First, process the initial (command) token + start = line.find_first_not_of(ws); + + // Only continue processing if line is a non-empty, non-comment line + if( start!=string::npos && line[start]!='#' ) + { + end = line.find_first_of(ws, start); + string op = line.substr(start, end-start); + + CmdObject *fn = env.lookup_command(op); + if( !fn ) return SCRIPT_ERR_UNDEF; + + CmdLine argv(line); + argv.op = CmdLine::range_type(start, end); + + while(1) + { + start = line.find_first_not_of(ws, end); + if( start==string::npos ) break; + end = line.find_first_of(ws, start); + + argv.tokens.push_back( CmdLine::range_type(start, end) ); + } + + return (*fn)(argv); + } + + return SCRIPT_OK; +} + +int CmdEnv::do_stream(istream &in) +{ + string line; + + while( !in.eof() ) + { + getline(in, line); + if( in.fail() ) break; + + int rc = do_line(line); + if( rc != SCRIPT_OK ) + { + cerr << "Script Error: " << line << endl; + return rc; + } + } + + return SCRIPT_OK; +} + +int CmdEnv::do_file(const std::string& filename) +{ +#ifdef HAVE_GZSTREAM + if( !filename.compare(filename.size()-3, 3, ".gz") || + !filename.compare(filename.size()-2, 2, ".z") || + !filename.compare(filename.size()-2, 2, ".Z") ) + { + igzstream in(filename.c_str()); + if( in.good() ) return do_stream(in); + else return SCRIPT_ERR_NOFILE; + } + else + { + ifstream in(filename.c_str()); + if( in.good() ) return do_stream(in); + else return SCRIPT_ERR_NOFILE; + } +#else + ifstream in(filename.c_str()); + if( in.good() ) return do_stream(in); + else return SCRIPT_ERR_NOFILE; +#endif +} + +int CmdEnv::do_string(const std::string& str) +{ + istringstream in(str.c_str()); + if( in.good() ) return CmdEnv::do_stream(in); + else return SCRIPT_ERR_NOFILE; +} + +} // namespace gfx diff --git a/debian/fireflies/fireflies-2.08/libgfx/src/symmat2.cxx b/debian/fireflies/fireflies-2.08/libgfx/src/symmat2.cxx new file mode 100644 index 00000000..df923f33 --- /dev/null +++ b/debian/fireflies/fireflies-2.08/libgfx/src/symmat2.cxx @@ -0,0 +1,61 @@ +#include <gfx/gfx.h> +#include <gfx/symmat2.h> + +namespace gfx +{ + +SymMat2 SymMat2::I() +{ + SymMat2 A; + A(0,0) = A(1,1) = 1; + return A; +} + +Mat2 SymMat2::fullmatrix() const +{ + Mat2 A; + + for(int i=0; i<A.dim(); i++) + for(int j=0; j<A.dim(); j++) + A(i, j) = (*this)(i,j); + + return A; +} + +SymMat2 operator*(const SymMat2& n, const SymMat2& m) +{ + SymMat2 A; + for(int i=0; i<2; i++) for(int j=i; j<2; j++) + A(i,j) = n.row(i)*m.col(j); + return A; +} + +std::ostream &operator<<(std::ostream &out, const SymMat2& M) +{ + for(int i=0; i<M.dim(); i++) + { + for(int j=0; j<M.dim(); j++) + out << M(i, j) << " "; + out << std::endl; + } + + return out; +} + +SymMat2 SymMat2::outer_product(const Vec2& v) +{ + SymMat2 A; + + for(int i=0; i<A.dim(); i++) + for(int j=i; j<A.dim(); j++) + A(i, j) = v[i]*v[j]; + + return A; +} + +double invert(Mat2& m_inv, const SymMat2& m) +{ + return invert(m_inv, m.fullmatrix()); +} + +} // namespace gfx diff --git a/debian/fireflies/fireflies-2.08/libgfx/src/symmat3.cxx b/debian/fireflies/fireflies-2.08/libgfx/src/symmat3.cxx new file mode 100644 index 00000000..36c684e3 --- /dev/null +++ b/debian/fireflies/fireflies-2.08/libgfx/src/symmat3.cxx @@ -0,0 +1,61 @@ +#include <gfx/gfx.h> +#include <gfx/symmat3.h> + +namespace gfx +{ + +SymMat3 SymMat3::I() +{ + SymMat3 A; + A(0,0) = A(1,1) = A(2,2) = 1; + return A; +} + +Mat3 SymMat3::fullmatrix() const +{ + Mat3 A; + + for(int i=0; i<A.dim(); i++) + for(int j=0; j<A.dim(); j++) + A(i, j) = (*this)(i,j); + + return A; +} + +SymMat3 operator*(const SymMat3& n, const SymMat3& m) +{ + SymMat3 A; + for(int i=0; i<3; i++) for(int j=i; j<3; j++) + A(i,j) = n.row(i)*m.col(j); + return A; +} + +std::ostream &operator<<(std::ostream &out, const SymMat3& M) +{ + for(int i=0; i<M.dim(); i++) + { + for(int j=0; j<M.dim(); j++) + out << M(i, j) << " "; + out << std::endl; + } + + return out; +} + +SymMat3 SymMat3::outer_product(const Vec3& v) +{ + SymMat3 A; + + for(int i=0; i<A.dim(); i++) + for(int j=i; j<A.dim(); j++) + A(i, j) = v[i]*v[j]; + + return A; +} + +double invert(Mat3& m_inv, const SymMat3& m) +{ + return invert(m_inv, m.fullmatrix()); +} + +} // namespace gfx diff --git a/debian/fireflies/fireflies-2.08/libgfx/src/symmat4.cxx b/debian/fireflies/fireflies-2.08/libgfx/src/symmat4.cxx new file mode 100644 index 00000000..d8483017 --- /dev/null +++ b/debian/fireflies/fireflies-2.08/libgfx/src/symmat4.cxx @@ -0,0 +1,52 @@ +/************************************************************************ + + 4X4 Symmetric Matrix class + + $Id: symmat4.cxx 427 2004-09-27 04:45:31Z garland $ + + ************************************************************************/ +#include <gfx/symmat4.h> + +namespace gfx +{ + +SymMat4 SymMat4::I() +{ + SymMat4 A; + A(0,0) = A(1,1) = A(2,2) = A(3,3) = 1; + return A; +} + +Mat4 SymMat4::fullmatrix() const +{ + Mat4 temp; + for (int i=0; i<4; i++) + for (int j=0; j<4; j++) + temp(i,j) = (*this) (i,j); + return temp; +} + +SymMat4 SymMat4::outer_product(const Vec4& v) +{ + SymMat4 tmp; + for(int i=0; i<4; i++) + for(int j=0; j<4; j++) + tmp(i,j)=v[i]*v[j]; + return tmp; +} + +SymMat4 operator* (const SymMat4& n, const SymMat4& m) +{ + SymMat4 temp; + for (int i=0; i<4; i++) + for(int j=0; j<4; j++) + temp(i,j)=n.row(i) * m.col(j); + return temp; +} + +double invert(Mat4& m_inv, const SymMat4& m) +{ + return invert(m_inv, m.fullmatrix()); +} + +} // namespace gfx diff --git a/debian/fireflies/fireflies-2.08/libgfx/src/time.cxx b/debian/fireflies/fireflies-2.08/libgfx/src/time.cxx new file mode 100644 index 00000000..cbbea1c5 --- /dev/null +++ b/debian/fireflies/fireflies-2.08/libgfx/src/time.cxx @@ -0,0 +1,86 @@ +/************************************************************************ + + Routines for measuring time. + + $Id: time.cxx 427 2004-09-27 04:45:31Z garland $ + + ************************************************************************/ + +#include <gfx/gfx.h> + +#if defined(WIN32) +#define WIN32_LEAN_AND_MEAN +#include <windows.h> + +namespace gfx +{ +// Only Windows NT supports getting proper time usage information. +// In Windows 95, we have to settle for measuring real time. +double get_cpu_time() +{ + FILETIME start, end, kernel, user; + + if( !GetThreadTimes(GetCurrentThread(), &start, &end, &kernel, &user) ) + { + // We're running under Windows 95 instead of NT. + // Just get the current time and be done with it. + SYSTEMTIME now; + GetSystemTime(&now); + SystemTimeToFileTime(&now, &user); + } + + // Convert into something we can do math on + LARGE_INTEGER i; + i.LowPart = user.dwLowDateTime; + i.HighPart = user.dwHighDateTime; + +#ifdef __GNUC__ + + // The Win32 headers shipped with GCC don't define the QuadPart + // accessor for the LARGE_INTEGER type. So we have to build it + // directly. + long long quad = i.HighPart; + quad = (quad << 32) + i.LowPart; + return (double)quad / 1e7; +#else + // Convert to seconds and return + return (double)(i.QuadPart) / 1e7; +#endif +} +} + +#elif defined(HAVE_GETRUSAGE) +#include <sys/time.h> +#include <sys/resource.h> + +namespace gfx +{ +double get_cpu_time() +{ + struct rusage t; + + getrusage(RUSAGE_SELF, &t); + + return (double)t.ru_utime.tv_sec + (double)t.ru_utime.tv_usec/1000000; +} +} + +#elif defined(HAVE_TIMES) + +namespace gfx +{ +double get_cpu_time() +{ + struct tms t; + + times(&t); + + return (double)(t.tms_utime) / (double)CLK_TCK; +} +} + +#else + +#error "No supported timing mechanism available." + +#endif diff --git a/debian/fireflies/fireflies-2.08/libgfx/src/trackball.cxx b/debian/fireflies/fireflies-2.08/libgfx/src/trackball.cxx new file mode 100644 index 00000000..40615660 --- /dev/null +++ b/debian/fireflies/fireflies-2.08/libgfx/src/trackball.cxx @@ -0,0 +1,153 @@ +/************************************************************************ + + Virtual Trackball for manipulating objects on the screen. + + This code is based on the virtual trackball mechanism developed by + Gavin Bell of Silicon Graphics. + + $Id: trackball.cxx 427 2004-09-27 04:45:31Z garland $ + + ************************************************************************/ + +#include <gfx/gfx.h> +#include <gfx/gl.h> +#include <gfx/trackball.h> + +namespace gfx +{ + +static +float proj_to_sphere(float r, float x, float y) +{ + // This is a magic number taken from the SGI trackball. + // + const float MAGIC_RLIMIT = 0.70710678118654752440f; + + // Project (x,y) onto a sphere of radius r or a hyperbolic sheet + // if the point is far enough away from the origin. + // + float d = sqrt(x*x + y*y); + if (d < r * MAGIC_RLIMIT ) + { + // Inside sphere + return sqrt(r*r - d*d); + } + else + { + // On hyperbola + float t = r * MAGIC_RLIMIT; + return t*t / d; + } +} + +// +// This is the core routine that actually simulates the action of the +// trackball. It projects the given coordinates onto the trackball +// surface, and computes an appropriate rotation. +// +// NOTE: This uses the combined spherical/hyperbolic trackball surface +// used in the SGI trackball. +// +void trackball(Quat& q, float p1x, float p1y, float p2x, float p2y) +{ + if (p1x == p2x && p1y == p2y) + { + q = Quat::ident(); + return; + } + + // This is a magic number taken from the SGI trackball source. + // Here is the original explanation of this constant: + // + // This size should really be based on the distance from the + // center of rotation to the point on the object underneath + // the mouse. That point would then track the mouse as + // closely as possible. This is a simple example, though, so + // that is left as an Exercise for the Programmer. + // + const float TRACKBALLSIZE = 0.8f; + + // Project the window coordinates onto the trackball surface. + // + Vec3 p1(p1x,p1y,proj_to_sphere(TRACKBALLSIZE,p1x,p1y)); + Vec3 p2(p2x,p2y,proj_to_sphere(TRACKBALLSIZE,p2x,p2y)); + + // And how much do we rotate? + // + float t = norm(p1-p2) / (2.0*TRACKBALLSIZE); + if (t > 1.0) t = 1.0; + if (t < -1.0) t = -1.0; + + // Convert this axis/angle rotation to a quaternion. + // + q = axis_to_quat(p2^p1, 2.0*asin(t)); +} + +static +void add_quats(const Quat& q1, const Quat& q2, Quat& dest) +{ + dest = q2*q1; + unitize(dest); +} + +//////////////////////////////////////////////////////////////////////// +// +// Encapsulate the standard interface of the trackball to simplify +// its use in most applications. +// + +Trackball::Trackball() +{ +} + +void Trackball::update_animation() +{ + add_quats(lastquat, curquat, curquat); +} + +bool Trackball::mouse_up(int *where, int which) +{ + return false; +} + +bool Trackball::mouse_down(int *where, int which) +{ + if( which==1 ) + lastquat = Quat::ident(); + + return false; +} + +bool Trackball::mouse_drag(int *where, int *last, int which) +{ + float vp[4]; + glGetFloatv(GL_VIEWPORT, vp); + float W=vp[2], H=vp[3]; + + float diam = 2*radius; + + if( which==1 ) + { + trackball(lastquat, + (2.0 * last[0] - W)/W, + (H - 2.0 * last[1])/H, + (2.0 * where[0] - W)/W, + (H - 2.0 * where[1])/H); + add_quats(lastquat, curquat, curquat); + } + else if( which==2 ) + { + trans[0] += diam * (where[0] - last[0]) / W; + trans[1] += diam * (last[1] - where[1]) / H; + } + else if( which==3 ) + { + trans[2] += 0.02*diam*(where[1] - last[1]); + } + else + return false; + + return true; +} + +} // namespace gfx diff --git a/debian/fireflies/fireflies-2.08/libgfx/src/wintools.cxx b/debian/fireflies/fireflies-2.08/libgfx/src/wintools.cxx new file mode 100644 index 00000000..dc4fae15 --- /dev/null +++ b/debian/fireflies/fireflies-2.08/libgfx/src/wintools.cxx @@ -0,0 +1,88 @@ +/************************************************************************ + + Support code for handling various tasks under Win32 + + $Id: wintools.cxx 427 2004-09-27 04:45:31Z garland $ + + ************************************************************************/ + +#include <gfx/win/wintools.h> + +namespace gfx +{ + +HGLRC create_glcontext(HDC dc) +{ + HGLRC context = wglCreateContext(dc); + if( context ) + { + if( !wglMakeCurrent(dc, context) ) + { + // Destroy context if it fails to bind + wglDeleteContext(context); + context = NULL; + } + } + + return context; +} + +int set_pixel_format(HDC dc) +{ + PIXELFORMATDESCRIPTOR pixelDesc; + + // + // These are the important fields of the PFD + // + pixelDesc.nSize = sizeof(PIXELFORMATDESCRIPTOR); + pixelDesc.nVersion = 1; + + pixelDesc.dwFlags = + PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | + PFD_DOUBLEBUFFER | PFD_STEREO_DONTCARE; + pixelDesc.iPixelType = PFD_TYPE_RGBA; + pixelDesc.cColorBits = 24; + pixelDesc.iLayerType = PFD_MAIN_PLANE; + + // + // According to the docs, these can be/are ignored. + // + pixelDesc.cRedBits = 8; + pixelDesc.cRedShift = 16; + pixelDesc.cGreenBits = 8; + pixelDesc.cGreenShift = 8; + pixelDesc.cBlueBits = 8; + pixelDesc.cBlueShift = 0; + pixelDesc.cAlphaBits = 0; + pixelDesc.cAlphaShift = 0; + pixelDesc.cAccumBits = 0; + pixelDesc.cAccumRedBits = 0; + pixelDesc.cAccumGreenBits = 0; + pixelDesc.cAccumBlueBits = 0; + pixelDesc.cAccumAlphaBits = 0; + pixelDesc.cDepthBits = 32; + pixelDesc.cStencilBits = 0; + pixelDesc.cAuxBuffers = 0; + pixelDesc.bReserved = 0; + pixelDesc.dwLayerMask = 0; + pixelDesc.dwVisibleMask = 0; + pixelDesc.dwDamageMask = 0; + + + int pixel_format = ChoosePixelFormat(dc, &pixelDesc); + if( !pixel_format ) + { + // Try and guess a decent default pixel format + pixel_format = 1; + if( !DescribePixelFormat(dc, pixel_format, + sizeof(PIXELFORMATDESCRIPTOR), &pixelDesc) ) + return NULL; + } + + if( !SetPixelFormat(dc, pixel_format, &pixelDesc) ) + return NULL; + + return pixel_format; +} + +} // namespace gfx |