diff --git a/bazaar/FTGL_Demo/FTGLCtrl.cpp b/bazaar/FTGL_Demo/FTGLCtrl.cpp new file mode 100644 index 000000000..f5446cac7 --- /dev/null +++ b/bazaar/FTGL_Demo/FTGLCtrl.cpp @@ -0,0 +1,542 @@ +#include "FTGLCtrl.h" + +FTGLCtrl::FTGLCtrl() : trackBall(this) +{ + mode = INTERACTIVE; + + currentFont = FTGL_EXTRUDE; + + myString = + "OpenGL is a powerful software interface for graphics " + "hardware that allows graphics programmers to produce high-quality " + "color images of 3D objects. abcdefghijklmnopqrstuvwxyzABCDEFGHIJKL" + "MNOPQRSTUVWXYZ0123456789"; + + totalFonts = 0; + + layouts.Add(new FTSimpleLayout); + currentLayout = 0; + + OX = -100; + OY = 200; + +#ifdef PLATFORM_OSX11 + SetFontFiles(Vector() + << "/System/Library/Fonts/Helvetica.dfont", + << "/System/Library/Fonts/Geneva.dfont" + ; +#elif defined(WIN32) + SetFontFiles(Vector() + << "C:\\WINDOWS\\Fonts\\arial.ttf" + ); +#elif defined(PLATFORM_LINUX) + SetFontFiles(Vector() + << "/usr/share/fonts/truetype/msttcorefonts/arial.ttf" + ); +#else +#error "UNSUPPORTED PLATFORM -- ADD HERE DEFAULT FONTS" +#endif + + initialLineLength = 300.0f; + + FTSimpleLayout &sl = (FTSimpleLayout &)layouts.Top(); + sl.SetLineLength(initialLineLength); + sl.SetFont(&fonts[currentFont]); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glClearColor(0.13, 0.17, 0.32, 0.0); + glColor3f(1.0, 1.0, 1.0); + + glEnable(GL_CULL_FACE); + glFrontFace(GL_CCW); + + glEnable(GL_DEPTH_TEST); + + glEnable(GL_POLYGON_OFFSET_LINE); + glPolygonOffset(1.0, 1.0); // ???? + + SetCamera(); +} + +bool FTGLCtrl::Key(dword key, int count) +{ + FTSimpleLayout *l = NULL; + + // If the currentLayout is a SimpleLayout store a pointer in l + if(hasLayout() && (dynamic_cast (&layouts[currentLayout]))) + l = (FTSimpleLayout *)&layouts[currentLayout]; + + switch (key) + { + case K_ESCAPE: + GetMainWindow()->Break(); + break; + + case K_RETURN: + if(mode == EDITING) + mode = INTERACTIVE; + else + mode = EDITING; + break; + + case K_TAB: + if(l) + { + // Decrement the layout + switch (l->GetAlignment()) + { + case FTGL::ALIGN_LEFT: + l->SetAlignment(FTGL::ALIGN_RIGHT); + break; + + case FTGL::ALIGN_RIGHT: + l->SetAlignment(FTGL::ALIGN_CENTER); + break; + + case FTGL::ALIGN_CENTER: + l->SetAlignment(FTGL::ALIGN_JUSTIFY); + break; + + case FTGL::ALIGN_JUSTIFY: + l->SetAlignment(FTGL::ALIGN_LEFT); + break; + } + } + break; + + case K_UP: + currentFont = (GetFace()*NumStyles + (currentFont + 1) % NumStyles) % totalFonts; + break; + + case K_DOWN: + currentFont = (GetFace()*NumStyles + (currentFont + NumStyles - 1) % NumStyles) % totalFonts; + break; + + case K_LEFT: + fonts[currentFont].FaceSize(fonts[currentFont].FaceSize() - 1); + break; + + case K_RIGHT: + fonts[currentFont].FaceSize(fonts[currentFont].FaceSize() + 1); + break; + + case K_PAGEUP: + currentFont = (currentFont + NumStyles) % totalFonts; + break; + + case K_PAGEDOWN: + currentFont = (currentFont + totalFonts - NumStyles) % totalFonts; + break; + + case K_HOME: + currentLayout = (currentLayout + 1) % layouts.GetCount(); + break; + + case K_END: + currentLayout = (currentLayout + layouts.GetCount() - 1) % layouts.GetCount(); + break; + + case K_F1: + case K_F10: + // If the current layout is simple decrement its line length + if (l) + l->SetLineLength(l->GetLineLength() - 10.0f); + break; + + case K_F2: + case K_F11: + // If the current layout is simple increment its line length + if (l) + l->SetLineLength(l->GetLineLength() + 10.0f); + break; + + default: + if(mode == EDITING) + { + if(isprint(key)) + myString << (char)key; + else if(key == K_BACKSPACE && myString.GetCount() > 0) + myString.Trim(myString.GetCount() - 1); + } + break; + } + + // If the current layout is a SimpleLayout, update its font. + if(l) + l->SetFont(&fonts[currentFont]); + + Refresh(); + Sync(); + + return true; +} + +void FTGLCtrl::SetUpLighting() +{ + // Set up lighting. + float light1_ambient[4] = { 1.0, 1.0, 1.0, 1.0 }; + float light1_diffuse[4] = { 1.0, 0.9, 0.9, 1.0 }; + float light1_specular[4] = { 1.0, 0.7, 0.7, 1.0 }; + float light1_position[4] = { -1.0, 1.0, 1.0, 0.0 }; + glLightfv(GL_LIGHT1, GL_AMBIENT, light1_ambient); + glLightfv(GL_LIGHT1, GL_DIFFUSE, light1_diffuse); + glLightfv(GL_LIGHT1, GL_SPECULAR, light1_specular); + glLightfv(GL_LIGHT1, GL_POSITION, light1_position); + glEnable(GL_LIGHT1); + + float light2_ambient[4] = { 0.2, 0.2, 0.2, 1.0 }; + float light2_diffuse[4] = { 0.9, 0.9, 0.9, 1.0 }; + float light2_specular[4] = { 0.7, 0.7, 0.7, 1.0 }; + float light2_position[4] = { 1.0, -1.0, -1.0, 0.0 }; + glLightfv(GL_LIGHT2, GL_AMBIENT, light2_ambient); + glLightfv(GL_LIGHT2, GL_DIFFUSE, light2_diffuse); + glLightfv(GL_LIGHT2, GL_SPECULAR, light2_specular); + glLightfv(GL_LIGHT2, GL_POSITION, light2_position); + //glEnable(GL_LIGHT2); + + float front_emission[4] = { 0.3, 0.2, 0.1, 0.0 }; + float front_ambient[4] = { 0.2, 0.2, 0.2, 0.0 }; + float front_diffuse[4] = { 0.95, 0.95, 0.8, 0.0 }; + float front_specular[4] = { 0.6, 0.6, 0.6, 0.0 }; + glMaterialfv(GL_FRONT, GL_EMISSION, front_emission); + glMaterialfv(GL_FRONT, GL_AMBIENT, front_ambient); + glMaterialfv(GL_FRONT, GL_DIFFUSE, front_diffuse); + glMaterialfv(GL_FRONT, GL_SPECULAR, front_specular); + glMaterialf(GL_FRONT, GL_SHININESS, 16.0); + glColor4fv(front_diffuse); + + glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE); + glEnable(GL_CULL_FACE); + glColorMaterial(GL_FRONT, GL_DIFFUSE); + glEnable(GL_COLOR_MATERIAL); + + glEnable(GL_LIGHTING); + glShadeModel(GL_SMOOTH); +} + + +void FTGLCtrl::SetFontFiles(Vector const &files) +{ + // copy font file names, it's needed later... + fontFiles <<= files; + + // The total number of fonts is styles * faces + totalFonts = files.GetCount() * NumStyles; + + // Instantiate and configure named fonts + for(int i = 0; i < files.GetCount(); i++) + { + fonts.Add(new FTBitmapFont(files[i])); + fonts.Add(new FTPixmapFont(files[i])); + fonts.Add(new FTOutlineFont(files[i])); + fonts.Add(new FTPolygonFont(files[i])); + fonts.Add(new FTExtrudeFont(files[i])); + fonts.Add(new FTTextureFont(files[i])); + + for(int x = 0; x < NumStyles; ++x) + { + int j = i * NumStyles + x; + if(fonts[j].Error()) + { + Exclamation(Format("Failed to open font %s", fontFiles[i])); + exit(1); + } + + if(!fonts[j].FaceSize(24)) + { + Exclamation("Failed to set size"); + exit(1); + } + fonts[j].Depth(20); + fonts[j].CharMap(ft_encoding_unicode); + } + } + + infoFont = new FTPixmapFont(files[0]); + if(infoFont->Error()) + { + Exclamation(Format("Failed to open font %s\n", files[0])); + exit(1); + } + + infoFont->FaceSize(18); +} + + +void FTGLCtrl::RenderFontmetrics() +{ + FTBBox bbox; + float x1, y1, z1, x2, y2, z2; + + // If there is a layout, use it to compute the bbox, otherwise query as + // a string. + if(hasLayout()) + bbox = layouts[currentLayout].BBox(myString); + else + bbox = fonts[currentFont].BBox(myString); + + x1 = bbox.Lower().Xf(); y1 = bbox.Lower().Yf(); z1 = bbox.Lower().Zf(); + x2 = bbox.Upper().Xf(); y2 = bbox.Upper().Yf(); z2 = bbox.Upper().Zf(); + + // Draw the bounding box + glDisable(GL_LIGHTING); + glDisable(GL_TEXTURE_2D); + glEnable(GL_LINE_SMOOTH); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE); // GL_ONE_MINUS_SRC_ALPHA + + glColor3f(0.0, 1.0, 0.0); + // Draw the front face + glBegin(GL_LINE_LOOP); + glVertex3f(x1, y1, z1); + glVertex3f(x1, y2, z1); + glVertex3f(x2, y2, z1); + glVertex3f(x2, y1, z1); + glEnd(); + // Draw the back face + if((GetStyle() == FTGL_EXTRUDE) && (z1 != z2)) + { + glBegin(GL_LINE_LOOP); + glVertex3f(x1, y1, z2); + glVertex3f(x1, y2, z2); + glVertex3f(x2, y2, z2); + glVertex3f(x2, y1, z2); + glEnd(); + // Join the faces + glBegin(GL_LINES); + glVertex3f(x1, y1, z1); + glVertex3f(x1, y1, z2); + + glVertex3f(x1, y2, z1); + glVertex3f(x1, y2, z2); + + glVertex3f(x2, y2, z1); + glVertex3f(x2, y2, z2); + + glVertex3f(x2, y1, z1); + glVertex3f(x2, y1, z2); + glEnd(); + } + + // Render layout-specific metrics + if(!hasLayout()) + { + // There is no layout. Draw the baseline, Ascender and Descender + glBegin(GL_LINES); + glColor3f(0.0, 0.0, 1.0); + glVertex3f(0.0, 0.0, 0.0); + glVertex3f(fonts[currentFont].Advance(myString), 0.0, 0.0); + glVertex3f(0.0, fonts[currentFont].Ascender(), 0.0); + glVertex3f(0.0, fonts[currentFont].Descender(), 0.0); + glEnd(); + } + else if (dynamic_cast (&layouts[currentLayout])) + { + float lineWidth = ((FTSimpleLayout const &)layouts[currentLayout]).GetLineLength(); + + // The layout is a SimpleLayout. Render guides that mark the edges + // of the wrap region. + glColor3f(0.5, 1.0, 1.0); + glBegin(GL_LINES); + glVertex3f(0, 10000, 0); + glVertex3f(0, -10000, 0); + glVertex3f(lineWidth, 10000, 0); + glVertex3f(lineWidth, -10000, 0); + glEnd(); + } + + // Draw the origin + glColor3f(1.0, 0.0, 0.0); + glPointSize(5.0); + glBegin(GL_POINTS); + glVertex3f(0.0, 0.0, 0.0); + glEnd(); +} + +void FTGLCtrl::RenderFontInfo() +{ + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluOrtho2D(0, GetSize().cx, 0, GetSize().cy); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + // draw mode + glColor3f(1.0, 1.0, 1.0); + glRasterPos2f(20.0f , GetSize().cy - (20.0f + infoFont->Ascender())); + + switch(mode) + { + case EDITING: + infoFont->Render("Edit Mode"); + break; + + case INTERACTIVE: + break; + } + + // draw font type + glRasterPos2i(20 , 20); + switch(GetStyle()) + { + case FTGL_BITMAP: + infoFont->Render("Bitmap Font"); + break; + + case FTGL_PIXMAP: + infoFont->Render("Pixmap Font"); + break; + + case FTGL_OUTLINE: + infoFont->Render("Outline Font"); + break; + + case FTGL_POLYGON: + infoFont->Render("Polygon Font"); + break; + + case FTGL_EXTRUDE: + infoFont->Render("Extruded Font"); + break; + + case FTGL_TEXTURE: + infoFont->Render("Texture Font"); + break; + } + + glRasterPos2f(20.0f , 20.0f + infoFont->Ascender() - infoFont->Descender()); + infoFont->Render(fontFiles[GetFace()]); + + // If the current layout is a SimpleLayout, output the alignemnt mode + if(hasLayout() && (dynamic_cast (&layouts[currentLayout]))) + { + glRasterPos2f(20.0f , 20.0f + 2*(infoFont->Ascender() - infoFont->Descender())); + + // Output the alignment mode of the layout + switch (((FTSimpleLayout const &)layouts[currentLayout]).GetAlignment()) + { + case FTGL::ALIGN_LEFT: + infoFont->Render("Align Left"); + break; + + case FTGL::ALIGN_RIGHT: + infoFont->Render("Align Right"); + break; + + case FTGL::ALIGN_CENTER: + infoFont->Render("Align Center"); + break; + + case FTGL::ALIGN_JUSTIFY: + infoFont->Render("Align Justified"); + break; + } + } +} + +void FTGLCtrl::Paint0(void) +{ + switch(GetStyle()) + { + case FTGL_BITMAP: + case FTGL_PIXMAP: + case FTGL_OUTLINE: + break; + + case FTGL_POLYGON: + glDisable(GL_BLEND); + SetUpLighting(); + break; + + case FTGL_EXTRUDE: + glEnable(GL_DEPTH_TEST); + glDisable(GL_BLEND); + SetUpLighting(); + break; + + case FTGL_TEXTURE: + glEnable(GL_TEXTURE_2D); + glDisable(GL_DEPTH_TEST); + SetUpLighting(); + glNormal3f(0.0, 0.0, 1.0); + break; + } + + glColor3f(1.0, 1.0, 1.0); + // If you do want to switch the color of bitmaps rendered with glBitmap, + // you will need to explicitly call glRasterPos (or its ilk) to lock + // in a changed current color. + + // If there is an active layout use it to render the font + if (hasLayout()) + layouts[currentLayout].Render(myString); + else + fonts[currentFont].Render(myString); + RenderFontmetrics(); + RenderFontInfo(); +} + +void FTGLCtrl::SetCamera(void) +{ + switch(GetStyle()) + { + case FTGL_BITMAP: + case FTGL_PIXMAP: + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluOrtho2D(0, GetSize().cx, 0, GetSize().cy); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + break; + + case FTGL_OUTLINE: + case FTGL_POLYGON: + case FTGL_EXTRUDE: + case FTGL_TEXTURE: + glMatrixMode (GL_PROJECTION); + glLoadIdentity (); + gluPerspective(90, (float)GetSize().cx / (float)GetSize().cy, 1, 1000); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + gluLookAt(0.0, 0.0, (float)GetSize().cy / 2.0f, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); + break; + } +} + +void FTGLCtrl::Layout() +{ + glMatrixMode (GL_MODELVIEW); + glViewport (0, 0, GetSize().cx, GetSize().cy); + glLoadIdentity(); + SetCamera(); + trackBall.Reshape(GetSize().cx, GetSize().cy); + GLCtrl::Layout(); +} + +void FTGLCtrl::GLPaint() +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + SetCamera(); + + switch(GetStyle()) + { + case FTGL_BITMAP: + case FTGL_PIXMAP: + glRasterPos2i((long)(GetSize().cx / 2 + OX), (long)(GetSize().cy / 2 + OY)); + glTranslatef(GetSize().cx / 2 + OX, GetSize().cy / 2 + OY, 0.0); + break; + + case FTGL_OUTLINE: + case FTGL_POLYGON: + case FTGL_EXTRUDE: + case FTGL_TEXTURE: + glTranslatef(OX, OY, 0); + trackBall.Matrix(); + break; + } + + glPushMatrix(); + Paint0(); + glPopMatrix(); +} diff --git a/bazaar/FTGL_Demo/FTGLCtrl.h b/bazaar/FTGL_Demo/FTGLCtrl.h new file mode 100644 index 000000000..8ca17e760 --- /dev/null +++ b/bazaar/FTGL_Demo/FTGLCtrl.h @@ -0,0 +1,70 @@ +#ifndef _FTGL_Demo_FTGLCtrl_h_ +#define _FTGL_Demo_FTGLCtrl_h_ + +#include +#include + +#include + +#include "TrackBall.h" + +using namespace Upp; + +class FTGLCtrl : public GLCtrl +{ + private: + + TrackBall trackBall; + + typedef enum { FTGL_BITMAP, FTGL_PIXMAP, FTGL_OUTLINE, FTGL_POLYGON, FTGL_EXTRUDE, FTGL_TEXTURE, NumStyles } Styles; + typedef enum { EDITING = 1, INTERACTIVE } Modes; + + Modes mode; + + Vector fontFiles; + int currentFont; + + // array containing all fonts + Array fonts; + int totalFonts; + One infoFont; + + Array layouts; + int currentLayout; + bool hasLayout(void) { return currentLayout >= 0 && currentLayout < layouts.GetCount(); } + + // displayed string + String myString; + + void SetUpLighting(); + void SetUpFonts(int numFontFiles); + void RenderFontmetrics(); + void RenderFontInfo(); + void SetCamera(); + void Paint0(void); + + int GetStyle() { return currentFont % NumStyles; } + int GetFace() { return currentFont / NumStyles; } + + float OX; + float OY; + + float initialLineLength; + + protected: + virtual void GLPaint(); + + virtual Image MouseEvent(int event, Point p, int zdelta, dword keyflags) { return trackBall.MouseEvent(event, p, zdelta, keyflags); } + virtual bool Key(dword key, int count); + + virtual void Layout(); + + public: + typedef FTGLCtrl CLASSNAME; + + void SetFontFiles(Vector const &files); + + FTGLCtrl(); +}; + +#endif diff --git a/bazaar/FTGL_Demo/FTGLDemo.cpp b/bazaar/FTGL_Demo/FTGLDemo.cpp new file mode 100644 index 000000000..7b744959a --- /dev/null +++ b/bazaar/FTGL_Demo/FTGLDemo.cpp @@ -0,0 +1,14 @@ +#include "FTGLDemo.h" + +FTGLDemo::FTGLDemo() +{ + Add(ftglCtrl.SizePos()); +} + + +GUI_APP_MAIN +{ + FTGLDemo ftglDemo; + ftglDemo.Sizeable().Zoomable().MinimizeBox(); + ftglDemo.Run(); +} diff --git a/bazaar/FTGL_Demo/FTGLDemo.h b/bazaar/FTGL_Demo/FTGLDemo.h new file mode 100644 index 000000000..294227b33 --- /dev/null +++ b/bazaar/FTGL_Demo/FTGLDemo.h @@ -0,0 +1,18 @@ +#ifndef _FTGL_Demo_FTGLDemo_h_ +#define _FTGL_Demo_FTGLDemo_h_ + +#include "FTGLCtrl.h" + +class FTGLDemo : public TopWindow +{ + typedef FTGLDemo CLASSNAME; + +private: + FTGLCtrl ftglCtrl; + +public: + FTGLDemo(); +}; + + +#endif diff --git a/bazaar/FTGL_Demo/FTGLMFontDemo.cpp b/bazaar/FTGL_Demo/FTGLMFontDemo.cpp new file mode 100644 index 000000000..33dea7469 --- /dev/null +++ b/bazaar/FTGL_Demo/FTGLMFontDemo.cpp @@ -0,0 +1,693 @@ +/* + * FTGLDemo - advanced demo for FTGL, the OpenGL font library + * + * Copyright (c) 2001-2004 Henry Maddocks + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "config.h" + +#include +#include +#include + +#if defined HAVE_GL_GLUT_H +# include +#elif defined HAVE_GLUT_GLUT_H +# include +#else +# error GLUT headers not present +#endif + +#include + +#include "tb.h" + +// YOU'LL PROBABLY WANT TO CHANGE THESE +#if defined FONT_FILE + char const *defaultFonts[] = { FONT_FILE }; + const int NumDefaultFonts = 1; +#elif defined __APPLE_CC__ + char const *defaultFonts[] = { "/System/Library/Fonts/Helvetica.dfont", + "/System/Library/Fonts/Geneva.dfont" }; + const int NumDefaultFonts = 2; +#elif defined WIN32 + char const *defaultFonts[] = { "C:\\WINNT\\Fonts\\arial.ttf" }; + const int NumDefaultFonts = 1; +#else + // Put your font files here if configure did not find any. + char const *defaultFonts[] = { }; + const int NumDefaultFonts = 0; +#endif + +/* Set this to 1 to build a Mac os app (ignore the command line args). */ +#ifndef IGNORE_ARGV +# define IGNORE_ARGV 0 +#endif /* IGNORE_ARGV */ + +#define EDITING 1 +#define INTERACTIVE 2 + +#define FTGL_BITMAP 0 +#define FTGL_PIXMAP 1 +#define FTGL_OUTLINE 2 +#define FTGL_POLYGON 3 +#define FTGL_EXTRUDE 4 +#define FTGL_TEXTURE 5 +const int NumStyles = 6; + +char const * const *fontfiles; +int current_font = FTGL_EXTRUDE; + +GLint w_win = 640, h_win = 480; +int mode = INTERACTIVE; +int carat = 0; + +FTSimpleLayout simpleLayout; +FTLayout *layouts[] = { &simpleLayout, NULL }; +int currentLayout = 0; +const int NumLayouts = 2; + +const float InitialLineLength = 300.0f; + +const float OX = -100; +const float OY = 200; + +//wchar_t myString[16] = { 0x6FB3, 0x9580}; +char myString[4096]; + +int totalFonts; +static FTFont** fonts; +static FTPixmapFont* infoFont; + +void SetCamera(void); + +inline int GetStyle() +{ + return current_font % NumStyles; +} + +inline int GetFace() +{ + return current_font / NumStyles; +} + +void setUpLighting() +{ + // Set up lighting. + float light1_ambient[4] = { 1.0, 1.0, 1.0, 1.0 }; + float light1_diffuse[4] = { 1.0, 0.9, 0.9, 1.0 }; + float light1_specular[4] = { 1.0, 0.7, 0.7, 1.0 }; + float light1_position[4] = { -1.0, 1.0, 1.0, 0.0 }; + glLightfv(GL_LIGHT1, GL_AMBIENT, light1_ambient); + glLightfv(GL_LIGHT1, GL_DIFFUSE, light1_diffuse); + glLightfv(GL_LIGHT1, GL_SPECULAR, light1_specular); + glLightfv(GL_LIGHT1, GL_POSITION, light1_position); + glEnable(GL_LIGHT1); + + float light2_ambient[4] = { 0.2, 0.2, 0.2, 1.0 }; + float light2_diffuse[4] = { 0.9, 0.9, 0.9, 1.0 }; + float light2_specular[4] = { 0.7, 0.7, 0.7, 1.0 }; + float light2_position[4] = { 1.0, -1.0, -1.0, 0.0 }; + glLightfv(GL_LIGHT2, GL_AMBIENT, light2_ambient); + glLightfv(GL_LIGHT2, GL_DIFFUSE, light2_diffuse); + glLightfv(GL_LIGHT2, GL_SPECULAR, light2_specular); + glLightfv(GL_LIGHT2, GL_POSITION, light2_position); + //glEnable(GL_LIGHT2); + + float front_emission[4] = { 0.3, 0.2, 0.1, 0.0 }; + float front_ambient[4] = { 0.2, 0.2, 0.2, 0.0 }; + float front_diffuse[4] = { 0.95, 0.95, 0.8, 0.0 }; + float front_specular[4] = { 0.6, 0.6, 0.6, 0.0 }; + glMaterialfv(GL_FRONT, GL_EMISSION, front_emission); + glMaterialfv(GL_FRONT, GL_AMBIENT, front_ambient); + glMaterialfv(GL_FRONT, GL_DIFFUSE, front_diffuse); + glMaterialfv(GL_FRONT, GL_SPECULAR, front_specular); + glMaterialf(GL_FRONT, GL_SHININESS, 16.0); + glColor4fv(front_diffuse); + + glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE); + glEnable(GL_CULL_FACE); + glColorMaterial(GL_FRONT, GL_DIFFUSE); + glEnable(GL_COLOR_MATERIAL); + + glEnable(GL_LIGHTING); + glShadeModel(GL_SMOOTH); +} + + +void setUpFonts(int numFontFiles) +{ + // The total number of fonts is styles * faces + totalFonts = numFontFiles*NumStyles; + + // Allocate an array to hold all fonts + fonts = new FTFont *[totalFonts]; + + // Instantiate and configure named fonts + for(int i = 0; i < numFontFiles; i++) + { + fonts[i*NumStyles + FTGL_BITMAP] = new FTBitmapFont(fontfiles[i]); + fonts[i*NumStyles + FTGL_PIXMAP] = new FTPixmapFont(fontfiles[i]); + fonts[i*NumStyles + FTGL_OUTLINE] = new FTOutlineFont(fontfiles[i]); + fonts[i*NumStyles + FTGL_POLYGON] = new FTPolygonFont(fontfiles[i]); + fonts[i*NumStyles + FTGL_EXTRUDE] = new FTExtrudeFont(fontfiles[i]); + fonts[i*NumStyles + FTGL_TEXTURE] = new FTTextureFont(fontfiles[i]); + + for(int x = 0; x < NumStyles; ++x) + { + int j = i * NumStyles + x; + + if(fonts[j]->Error()) + { + fprintf(stderr, "Failed to open font %s\n", fontfiles[i]); + exit(1); + } + + if(!fonts[j]->FaceSize(24)) + { + fprintf(stderr, "Failed to set size\n"); + exit(1); + } + + fonts[j]->Depth(20); + fonts[j]->CharMap(ft_encoding_unicode); + } + } + + infoFont = new FTPixmapFont(fontfiles[0]); + + if(infoFont->Error()) + { + fprintf(stderr, "Failed to open font %s\n", fontfiles[0]); + exit(1); + } + + infoFont->FaceSize(18); + + strcpy(myString, "OpenGL is a powerful software interface for graphics " + "hardware that allows graphics programmers to produce high-quality " + "color images of 3D objects. abcdefghijklmnopqrstuvwxyzABCDEFGHIJKL" + "MNOPQRSTUVWXYZ0123456789"); +} + + +void renderFontmetrics() +{ + FTBBox bbox; + float x1, y1, z1, x2, y2, z2; + + // If there is a layout, use it to compute the bbox, otherwise query as + // a string. + if(layouts[currentLayout]) + bbox = layouts[currentLayout]->BBox(myString); + else + bbox = fonts[current_font]->BBox(myString); + + x1 = bbox.Lower().Xf(); y1 = bbox.Lower().Yf(); z1 = bbox.Lower().Zf(); + x2 = bbox.Upper().Xf(); y2 = bbox.Upper().Yf(); z2 = bbox.Upper().Zf(); + + // Draw the bounding box + glDisable(GL_LIGHTING); + glDisable(GL_TEXTURE_2D); + glEnable(GL_LINE_SMOOTH); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE); // GL_ONE_MINUS_SRC_ALPHA + + glColor3f(0.0, 1.0, 0.0); + // Draw the front face + glBegin(GL_LINE_LOOP); + glVertex3f(x1, y1, z1); + glVertex3f(x1, y2, z1); + glVertex3f(x2, y2, z1); + glVertex3f(x2, y1, z1); + glEnd(); + // Draw the back face + if((GetStyle() == FTGL_EXTRUDE) && (z1 != z2)) + { + glBegin(GL_LINE_LOOP); + glVertex3f(x1, y1, z2); + glVertex3f(x1, y2, z2); + glVertex3f(x2, y2, z2); + glVertex3f(x2, y1, z2); + glEnd(); + // Join the faces + glBegin(GL_LINES); + glVertex3f(x1, y1, z1); + glVertex3f(x1, y1, z2); + + glVertex3f(x1, y2, z1); + glVertex3f(x1, y2, z2); + + glVertex3f(x2, y2, z1); + glVertex3f(x2, y2, z2); + + glVertex3f(x2, y1, z1); + glVertex3f(x2, y1, z2); + glEnd(); + } + + // Render layout-specific metrics + if(!layouts[currentLayout]) + { + // There is no layout. Draw the baseline, Ascender and Descender + glBegin(GL_LINES); + glColor3f(0.0, 0.0, 1.0); + glVertex3f(0.0, 0.0, 0.0); + glVertex3f(fonts[current_font]->Advance(myString), 0.0, 0.0); + glVertex3f(0.0, fonts[current_font]->Ascender(), 0.0); + glVertex3f(0.0, fonts[current_font]->Descender(), 0.0); + glEnd(); + } + else if (layouts[currentLayout] + && (dynamic_cast (layouts[currentLayout]))) + { + float lineWidth = ((FTSimpleLayout *)layouts[currentLayout])->GetLineLength(); + + // The layout is a SimpleLayout. Render guides that mark the edges + // of the wrap region. + glColor3f(0.5, 1.0, 1.0); + glBegin(GL_LINES); + glVertex3f(0, 10000, 0); + glVertex3f(0, -10000, 0); + glVertex3f(lineWidth, 10000, 0); + glVertex3f(lineWidth, -10000, 0); + glEnd(); + } + + // Draw the origin + glColor3f(1.0, 0.0, 0.0); + glPointSize(5.0); + glBegin(GL_POINTS); + glVertex3f(0.0, 0.0, 0.0); + glEnd(); +} + + +void renderFontInfo() +{ + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluOrtho2D(0, w_win, 0, h_win); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + // draw mode + glColor3f(1.0, 1.0, 1.0); + glRasterPos2f(20.0f , h_win - (20.0f + infoFont->Ascender())); + + switch(mode) + { + case EDITING: + infoFont->Render("Edit Mode"); + break; + case INTERACTIVE: + break; + } + + // draw font type + glRasterPos2i(20 , 20); + switch(GetStyle()) + { + case FTGL_BITMAP: + infoFont->Render("Bitmap Font"); + break; + case FTGL_PIXMAP: + infoFont->Render("Pixmap Font"); + break; + case FTGL_OUTLINE: + infoFont->Render("Outline Font"); + break; + case FTGL_POLYGON: + infoFont->Render("Polygon Font"); + break; + case FTGL_EXTRUDE: + infoFont->Render("Extruded Font"); + break; + case FTGL_TEXTURE: + infoFont->Render("Texture Font"); + break; + } + + glRasterPos2f(20.0f , 20.0f + infoFont->Ascender() - infoFont->Descender()); + infoFont->Render(fontfiles[GetFace()]); + + // If the current layout is a SimpleLayout, output the alignemnt mode + if(layouts[currentLayout] + && (dynamic_cast (layouts[currentLayout]))) + { + glRasterPos2f(20.0f , 20.0f + 2*(infoFont->Ascender() - infoFont->Descender())); + // Output the alignment mode of the layout + switch (((FTSimpleLayout *)layouts[currentLayout])->GetAlignment()) + { + case FTGL::ALIGN_LEFT: + infoFont->Render("Align Left"); + break; + case FTGL::ALIGN_RIGHT: + infoFont->Render("Align Right"); + break; + case FTGL::ALIGN_CENTER: + infoFont->Render("Align Center"); + break; + case FTGL::ALIGN_JUSTIFY: + infoFont->Render("Align Justified"); + break; + } + } +} + + +void do_display (void) +{ + switch(GetStyle()) + { + case FTGL_BITMAP: + case FTGL_PIXMAP: + case FTGL_OUTLINE: + break; + case FTGL_POLYGON: + glDisable(GL_BLEND); + setUpLighting(); + break; + case FTGL_EXTRUDE: + glEnable(GL_DEPTH_TEST); + glDisable(GL_BLEND); + setUpLighting(); + break; + case FTGL_TEXTURE: + glEnable(GL_TEXTURE_2D); + glDisable(GL_DEPTH_TEST); + setUpLighting(); + glNormal3f(0.0, 0.0, 1.0); + break; + + } + + glColor3f(1.0, 1.0, 1.0); + // If you do want to switch the color of bitmaps rendered with glBitmap, + // you will need to explicitly call glRasterPos (or its ilk) to lock + // in a changed current color. + + // If there is an active layout use it to render the font + if (layouts[currentLayout]) + { + layouts[currentLayout]->Render(myString); + } + else + { + fonts[current_font]->Render(myString); + } + + renderFontmetrics(); + renderFontInfo(); +} + + +void display(void) +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + SetCamera(); + + switch(GetStyle()) + { + case FTGL_BITMAP: + case FTGL_PIXMAP: + glRasterPos2i((long)(w_win / 2 + OX), (long)(h_win / 2 + OY)); + glTranslatef(w_win / 2 + OX, h_win / 2 + OY, 0.0); + break; + case FTGL_OUTLINE: + case FTGL_POLYGON: + case FTGL_EXTRUDE: + case FTGL_TEXTURE: + glTranslatef(OX, OY, 0); + tbMatrix(); + break; + } + + glPushMatrix(); + + do_display(); + + glPopMatrix(); + + glutSwapBuffers(); +} + + +void myinit(int numFontFiles) +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glClearColor(0.13, 0.17, 0.32, 0.0); + glColor3f(1.0, 1.0, 1.0); + + glEnable(GL_CULL_FACE); + glFrontFace(GL_CCW); + + glEnable(GL_DEPTH_TEST); + + glEnable(GL_POLYGON_OFFSET_LINE); + glPolygonOffset(1.0, 1.0); // ???? + + SetCamera(); + + tbInit(GLUT_LEFT_BUTTON); + tbAnimate(GL_FALSE); + + setUpFonts(numFontFiles); + + // Configure the SimpleLayout + simpleLayout.SetLineLength(InitialLineLength); + simpleLayout.SetFont(fonts[current_font]); +} + + +void parsekey(unsigned char key, int x, int y) +{ + switch (key) + { + case 27: + exit(0); + break; + case 13: + if(mode == EDITING) + { + mode = INTERACTIVE; + } + else + { + mode = EDITING; + carat = 0; + } + break; + case '\t': + // If current layout is a SimpleLayout, change its alignment properties + if(layouts[currentLayout] + && (dynamic_cast (layouts[currentLayout]))) + { + FTSimpleLayout *l = (FTSimpleLayout *)layouts[currentLayout]; + // Decrement the layout + switch (l->GetAlignment()) + { + case FTGL::ALIGN_LEFT: + l->SetAlignment(FTGL::ALIGN_RIGHT); + break; + case FTGL::ALIGN_RIGHT: + l->SetAlignment(FTGL::ALIGN_CENTER); + break; + case FTGL::ALIGN_CENTER: + l->SetAlignment(FTGL::ALIGN_JUSTIFY); + break; + case FTGL::ALIGN_JUSTIFY: + l->SetAlignment(FTGL::ALIGN_LEFT); + break; + } + } + break; + default: + if(mode == INTERACTIVE) + { + myString[0] = key; + myString[1] = 0; + } + else + { + myString[carat] = key; + myString[carat + 1] = 0; + carat = carat > 2000 ? 2000 : carat + 1; + } + break; + } + + glutPostRedisplay(); +} + + +void parseSpecialKey(int key, int x, int y) +{ + FTSimpleLayout *l = NULL; + + // If the currentLayout is a SimpleLayout store a pointer in l + if(layouts[currentLayout] + && (dynamic_cast (layouts[currentLayout]))) + { + l = (FTSimpleLayout *)layouts[currentLayout]; + } + + switch (key) + { + case GLUT_KEY_UP: + current_font = (GetFace()*NumStyles + (current_font + 1)%NumStyles)%totalFonts; + break; + case GLUT_KEY_DOWN: + current_font = (GetFace()*NumStyles + (current_font + NumStyles - 1)%NumStyles)%totalFonts; + break; + case GLUT_KEY_LEFT: + fonts[current_font]->FaceSize(fonts[current_font]->FaceSize() - 1); + break; + case GLUT_KEY_RIGHT: + fonts[current_font]->FaceSize(fonts[current_font]->FaceSize() + 1); + break; + case GLUT_KEY_PAGE_UP: + current_font = (current_font + NumStyles)%totalFonts; + break; + case GLUT_KEY_PAGE_DOWN: + current_font = (current_font + totalFonts - NumStyles)%totalFonts; + break; + case GLUT_KEY_HOME: + currentLayout = (currentLayout + 1)%NumLayouts; + break; + case GLUT_KEY_END: + currentLayout = (currentLayout + NumLayouts - 1)%NumLayouts; + break; + case GLUT_KEY_F1: + case GLUT_KEY_F10: + // If the current layout is simple decrement its line length + if (l) l->SetLineLength(l->GetLineLength() - 10.0f); + break; + case GLUT_KEY_F2: + case GLUT_KEY_F11: + // If the current layout is simple increment its line length + if (l) l->SetLineLength(l->GetLineLength() + 10.0f); + break; + } + + // If the current layout is a SimpleLayout, update its font. + if(l) + { + l->SetFont(fonts[current_font]); + } + + glutPostRedisplay(); +} + + +void motion(int x, int y) +{ + tbMotion(x, y); +} + +void mouse(int button, int state, int x, int y) +{ + tbMouse(button, state, x, y); +} + +void myReshape(int w, int h) +{ + glMatrixMode (GL_MODELVIEW); + glViewport (0, 0, w, h); + glLoadIdentity(); + + w_win = w; + h_win = h; + SetCamera(); + + tbReshape(w_win, h_win); +} + +void SetCamera(void) +{ + switch(GetStyle()) + { + case FTGL_BITMAP: + case FTGL_PIXMAP: + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluOrtho2D(0, w_win, 0, h_win); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + break; + case FTGL_OUTLINE: + case FTGL_POLYGON: + case FTGL_EXTRUDE: + case FTGL_TEXTURE: + glMatrixMode (GL_PROJECTION); + glLoadIdentity (); + gluPerspective(90, (float)w_win / (float)h_win, 1, 1000); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + gluLookAt(0.0, 0.0, (float)h_win / 2.0f, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); + break; + } +} + + +int main(int argc, char *argv[]) +{ + int numFontFiles; + + if((argc >= 2) && !IGNORE_ARGV) + { + fontfiles = (char const * const *)argv + 1; + numFontFiles = argc - 1; + } + else + { + fontfiles = defaultFonts; + numFontFiles = NumDefaultFonts; + } + + if(!fontfiles[0]) + { + fprintf(stderr, "At least one font file must be specified on the command line\n"); + exit(1); + } + + glutInit(&argc, argv); + glutInitDisplayMode(GLUT_DEPTH | GLUT_RGB | GLUT_DOUBLE | GLUT_MULTISAMPLE); + glutInitWindowPosition(50, 50); + glutInitWindowSize(w_win, h_win); + glutCreateWindow("FTGL TEST"); + glutDisplayFunc(display); + glutKeyboardFunc(parsekey); + glutSpecialFunc(parseSpecialKey); + glutMouseFunc(mouse); + glutMotionFunc(motion); + glutReshapeFunc(myReshape); + glutIdleFunc(display); + + myinit(numFontFiles); + + glutMainLoop(); + + return 0; +} + diff --git a/bazaar/FTGL_Demo/FTGL_Demo.upp b/bazaar/FTGL_Demo/FTGL_Demo.upp new file mode 100644 index 000000000..4e703ad0a --- /dev/null +++ b/bazaar/FTGL_Demo/FTGL_Demo.upp @@ -0,0 +1,18 @@ +uses + FTGL, + CtrlLib, + GLCtrl; + +file + trackball.c, + trackball.h, + TrackBall.h, + TrackBall.cpp, + FTGLCtrl.h, + FTGLCtrl.cpp, + FTGLDemo.h, + FTGLDemo.cpp; + +mainconfig + "" = "GUI"; + diff --git a/bazaar/FTGL_Demo/TrackBall.cpp b/bazaar/FTGL_Demo/TrackBall.cpp new file mode 100644 index 000000000..29910cf71 --- /dev/null +++ b/bazaar/FTGL_Demo/TrackBall.cpp @@ -0,0 +1,98 @@ +#include "TrackBall.h" + +#include "trackball.h" +#include + +void TrackBall::_Animate(void) +{ + add_quats(lastquat, curquat, curquat); + owner->Refresh(); + owner->Sync(); + if(enableAnimCb) + owner->SetTimeCallback(10, THISBACK(_Animate)); +} + +void TrackBall::_StartMotion(int x, int y, Time time) +{ + enableAnimCb = false; + tracking = true; + lastTime = time; + beginx = x; + beginy = y; +} + +void TrackBall::_StopMotion(Time time) +{ + tracking = false; + + if (time == lastTime && animate) + { + enableAnimCb = true; + _Animate(); + } + else + if (animate) + enableAnimCb = false; +} + +void TrackBall::Animate(bool a) +{ + animate = a; +} + +void TrackBall::Matrix(void) +{ + GLfloat m[4][4]; + + build_rotmatrix(m, curquat); + glMultMatrixf(&m[0][0]); +} + +void TrackBall::Reshape(int w, int h) +{ + width = w; + height = h; +} + +// mouse event handler +Image TrackBall::MouseEvent(int event, Point p, int zdelta, dword keyflags) +{ + // mouse up/down starts and stop motion + if ((event & Ctrl::BUTTON) == button && (event & Ctrl::ACTION) == Ctrl::DOWN) + _StartMotion(p.x, p.y, GetSysTime()); + else + if ((event & Ctrl::BUTTON) == button && (event & Ctrl::ACTION) == Ctrl::UP) + _StopMotion(GetSysTime()); + + // mouse move do the animation, if we're tracking + else if((event & Ctrl::ACTION) == Ctrl::MOUSEMOVE) + { + if (tracking) + { + trackball( + lastquat, + (2.0 * beginx - width) / width, + (height - 2.0 * beginy) / height, + (2.0 * p.x - width) / width, + (height - 2.0 * p.y) / height + ); + beginx = p.x; + beginy = p.y; + animate = true; + lastTime = GetSysTime(); + _Animate(); + } + } + + return Image(); +} + +TrackBall::TrackBall(Ctrl *ow) +{ + owner = ow; + button = Ctrl::LEFT; + tracking = false; + animate = false; + trackball(curquat, 0.0, 0.0, 0.0, 0.0); + enableAnimCb = false; +} diff --git a/bazaar/FTGL_Demo/TrackBall.h b/bazaar/FTGL_Demo/TrackBall.h new file mode 100644 index 000000000..46d5c63f8 --- /dev/null +++ b/bazaar/FTGL_Demo/TrackBall.h @@ -0,0 +1,50 @@ +#ifndef _FTGL_Demo_TrackBall_h_ +#define _FTGL_Demo_TrackBall_h_ + +#include + +using namespace Upp; + +class TrackBall +{ + private: + + Ctrl *owner; + + Time lastTime; + + float curquat[4]; + float lastquat[4]; + int beginx, beginy; + + int width; + int height; + + int button; + bool tracking; + bool animate; + + void _Animate(void); + void _StartMotion(int x, int y, Time time); + void _StopMotion(Time time); + + bool enableAnimCb; + + protected: + + public: + + typedef TrackBall CLASSNAME; + + void Matrix(void); + void Reshape(int width, int height); + void Animate(bool animate); + + void SetButton(int but = Ctrl::LEFT) { button = but; } + + virtual Image MouseEvent(int event, Point p, int zdelta, dword keyflags); + + TrackBall(Ctrl *owner); +}; + +#endif diff --git a/bazaar/FTGL_Demo/init b/bazaar/FTGL_Demo/init new file mode 100644 index 000000000..2ee21c04c --- /dev/null +++ b/bazaar/FTGL_Demo/init @@ -0,0 +1,6 @@ +#ifndef _FTGL_Demo_icpp_init_stub +#define _FTGL_Demo_icpp_init_stub +#include "FTGL/init" +#include "CtrlLib/init" +#include "GLCtrl/init" +#endif diff --git a/bazaar/FTGL_Demo/tb.c b/bazaar/FTGL_Demo/tb.c new file mode 100644 index 000000000..310f23de0 --- /dev/null +++ b/bazaar/FTGL_Demo/tb.c @@ -0,0 +1,131 @@ +/* + * Simple trackball-like motion adapted (ripped off) from projtex.c + * (written by David Yu and David Blythe). See the SIGGRAPH '96 + * Advanced OpenGL course notes. + */ + +#include "config.h" + +#include +#include + +#if defined HAVE_GL_GLUT_H +# include +#elif defined HAVE_GLUT_GLUT_H +# include +#else +# error GLUT headers not present +#endif + +#include "tb.h" +#include "trackball.h" + +/* globals */ +static GLuint tb_lasttime; + +float curquat[4]; +float lastquat[4]; +int beginx, beginy; + +static GLuint tb_width; +static GLuint tb_height; + +static GLint tb_button = -1; +static GLboolean tb_tracking = GL_FALSE; +static GLboolean tb_animate = GL_TRUE; + +static void +_tbAnimate(void) +{ + add_quats(lastquat, curquat, curquat); + glutPostRedisplay(); +} + +static void +_tbStartMotion(int x, int y, int time) +{ + assert(tb_button != -1); + + glutIdleFunc(0); + tb_tracking = GL_TRUE; + tb_lasttime = time; + beginx = x; + beginy = y; +} + +static void +_tbStopMotion(unsigned time) +{ + assert(tb_button != -1); + + tb_tracking = GL_FALSE; + + if (time == tb_lasttime && tb_animate) { + glutIdleFunc(_tbAnimate); + } else { + if (tb_animate) { + glutIdleFunc(0); + } + } +} + +void +tbAnimate(GLboolean animate) +{ + tb_animate = animate; +} + +void +tbInit(GLuint button) +{ + tb_button = button; + trackball(curquat, 0.0, 0.0, 0.0, 0.0); +} + +void +tbMatrix(void) +{ + GLfloat m[4][4]; + + assert(tb_button != -1); + build_rotmatrix(m, curquat); + glMultMatrixf(&m[0][0]); +} + +void +tbReshape(int width, int height) +{ + assert(tb_button != -1); + + tb_width = width; + tb_height = height; +} + +void +tbMouse(int button, int state, int x, int y) +{ + assert(tb_button != -1); + + if (state == GLUT_DOWN && button == tb_button) + _tbStartMotion(x, y, glutGet(GLUT_ELAPSED_TIME)); + else if (state == GLUT_UP && button == tb_button) + _tbStopMotion(glutGet(GLUT_ELAPSED_TIME)); +} + +void +tbMotion(int x, int y) +{ + if (tb_tracking) { + trackball(lastquat, + (2.0 * beginx - tb_width) / tb_width, + (tb_height - 2.0 * beginy) / tb_height, + (2.0 * x - tb_width) / tb_width, + (tb_height - 2.0 * y) / tb_height + ); + beginx = x; + beginy = y; + tb_animate = 1; + tb_lasttime = glutGet(GLUT_ELAPSED_TIME); + _tbAnimate(); + } +} diff --git a/bazaar/FTGL_Demo/tb.h b/bazaar/FTGL_Demo/tb.h new file mode 100644 index 000000000..3ac0ea81c --- /dev/null +++ b/bazaar/FTGL_Demo/tb.h @@ -0,0 +1,103 @@ +/* + * Simple trackball-like motion adapted (ripped off) from projtex.c + * (written by David Yu and David Blythe). See the SIGGRAPH '96 + * Advanced OpenGL course notes. + * + * + * Usage: + * + * o call tbInit() in before any other tb call + * o call tbReshape() from the reshape callback + * o call tbMatrix() to get the trackball matrix rotation + * o call tbStartMotion() to begin trackball movememt + * o call tbStopMotion() to stop trackball movememt + * o call tbMotion() from the motion callback + * o call tbAnimate(GL_TRUE) if you want the trackball to continue + * spinning after the mouse button has been released + * o call tbAnimate(GL_FALSE) if you want the trackball to stop + * spinning after the mouse button has been released + * + * Typical setup: + * + * + void + init(void) + { + tbInit(GLUT_MIDDLE_BUTTON); + tbAnimate(GL_TRUE); + . . . + } + + void + reshape(int width, int height) + { + tbReshape(width, height); + . . . + } + + void + display(void) + { + glPushMatrix(); + + tbMatrix(); + . . . draw the scene . . . + + glPopMatrix(); + } + + void + mouse(int button, int state, int x, int y) + { + tbMouse(button, state, x, y); + . . . + } + + void + motion(int x, int y) + { + tbMotion(x, y); + . . . + } + + int + main(int argc, char** argv) + { + . . . + init(); + glutReshapeFunc(reshape); + glutDisplayFunc(display); + glutMouseFunc(mouse); + glutMotionFunc(motion); + . . . + } + * + * */ + + +/* functions */ +#ifdef __cplusplus +extern "C" { +#endif + +void +tbInit(GLuint button); + +void +tbMatrix(void); + +void +tbReshape(int width, int height); + +void +tbMouse(int button, int state, int x, int y); + +void +tbMotion(int x, int y); + +void +tbAnimate(GLboolean animate); + +#ifdef __cplusplus +} +#endif diff --git a/bazaar/FTGL_Demo/trackball.c b/bazaar/FTGL_Demo/trackball.c new file mode 100644 index 000000000..6ac4c37e9 --- /dev/null +++ b/bazaar/FTGL_Demo/trackball.c @@ -0,0 +1,326 @@ +/* + * (c) Copyright 1993, 1994, Silicon Graphics, Inc. + * ALL RIGHTS RESERVED + * Permission to use, copy, modify, and distribute this software for + * any purpose and without fee is hereby granted, provided that the above + * copyright notice appear in all copies and that both the copyright notice + * and this permission notice appear in supporting documentation, and that + * the name of Silicon Graphics, Inc. not be used in advertising + * or publicity pertaining to distribution of the software without specific, + * written prior permission. + * + * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS" + * AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR + * FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON + * GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT, + * SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY + * KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION, + * LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF + * THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC. HAS BEEN + * ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE + * POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE. + * + * US Government Users Restricted Rights + * Use, duplication, or disclosure by the Government is subject to + * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph + * (c)(1)(ii) of the Rights in Technical Data and Computer Software + * clause at DFARS 252.227-7013 and/or in similar or successor + * clauses in the FAR or the DOD or NASA FAR Supplement. + * Unpublished-- rights reserved under the copyright laws of the + * United States. Contractor/manufacturer is Silicon Graphics, + * Inc., 2011 N. Shoreline Blvd., Mountain View, CA 94039-7311. + * + * OpenGL(TM) is a trademark of Silicon Graphics, Inc. + */ + +/* + * Trackball code: + * + * Implementation of a virtual trackball. + * Implemented by Gavin Bell, lots of ideas from Thant Tessman and + * the August '88 issue of Siggraph's "Computer Graphics," pp. 121-129. + * + * Vector manip code: + * + * Original code from: + * David M. Ciemiewicz, Mark Grossman, Henry Moreton, and Paul Haeberli + * + * Much mucking with by: + * Gavin Bell + */ + +#include +#include "trackball.h" + +/* + * 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. + */ +#define TRACKBALLSIZE (0.4f) + +/* + * Local function prototypes (not defined in trackball.h) + */ +static float tb_project_to_sphere(float, float, float); +static void normalize_quat(float [4]); + +static void +vzero(float *v) +{ + v[0] = 0.0; + v[1] = 0.0; + v[2] = 0.0; +} + +static void +vset(float *v, float x, float y, float z) +{ + v[0] = x; + v[1] = y; + v[2] = z; +} + +static void +vsub(const float *src1, const float *src2, float *dst) +{ + dst[0] = src1[0] - src2[0]; + dst[1] = src1[1] - src2[1]; + dst[2] = src1[2] - src2[2]; +} + +static void +vcopy(const float *v1, float *v2) +{ + register int i; + for (i = 0 ; i < 3 ; i++) + v2[i] = v1[i]; +} + +static void +vcross(const float *v1, const float *v2, float *cross) +{ + float temp[3]; + + temp[0] = (v1[1] * v2[2]) - (v1[2] * v2[1]); + temp[1] = (v1[2] * v2[0]) - (v1[0] * v2[2]); + temp[2] = (v1[0] * v2[1]) - (v1[1] * v2[0]); + vcopy(temp, cross); +} + +static float +vlength(const float *v) +{ + return sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]); +} + +static void +vscale(float *v, float div) +{ + v[0] *= div; + v[1] *= div; + v[2] *= div; +} + +static void +vnormal(float *v) +{ + vscale(v,1.0f/vlength(v)); +} + +static float +vdot(const float *v1, const float *v2) +{ + return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2]; +} + +static void +vadd(const float *src1, const float *src2, float *dst) +{ + dst[0] = src1[0] + src2[0]; + dst[1] = src1[1] + src2[1]; + dst[2] = src1[2] + src2[2]; +} + +/* + * Ok, simulate a track-ball. Project the points onto the virtual + * trackball, then figure out the axis of rotation, which is the cross + * product of P1 P2 and O P1 (O is the center of the ball, 0,0,0) + * Note: This is a deformed trackball-- is a trackball in the center, + * but is deformed into a hyperbolic sheet of rotation away from the + * center. This particular function was chosen after trying out + * several variations. + * + * It is assumed that the arguments to this routine are in the range + * (-1.0 ... 1.0) + */ +void +trackball(float q[4], float p1x, float p1y, float p2x, float p2y) +{ + float a[3]; /* Axis of rotation */ + float phi; /* how much to rotate about axis */ + float p1[3], p2[3], d[3]; + float t; + + if (p1x == p2x && p1y == p2y) { + /* Zero rotation */ + vzero(q); + q[3] = 1.0; + return; + } + + /* + * First, figure out z-coordinates for projection of P1 and P2 to + * deformed sphere + */ + vset(p1,p1x,p1y,tb_project_to_sphere(TRACKBALLSIZE,p1x,p1y)); + vset(p2,p2x,p2y,tb_project_to_sphere(TRACKBALLSIZE,p2x,p2y)); + + /* + * Now, we want the cross product of P1 and P2 + */ + vcross(p2,p1,a); + + /* + * Figure out how much to rotate around that axis. + */ + vsub(p1,p2,d); + t = vlength(d) / (2.0f*TRACKBALLSIZE); + + /* + * Avoid problems with out-of-control values... + */ + if (t > 1.0f) t = 1.0f; + if (t < -1.0f) t = -1.0f; + phi = 2.0f * asin(t); + + axis_to_quat(a,phi,q); +} + +/* + * Given an axis and angle, compute quaternion. + */ +void +axis_to_quat(float a[3], float phi, float q[4]) +{ + vnormal(a); + vcopy(a,q); + vscale(q,sin(phi/2.0f)); + q[3] = cos(phi/2.0f); +} + +/* + * Project an x,y pair onto a sphere of radius r OR a hyperbolic sheet + * if we are away from the center of the sphere. + */ +static float +tb_project_to_sphere(float r, float x, float y) +{ + float d, t, z; + + d = sqrt(x*x + y*y); + if (d < r * 0.70710678118654752440f) { /* Inside sphere */ + z = sqrt(r*r - d*d); + } else { /* On hyperbola */ + t = r / 1.41421356237309504880f; + z = t*t / d; + } + return z; +} + +/* + * Given two rotations, e1 and e2, expressed as quaternion rotations, + * figure out the equivalent single rotation and stuff it into dest. + * + * This routine also normalizes the result every RENORMCOUNT times it is + * called, to keep error from creeping in. + * + * NOTE: This routine is written so that q1 or q2 may be the same + * as dest (or each other). + */ + +#define RENORMCOUNT 97 + +void +add_quats(float q1[4], float q2[4], float dest[4]) +{ + static int count=0; + float t1[4], t2[4], t3[4]; + float tf[4]; + + vcopy(q1,t1); + vscale(t1,q2[3]); + + vcopy(q2,t2); + vscale(t2,q1[3]); + + vcross(q2,q1,t3); + vadd(t1,t2,tf); + vadd(t3,tf,tf); + tf[3] = q1[3] * q2[3] - vdot(q1,q2); + + dest[0] = tf[0]; + dest[1] = tf[1]; + dest[2] = tf[2]; + dest[3] = tf[3]; + + if (++count > RENORMCOUNT) { + count = 0; + normalize_quat(dest); + } +} + +/* + * Quaternions always obey: a^2 + b^2 + c^2 + d^2 = 1.0 + * If they don't add up to 1.0, dividing by their magnitued will + * renormalize them. + * + * Note: See the following for more information on quaternions: + * + * - Shoemake, K., Animating rotation with quaternion curves, Computer + * Graphics 19, No 3 (Proc. SIGGRAPH'85), 245-254, 1985. + * - Pletinckx, D., Quaternion calculus as a basic tool in computer + * graphics, The Visual Computer 5, 2-13, 1989. + */ +static void +normalize_quat(float q[4]) +{ + int i; + float mag; + + mag = (q[0]*q[0] + q[1]*q[1] + q[2]*q[2] + q[3]*q[3]); + for (i = 0; i < 4; i++) q[i] /= mag; +} + +/* + * Build a rotation matrix, given a quaternion rotation. + * + */ +void +build_rotmatrix(float m[4][4], float q[4]) +{ + m[0][0] = 1.0f - 2.0f * (q[1] * q[1] + q[2] * q[2]); + m[0][1] = 2.0f * (q[0] * q[1] - q[2] * q[3]); + m[0][2] = 2.0f * (q[2] * q[0] + q[1] * q[3]); + m[0][3] = 0.0f; + + m[1][0] = 2.0f * (q[0] * q[1] + q[2] * q[3]); + m[1][1]= 1.0f - 2.0f * (q[2] * q[2] + q[0] * q[0]); + m[1][2] = 2.0f * (q[1] * q[2] - q[0] * q[3]); + m[1][3] = 0.0f; + + m[2][0] = 2.0f * (q[2] * q[0] - q[1] * q[3]); + m[2][1] = 2.0f * (q[1] * q[2] + q[0] * q[3]); + m[2][2] = 1.0f - 2.0f * (q[1] * q[1] + q[0] * q[0]); + m[2][3] = 0.0f; + + m[3][0] = 0.0f; + m[3][1] = 0.0f; + m[3][2] = 0.0f; + m[3][3] = 1.0f; +} + diff --git a/bazaar/FTGL_Demo/trackball.h b/bazaar/FTGL_Demo/trackball.h new file mode 100644 index 000000000..c010b78e1 --- /dev/null +++ b/bazaar/FTGL_Demo/trackball.h @@ -0,0 +1,85 @@ +/* + * (c) Copyright 1993, 1994, Silicon Graphics, Inc. + * ALL RIGHTS RESERVED + * Permission to use, copy, modify, and distribute this software for + * any purpose and without fee is hereby granted, provided that the above + * copyright notice appear in all copies and that both the copyright notice + * and this permission notice appear in supporting documentation, and that + * the name of Silicon Graphics, Inc. not be used in advertising + * or publicity pertaining to distribution of the software without specific, + * written prior permission. + * + * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS" + * AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR + * FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON + * GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT, + * SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY + * KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION, + * LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF + * THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC. HAS BEEN + * ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE + * POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE. + * + * US Government Users Restricted Rights + * Use, duplication, or disclosure by the Government is subject to + * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph + * (c)(1)(ii) of the Rights in Technical Data and Computer Software + * clause at DFARS 252.227-7013 and/or in similar or successor + * clauses in the FAR or the DOD or NASA FAR Supplement. + * Unpublished-- rights reserved under the copyright laws of the + * United States. Contractor/manufacturer is Silicon Graphics, + * Inc., 2011 N. Shoreline Blvd., Mountain View, CA 94039-7311. + * + * OpenGL(TM) is a trademark of Silicon Graphics, Inc. + */ +/* + * trackball.h + * A virtual trackball implementation + * Written by Gavin Bell for Silicon Graphics, November 1988. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Pass the x and y coordinates of the last and current positions of + * the mouse, scaled so they are from (-1.0 ... 1.0). + * + * The resulting rotation is returned as a quaternion rotation in the + * first paramater. + */ +void +trackball(float q[4], float p1x, float p1y, float p2x, float p2y); + +/* + * Given two quaternions, add them together to get a third quaternion. + * Adding quaternions to get a compound rotation is analagous to adding + * translations to get a compound translation. When incrementally + * adding rotations, the first argument here should be the new + * rotation, the second and third the total rotation (which will be + * over-written with the resulting new total rotation). + */ +void +add_quats(float *q1, float *q2, float *dest); + +/* + * A useful function, builds a rotation matrix in Matrix based on + * given quaternion. + */ +void +build_rotmatrix(float m[4][4], float q[4]); + +/* + * This function computes a quaternion based on an axis (defined by + * the given vector) and an angle about which to rotate. The angle is + * expressed in radians. The result is put into the third argument. + */ +void +axis_to_quat(float a[3], float phi, float q[4]); + +#ifdef __cplusplus +} +#endif