mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-09-03 08:42:41 -06:00
GLCanvas: Added
git-svn-id: svn://ultimatepp.org/upp/trunk@12889 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
parent
63a2eae1de
commit
8d0ec4742e
8 changed files with 805 additions and 0 deletions
93
bazaar/GLCanvas/GLCanvas.cpp
Normal file
93
bazaar/GLCanvas/GLCanvas.cpp
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
#include <GLCanvas/GLCanvas.h>
|
||||
|
||||
using namespace Upp;
|
||||
|
||||
|
||||
GLCanvas::GLCanvas() {
|
||||
WantFocus();
|
||||
|
||||
trackBall.Init(this);
|
||||
|
||||
SetCamera();
|
||||
}
|
||||
|
||||
Image GLCanvas::MouseEvent(int event, Point p, int zdelta, dword keyflags) {
|
||||
Image img = trackBall.MouseEvent(event, p, zdelta, keyflags);
|
||||
Refresh();
|
||||
return img;
|
||||
}
|
||||
|
||||
void GLCanvas::SetUpLighting() {
|
||||
float light1_ambient[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
|
||||
float light1_diffuse[4] = { 1.0f, 0.9f, 0.9f, 1.0f };
|
||||
float light1_specular[4] = { 1.0f, 0.7f, 0.7f, 1.0f };
|
||||
float light1_position[4] = { -1.0, 1.0, 1.0, 0.0f };
|
||||
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.2f, 0.2f, 0.2f, 1.0f };
|
||||
float light2_diffuse[4] = { 0.9f, 0.9f, 0.9f, 1.0f };
|
||||
float light2_specular[4] = { 0.7f, 0.7f, 0.7f, 1.0f };
|
||||
float light2_position[4] = { 1.0, -1.0, -1.0, 0.0f };
|
||||
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.3f, 0.2f, 0.1f, 0.0f };
|
||||
float front_ambient[4] = { 0.2f, 0.2f, 0.2f, 0.0f };
|
||||
float front_diffuse[4] = { 0.95f, 0.95f, 0.8f, 0.0f };
|
||||
float front_specular[4] = { 0.6f, 0.6f, 0.6f, 0.0f };
|
||||
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 GLCanvas::SetCamera(void) {
|
||||
glMatrixMode (GL_PROJECTION);
|
||||
glLoadIdentity ();
|
||||
gluPerspective(trackBall.GetZoomFactor(), (float)GetSize().cx / (float)GetSize().cy, 1, 10000);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
gluLookAt(0.0, 0.0, (float)GetSize().cy/2., 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
|
||||
}
|
||||
|
||||
void GLCanvas::Layout() {
|
||||
GLCtrl::Layout();
|
||||
glMatrixMode (GL_MODELVIEW);
|
||||
glViewport (0, 0, GetSize().cx, GetSize().cy);
|
||||
glLoadIdentity();
|
||||
SetCamera();
|
||||
trackBall.Reshape(GetSize().cx, GetSize().cy);
|
||||
}
|
||||
|
||||
void GLCanvas::GLPaint() {
|
||||
glClearColor(1, 1, 1, 0);
|
||||
glClearDepth(0);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
SetCamera();
|
||||
glTranslatef(0, 0, 0);
|
||||
trackBall.Matrix();
|
||||
|
||||
glPushMatrix();
|
||||
glDisable(GL_BLEND);
|
||||
SetUpLighting();
|
||||
WhenPaint();
|
||||
glPopMatrix();
|
||||
}
|
||||
89
bazaar/GLCanvas/GLCanvas.h
Normal file
89
bazaar/GLCanvas/GLCanvas.h
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
#ifndef _GLCanvas_GLCanvas_h_
|
||||
#define _GLCanvas_GLCanvas_h_
|
||||
|
||||
#include <GLCtrl/GLCtrl.h>
|
||||
#include "trackball.h"
|
||||
#include "surface.h"
|
||||
|
||||
class GLCanvas : public GLCtrl {
|
||||
public:
|
||||
typedef GLCanvas CLASSNAME;
|
||||
|
||||
GLCanvas();
|
||||
|
||||
private:
|
||||
TrackBall trackBall;
|
||||
|
||||
void SetUpLighting();
|
||||
void SetCamera();
|
||||
|
||||
protected:
|
||||
virtual void Layout();
|
||||
virtual Image MouseEvent(int event, Point p, int zdelta, dword keyflags);
|
||||
|
||||
public:
|
||||
void PaintLine(double x0, double y0, double z0, double x1, double y1, double z1, Color color) {
|
||||
glBegin(GL_LINES);
|
||||
glColor4d(color.GetR()/255., color.GetG()/255., color.GetB()/255., 1);
|
||||
glVertex3d(x0, y0, z0);
|
||||
glVertex3d(x1, y1, z1); //
|
||||
glEnd();
|
||||
}
|
||||
|
||||
void PaintAxis(double x, double y, double z) {
|
||||
PaintLine(0, 0, 0, x, 0, 0, LtRed());
|
||||
PaintLine(0, 0, 0, 0, y, 0, LtGreen());
|
||||
PaintLine(0, 0, 0, 0, 0, z, LtBlue());
|
||||
}
|
||||
|
||||
void PaintSurface(Surface &surf, Color linCol = LtGreen()) {
|
||||
PaintSurface0(surf, linCol, false, false);
|
||||
if (surf.x0z)
|
||||
PaintSurface0(surf, linCol, false, true);
|
||||
if (surf.y0z)
|
||||
PaintSurface0(surf, linCol, true, false);
|
||||
}
|
||||
|
||||
void SetZoomFactor(double factor) {trackBall.SetZoomFactor(factor);}
|
||||
|
||||
Function <void()> WhenPaint;
|
||||
|
||||
virtual void GLPaint();
|
||||
|
||||
private:
|
||||
void PaintSurface0(Surface &surf, Color linCol, bool simX, bool simY) {
|
||||
double xsig = simX ? -1 : 1;
|
||||
double ysig = simY ? -1 : 1;
|
||||
|
||||
for (int ip = 0; ip < surf.panels.GetCount(); ++ip) {
|
||||
Panel &panel = surf.panels[ip];
|
||||
Point3D &p0 = surf.nodes[panel.id0];
|
||||
Point3D &p1 = surf.nodes[panel.id1];
|
||||
Point3D &p2 = surf.nodes[panel.id2];
|
||||
Point3D &p3 = surf.nodes[panel.id3];
|
||||
|
||||
/*glBegin(GL_QUADS);
|
||||
glColor4d(1.0, 0.5, 0.0, 1);
|
||||
if (!sim) {
|
||||
glVertex3d(p0.x, p0.y*ysig, p0.z);
|
||||
glVertex3d(p1.x, p1.y*ysig, p1.z);
|
||||
glVertex3d(p2.x, p2.y*ysig, p2.z);
|
||||
glVertex3d(p3.x, p3.y*ysig, p3.z);
|
||||
} else {
|
||||
glVertex3d(p3.x, p3.y*ysig, p3.z);
|
||||
glVertex3d(p2.x, p2.y*ysig, p2.z);
|
||||
glVertex3d(p1.x, p1.y*ysig, p1.z);
|
||||
glVertex3d(p0.x, p0.y*ysig, p0.z);
|
||||
}
|
||||
glEnd();*/
|
||||
|
||||
PaintLine(p0.x*xsig, p0.y*ysig, p0.z, p1.x*xsig, p1.y*ysig, p1.z, linCol);
|
||||
PaintLine(p1.x*xsig, p1.y*ysig, p1.z, p2.x*xsig, p2.y*ysig, p2.z, linCol);
|
||||
PaintLine(p2.x*xsig, p2.y*ysig, p2.z, p3.x*xsig, p3.y*ysig, p3.z, linCol);
|
||||
PaintLine(p3.x*xsig, p3.y*ysig, p3.z, p0.x*xsig, p0.y*ysig, p0.z, linCol);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
15
bazaar/GLCanvas/GLCanvas.upp
Normal file
15
bazaar/GLCanvas/GLCanvas.upp
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
description "A basic canvas for OpenGL drawings\377B255,170,0";
|
||||
|
||||
uses
|
||||
GLCtrl;
|
||||
|
||||
file
|
||||
GLCanvas.cpp,
|
||||
GLCanvas.h,
|
||||
surface.h,
|
||||
trackball.cpp,
|
||||
trackball.h,
|
||||
trkball.c,
|
||||
trkball.h;
|
||||
|
||||
spellcheck_comments "EN-GB"
|
||||
93
bazaar/GLCanvas/surface.h
Normal file
93
bazaar/GLCanvas/surface.h
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
#ifndef _GLCanvas_surface_h_
|
||||
#define _GLCanvas_surface_h_
|
||||
|
||||
class Panel : public Moveable<Panel> {
|
||||
public:
|
||||
int id0, id1, id2, id3;
|
||||
|
||||
String ToString() const { return FormatInt(id0) + "," + FormatInt(id1) + "," + FormatInt(id2) + "," + FormatInt(id3); }
|
||||
};
|
||||
|
||||
class Point3D : public Moveable<Point3D> {
|
||||
public:
|
||||
double x, y, z;
|
||||
|
||||
String ToString() const { return FormatDouble(x) + "," + FormatDouble(y) + "," + FormatDouble(z); }
|
||||
};
|
||||
|
||||
|
||||
template <typename T>
|
||||
inline T const& maxNotNull(T const& a, T const& b) {
|
||||
if (IsNull(a))
|
||||
return b;
|
||||
else if (IsNull(b))
|
||||
return a;
|
||||
else
|
||||
return a > b ? a : b;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T const& minNotNull(T const& a, T const& b) {
|
||||
if (IsNull(a))
|
||||
return b;
|
||||
else if (IsNull(b))
|
||||
return a;
|
||||
else
|
||||
return a < b ? a : b;
|
||||
}
|
||||
|
||||
|
||||
class VolumeEnvelope {
|
||||
public:
|
||||
VolumeEnvelope() {Reset();}
|
||||
void Reset() {
|
||||
maxX = minX = maxY = minY = maxZ = minZ = Null;
|
||||
}
|
||||
|
||||
void MixEnvelope(VolumeEnvelope &env) {
|
||||
maxX = maxNotNull(env.maxX, maxX);
|
||||
minX = minNotNull(env.minX, minX);
|
||||
maxY = maxNotNull(env.maxY, maxY);
|
||||
minY = minNotNull(env.minY, minY);
|
||||
maxZ = maxNotNull(env.maxZ, maxZ);
|
||||
minZ = minNotNull(env.minZ, minZ);
|
||||
}
|
||||
|
||||
double maxX, minX, maxY, minY, maxZ, minZ;
|
||||
};
|
||||
|
||||
class Surface {
|
||||
public:
|
||||
Surface() : x0z(false), y0z(false) {}
|
||||
Vector<Point3D> nodes;
|
||||
Vector<Panel> panels;
|
||||
bool x0z, y0z;
|
||||
String file;
|
||||
VolumeEnvelope env;
|
||||
|
||||
bool Check() {
|
||||
for (int i = 0; i < panels.GetCount(); ++i)
|
||||
if (!panels[i].id0 || !panels[i].id1 || !panels[i].id2 || !panels[i].id3)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
void GetLimits() {
|
||||
env.maxX = env.maxY = env.maxZ = -DBL_MAX;
|
||||
env.minX = env.minY = env.minZ = DBL_MAX;
|
||||
for (int i = 0; i < nodes.GetCount(); ++i) {
|
||||
env.maxX = max(env.maxX, nodes[i].x);
|
||||
env.minX = min(env.minX, nodes[i].x);
|
||||
env.maxY = max(env.maxY, nodes[i].y);
|
||||
env.minY = min(env.minY, nodes[i].y);
|
||||
env.maxZ = max(env.maxZ, nodes[i].z);
|
||||
env.minZ = min(env.minZ, nodes[i].z);
|
||||
}
|
||||
}
|
||||
String GetLastError() {return lastError;}
|
||||
String lastError;
|
||||
|
||||
private:
|
||||
inline bool CheckId(int id) {return id >= 0 && id < nodes.GetCount()-1;}
|
||||
};
|
||||
|
||||
#endif
|
||||
63
bazaar/GLCanvas/trackball.cpp
Normal file
63
bazaar/GLCanvas/trackball.cpp
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
#include "TrackBall.h"
|
||||
#include "trkball.h"
|
||||
|
||||
#ifdef PLATFORM_POSIX
|
||||
#include <GL/glut.h>
|
||||
#elif defined(WIN32)
|
||||
#include <gl/glu.h>
|
||||
#endif
|
||||
|
||||
TrackBall::TrackBall() {
|
||||
owner = NULL;
|
||||
buttonRot = Ctrl::LEFT;
|
||||
tracking = false;
|
||||
zoomFactor = 10;
|
||||
//trackball(curquat, 0, -.5, -1, 1);
|
||||
curquat[0] = 0.15f; curquat[1] = 0.35f; curquat[2] = 0.85f; curquat[3] = 0.35f;
|
||||
}
|
||||
|
||||
void TrackBall::Init(Ctrl *ow) {
|
||||
owner = ow;
|
||||
}
|
||||
|
||||
void TrackBall::Matrix() {
|
||||
GLfloat m[4][4];
|
||||
|
||||
build_rotmatrix(m, curquat);
|
||||
glMultMatrixf(&m[0][0]);
|
||||
}
|
||||
|
||||
void TrackBall::Reshape(int w, int h) {
|
||||
width = w;
|
||||
height = h;
|
||||
}
|
||||
|
||||
Image TrackBall::MouseEvent(int event, Point p, int zdelta, dword keyflags) {
|
||||
if ((event & Ctrl::ACTION) == Ctrl::MOUSEWHEEL) {
|
||||
zoomFactor = min<double>(180., zoomFactor * (1 - zdelta/1000.));
|
||||
owner->Refresh();
|
||||
} else if ((event & Ctrl::BUTTON) == buttonRot && (event & Ctrl::ACTION) == Ctrl::DOWN) {
|
||||
tracking = true;
|
||||
beginx = p.x;
|
||||
beginy = p.y;
|
||||
} else {
|
||||
if ((event & Ctrl::BUTTON) == buttonRot && (event & Ctrl::ACTION) == Ctrl::UP)
|
||||
tracking = false;
|
||||
else if((event & Ctrl::ACTION) == Ctrl::MOUSEMOVE) {
|
||||
if (tracking) {
|
||||
trackball(
|
||||
lastquat,
|
||||
float((2.0 * beginx - width) / width),
|
||||
float((height - 2.0 * beginy) / height),
|
||||
float((2.0 * p.x - width) / width),
|
||||
float((height - 2.0 * p.y) / height)
|
||||
);
|
||||
beginx = p.x;
|
||||
beginy = p.y;
|
||||
add_quats(lastquat, curquat, curquat);
|
||||
owner->Refresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
return Image::Hand();
|
||||
}
|
||||
41
bazaar/GLCanvas/trackball.h
Normal file
41
bazaar/GLCanvas/trackball.h
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
#ifndef _FTGL_Demo_TrackBall_h_
|
||||
#define _FTGL_Demo_TrackBall_h_
|
||||
|
||||
#include <CtrlLib/CtrlLib.h>
|
||||
|
||||
using namespace Upp;
|
||||
|
||||
class TrackBall {
|
||||
public:
|
||||
typedef TrackBall CLASSNAME;
|
||||
|
||||
TrackBall();
|
||||
void Init(Ctrl *owner);
|
||||
|
||||
void Matrix(void);
|
||||
void Reshape(int width, int height);
|
||||
void SetZoomFactor(double factor) {factor = zoomFactor;}
|
||||
double GetZoomFactor() {return zoomFactor;}
|
||||
void SetButtonRot(int but = Ctrl::LEFT) {buttonRot = but; }
|
||||
|
||||
|
||||
virtual Image MouseEvent(int event, Point p, int zdelta, dword keyflags);
|
||||
|
||||
float curquat[4];
|
||||
|
||||
private:
|
||||
Ctrl *owner;
|
||||
|
||||
// float curquat[4];
|
||||
float lastquat[4];
|
||||
int beginx, beginy;
|
||||
|
||||
int width, height;
|
||||
|
||||
int buttonRot;
|
||||
bool tracking;
|
||||
|
||||
double zoomFactor;
|
||||
};
|
||||
|
||||
#endif
|
||||
326
bazaar/GLCanvas/trkball.c
Normal file
326
bazaar/GLCanvas/trkball.c
Normal file
|
|
@ -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 <math.h>
|
||||
#include "trkball.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;
|
||||
}
|
||||
|
||||
85
bazaar/GLCanvas/trkball.h
Normal file
85
bazaar/GLCanvas/trkball.h
Normal file
|
|
@ -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
|
||||
Loading…
Add table
Add a link
Reference in a new issue