⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 glwindow.c

📁 任意给定三维空间的点集
💻 C
📖 第 1 页 / 共 2 页
字号:
inline Mat4 Mat4::operator/(double s) const{    return Mat4(row[0]/s, row[1]/s, row[2]/s, row[3]/s);}inline GPoint4 Mat4::operator*(const GPoint4& v) const{    return GPoint4(row[0]*v, row[1]*v, row[2]*v, row[3]*v);}//// Transform a homogeneous 3-vector and reproject into normal 3-space//inline GPoint3 Mat4::operator*(const GPoint3  & v) const{    GPoint4 u=GPoint4(v,1);    double w=row[3].pnt*u;    if(w==0.0)	return GPoint3(row[0].pnt*u, row[1].pnt*u, row[2].pnt*u);    else	return GPoint3(row[0].pnt*u/w, row[1].pnt*u/w, row[2].pnt*u/w);}extern bool jacobi(const Mat4& m, GPoint4& vals, GPoint4 vecs[4]);#ifdef MXGL_INCLUDEDinline void glGetMatrix(Mat4& m, GLenum which=GL_MODELVIEW_MATRIX){ Mat4 tmp;  glGetDoublev(which, &tmp(0,0));  m=tmp.transpose(); }inline void glLoadMatrix(const Mat4& m){ Mat4 tmp = m.transpose();  glLoadMatrixd(&tmp(0,0)); }inline void glMultMatrix(const Mat4& m){ Mat4 tmp = m.transpose();  glMultMatrixd(&tmp(0,0)); }#endif//#include "stdmix.h"//#include "GL.h"//#include "Arcball.h"enum AxisSet {NoAxes, CameraAxes, BodyAxes, OtherAxes, NSets};enum BallType { ArcBall, TrackBall };typedef Mat4 HMatrix;/* ***** BallAux.c ***** */typedef  GPoint4  Quat;Quat qOne(0,0,0,1);/* Return quaternion product qL * qR.  Note: order is important! * To combine rotations, use the product Mul(qSecond, qFirst), * which gives the effect of rotating by qFirst then qSecond. */Quat Qt_Mul(Quat& qL, Quat& qR){    Quat qq;    qq.pnt[W] = qL[W]*qR[W] - qL[X]*qR[X] - qL[Y]*qR[Y] - qL[Z]*qR[Z];    qq.pnt[X] = qL[W]*qR[X] + qL[X]*qR[W] + qL[Y]*qR[Z] - qL[Z]*qR[Y];    qq.pnt[Y] = qL[W]*qR[Y] + qL[Y]*qR[W] + qL[Z]*qR[X] - qL[X]*qR[Z];    qq.pnt[Z] = qL[W]*qR[Z] + qL[Z]*qR[W] + qL[X]*qR[Y] - qL[Y]*qR[X];    return (qq);}/* Construct rotation matrix from (possibly non-unit) quaternion. * Assumes matrix is used to multiply column vector on the left: * vnew = mat vold.  Works correctly for right-handed coordinate system * and right-handed rotations. */HMatrix *Qt_ToMatrix(const Quat& q, HMatrix& out){    double Nq = norm2(q);    double s = (Nq > 0.0) ? (2.0 / Nq) : 0.0;    double xs = q[X]*s,  ys = q[Y]*s,  zs = q[Z]*s;    double wx = q[W]*xs, wy = q[W]*ys, wz = q[W]*zs;    double xx = q[X]*xs, xy = q[X]*ys, xz = q[X]*zs;    double yy = q[Y]*ys, yz = q[Y]*zs, zz = q[Z]*zs;    out(X,X) = 1.0 - (yy + zz); out(Y,X) = xy + wz; out(Z,X) = xz - wy;    out(X,Y) = xy - wz; out(Y,Y) = 1.0 - (xx + zz); out(Z,Y) = yz + wx;    out(X,Z) = xz + wy; out(Y,Z) = yz - wx; out(Z,Z) = 1.0 - (xx + yy);    out(X,W) = out(Y,W) = out(Z,W) = out(W,X) = out(W,Y) = out(W,Z) = 0.0;    out(W,W) = 1.0;    return ((HMatrix *)&out);}/* Return conjugate of quaternion. */Quat Qt_Conj(Quat& q){    Quat qq;    qq.pnt[X] = -q[X];    qq.pnt[Y] = -q[Y];    qq.pnt[Z] = -q[Z];    qq.pnt[W] = q[W];    return (qq);}/* Return vector formed from components */inline GPoint4 V3_(float x, float y, float z){    return GPoint4(x, y, z, 0);}/* Return norm of v, defined as sum of squares of components */inline double V3_Norm(const GPoint4& v){    return ( v[X]*v[X] + v[Y]*v[Y] + v[Z]*v[Z] );}/* Return unit magnitude vector in direction of v */GPoint4 V3_Unit(const GPoint4& v){    static GPoint4 u(0, 0, 0, 0);    float vlen = sqrt(V3_Norm(v));    if (vlen != 0.0) {	u.pnt[X] = v[X]/vlen;        u.pnt[Y] = v[Y]/vlen;         u.pnt[Z] = v[Z]/vlen;    }    return (u);}/* Return version of v scaled by s */inline GPoint4 V3_Scale(const GPoint4& v, float s){    return GPoint4(s*v[X], s*v[Y], s*v[Z], v[W]);}/* Return negative of v */inline GPoint4 V3_Negate(const GPoint4& v){    return GPoint4(-v[X], -v[Y], -v[Z], 0);}/* Return sum of v1 and v2 */inline GPoint4 V3_Add(const GPoint4& v1, const GPoint4& v2){    return GPoint4(v1[X]+v2[X], v1[Y]+v2[Y], v1[Z]+v2[Z], 0);}/* Return difference of v1 minus v2 */inline GPoint4 V3_Sub(const GPoint4& v1, const GPoint4& v2){    return GPoint4(v1[X]-v2[X], v1[Y]-v2[Y], v1[Z]-v2[Z], 0);}/* Halve arc between unit vectors v0 and v1. */GPoint4 V3_Bisect(const GPoint4& v0, const GPoint4& v1){    GPoint4 v(0, 0, 0, 0);    v = V3_Add(v0, v1);    float Nv = V3_Norm(v);    if (Nv < 1.0e-5) {	v = V3_(0, 0, 1);    } else {	v = V3_Scale(v, 1/sqrt(Nv));    }    return (v);}/* Return dot product of v1 and v2 */double V3_Dot(const GPoint4& v1, const GPoint4& v2){    return (v1[X]*v2[X] + v1[Y]*v2[Y] + v1[Z]*v2[Z]);}/* Return cross product, v1 x v2 */inline GPoint4 V3_Cross(const GPoint4& v1, const GPoint4& v2){    return GPoint4(v1[Y]*v2[Z]-v1[Z]*v2[Y],		v1[Z]*v2[X]-v1[X]*v2[Z],		v1[X]*v2[Y]-v1[Y]*v2[X],		0);}/* ***** Ball.h ***** */typedef GPoint4 *ConstraintSet;struct BallData {    GPoint4 center;    double radius, aspect;    Quat qNow, qDown, qDrag;    GPoint4 vNow, vDown, vFrom, vTo, vrFrom, vrTo;    HMatrix mNow, mDown;    int dragging;    ConstraintSet sets[NSets];    int setSizes[NSets];    AxisSet axisSet;    int axisIndex;    BallType ballType;};/* Public routines */extern BallData *Ball_Alloc();extern void Ball_Free(BallData *);extern void Ball_Init(BallData *ball, double aspect);extern void Ball_Place(BallData *ball, GPoint4 center, double radius		       /*, Quat orient*/);extern void Ball_Mouse(BallData *ball, GPoint4 vNow);extern void Ball_UseSet(BallData *ball, AxisSet axisSet);extern void Ball_Update(BallData *ball, int al);extern void Ball_Value(BallData *ball, HMatrix& mNow);extern void Ball_BeginDrag(BallData *ball);extern void Ball_EndDrag(BallData *ball);extern int Ball_MouseOutsideSphere(BallData *ball, GPoint4 vMouse);extern void Ball_SetBallType(BallData *ball, BallType bt);/* Private routines *//* ***** BallMath.c ***** *//* Convert window coordinates to sphere coordinates. */GPoint4 MouseOnSphere(GPoint4 mouse, GPoint4 ballCenter, double ballRadius){    GPoint4 ballMouse;    register double mag;    ballMouse.pnt[X] = (mouse[X] - ballCenter[X]) / ballRadius;    ballMouse.pnt[Y] = (mouse[Y] - ballCenter[Y]) / ballRadius;    mag = ballMouse[X]*ballMouse[X] + ballMouse[Y]*ballMouse[Y];    if (mag > 1.0) {	register double scale = 1.0/sqrt(mag);	ballMouse.pnt[X] *= scale; ballMouse.pnt[Y] *= scale;	ballMouse.pnt[Z] = 0.0;    } else {	ballMouse.pnt[Z] = sqrt(1 - mag);    }    ballMouse.pnt[W] = 0.0;    return (ballMouse);}/* Construct a unit quaternion from two points on unit sphere */Quat Qt_FromBallPoints(GPoint4 from, GPoint4 to, BallType bt){    Quat qu;    qu.pnt[X] = from[Y]*to[Z] - from[Z]*to[Y];    qu.pnt[Y] = from[Z]*to[X] - from[X]*to[Z];    qu.pnt[Z] = from[X]*to[Y] - from[Y]*to[X];    if (bt == ArcBall){	qu.pnt[W] = from[X]*to[X] + from[Y]*to[Y] + from[Z]*to[Z];    }    else {	float  a, s, mag;	a = .5*acos(from[X]*to[X] + from[Y]*to[Y] + from[Z]*to[Z]);	mag = sqrt(qu[X]*qu[X] + qu[Y]*qu[Y] + qu[Z]*qu[Z]);	qu.pnt[W] = cos(a); s = sin(a);	if (s != 0)	  s /= mag;	qu.pnt[X] *= s;  qu.pnt[Y] *= s; qu.pnt[Z] *= s;    }    return (qu);}/* Convert a unit quaternion to two points on unit sphere */void Qt_ToBallPoints(Quat q, GPoint4 *arcFrom, GPoint4 *arcTo){    double s;    s = sqrt(q[X]*q[X] + q[Y]*q[Y]);    if (s == 0.0) {	*arcFrom = V3_(0.0, 1.0, 0.0);    } else {	*arcFrom = V3_(-q[Y]/s, q[X]/s, 0.0);    }    (*arcTo).pnt[X] = q[W]*(*arcFrom)[X] - q[Z]*(*arcFrom)[Y];    (*arcTo).pnt[Y] = q[W]*(*arcFrom)[Y] + q[Z]*(*arcFrom)[X];    (*arcTo).pnt[Z] = q[X]*(*arcFrom)[Y] - q[Y]*(*arcFrom)[X];    if (q[W] < 0.0) *arcFrom = V3_(-(*arcFrom)[X], -(*arcFrom)[Y], 0.0);}/* Force sphere point to be perpendicular to axis. */GPoint4 ConstrainToAxis(GPoint4& loose, GPoint4& axis){    GPoint4 onPlane = V3_Sub(loose, V3_Scale(axis, V3_Dot(axis, loose)));    register float norm = V3_Norm(onPlane);    if (norm > 0.0) {	if (onPlane[Z] < 0.0) onPlane = V3_Negate(onPlane);	return ( V3_Scale(onPlane, 1/sqrt(norm)) );    } /* else drop through */    if (axis[Z] == 1) {	onPlane = V3_(1.0, 0.0, 0.0);    } else {	onPlane = V3_Unit(V3_(-axis[Y], axis[X], 0.0));    }    return (onPlane);}/* Find the index of nearest arc of axis set. */int NearestConstraintAxis(GPoint4& loose, GPoint4 *axes, int nAxes){    GPoint4 onPlane;    register float max, dot;    register int i, nearest;    max = -1; nearest = 0;    for (i=0; i<nAxes; i++) {	onPlane = ConstrainToAxis(loose, axes[i]);	dot = V3_Dot(onPlane, loose);	if (dot>max) {	    max = dot; nearest = i;	}    }    return (nearest);}/* ***** Ball.c ***** *//* Ken Shoemake, 1993 *//* Modified by Victor Ng, Jan. 1996 for OpenGL */#define FALSE 0#define TRUE 1#define LG_NSEGS 4#define NSEGS (1<<LG_NSEGS)#define RIMCOLOR()    glColor3f(0.0f, 1.0f, 1.0f);#define FARCOLOR()    glColor3f(0.8f, 0.5f, 0.0f);#define NEARCOLOR()   glColor3f(1.0f, 0.8f, 0.0f);#define DRAGCOLOR()   glColor3f(0.0f, 1.0f, 1.0f);#define RESCOLOR()    glColor3f(0.8f, 0.0f, 0.0f);GPoint4 otherAxis(-0.48, 0.80, 0.36, 1);BallData *Ball_Alloc(){    return (BallData *)malloc( sizeof(BallData) );}void Ball_Free(BallData *ball){    free(ball);}/* Establish reasonable initial values for controller. */void Ball_Init(BallData *ball, double aspect){    ball->center = qOne;    ball->radius = 1.0;    ball->aspect = aspect;    ball->ballType = ArcBall;    ball->vDown = ball->vNow = qOne;    ball->qDown = ball->qNow = qOne;    ball->mNow = Mat4::I;    ball->mDown = Mat4::I;    ball->dragging = FALSE;    ball->axisSet = NoAxes;    ball->sets[CameraAxes]     = (GPoint4 *)&Mat4::I(0,0);  // Mat4::I.row(0)    ball->setSizes[CameraAxes] = 3;    ball->sets[BodyAxes] = (GPoint4 *)&ball->mDown(0,0);  // mDown.row(0)    ball->setSizes[BodyAxes] = 3;    ball->sets[OtherAxes] = &otherAxis;    ball->setSizes[OtherAxes] = 1;}/* Set the center and size of the controller. */void Ball_Place(BallData *ball, GPoint4 center, double radius){    ball->center = center;    ball->radius = radius;}/* Incorporate new mouse position. */void Ball_Mouse(BallData *ball, GPoint4 vNow){    ball->vNow = vNow;}/* Choose a constraint set, or none. */void Ball_UseSet(BallData *ball, AxisSet axisSet){    /* if (!ball->dragging) */	ball->axisSet = axisSet;}/* Using vDown, vNow, dragging, and axisSet, compute rotation etc. *//* To use closest constraint axis, set aI to -1 */void Ball_Update(BallData *ball, int aI){    int setSize = ball->setSizes[ball->axisSet];    GPoint4 *set = (GPoint4 *)(ball->sets[ball->axisSet]);    ball->vFrom = MouseOnSphere(ball->vDown, ball->center, ball->radius);    ball->vTo = MouseOnSphere(ball->vNow, ball->center, ball->radius);    if (ball->dragging) {        if (ball->axisSet!=NoAxes) {	    aI = (aI==-1) ? ball->axisIndex : aI;            ball->vFrom = ConstrainToAxis(ball->vFrom, set[aI]);            ball->vTo = ConstrainToAxis(ball->vTo, set[aI]);        }        ball->qDrag =Qt_FromBallPoints(ball->vFrom, ball->vTo, ball->ballType);        ball->qNow = Qt_Mul(ball->qDrag, ball->qDown);    } else {        if (ball->axisSet!=NoAxes) {            ball->axisIndex = (aI==-1) ?	                      NearestConstraintAxis(ball->vTo, set, setSize) :	                      aI;        }    }    Qt_ToBallPoints(ball->qDown, &ball->vrFrom, &ball->vrTo);    Qt_ToMatrix(Qt_Conj(ball->qNow), ball->mNow); /* Gives transpose for GL. */}/* Returns TRUE iff vMouse is a point off the arcball sphere */int Ball_MouseOutsideSphere(BallData *ball, GPoint4 vMouse){    GPoint4  vTest = MouseOnSphere(vMouse, ball->center, ball->radius);    return vTest[Z] == 0.0;}/* Set the BallType: 'ArcBall' rotates through _twice_ the angle * between the two points on the sphere, and exhibits no * hysteresis. 'TrackBall' rotates through exactly the angle between * the two points on the sphere, like a physical trackball, and * consequently exhibits hysteresis. */void Ball_SetBallType(BallData *ball, BallType bt){    ball->ballType = bt;}/* Return rotation matrix defined by controller use. */void Ball_Value(BallData *ball, HMatrix& mNow){    mNow = ball->mNow;}/* Begin drag sequence. */void Ball_BeginDrag(BallData *ball){    ball->dragging = TRUE;    ball->vDown = ball->vNow;}/* Stop drag sequence. */void Ball_EndDrag(BallData *ball){    ball->dragging = FALSE;    ball->qDown = ball->qNow;    ball->mDown = ball->mNow;}Arcball::~Arcball(){    if( ball ) Ball_Free(ball);}void Arcball::init(const GBBox   & bounds, float aspect){    if( ball ) Ball_Free(ball);  // Don't try to reuse old Balls    ball = Ball_Alloc();    Ball_Init(ball, aspect);    Ball_UseSet(ball, NoAxes);    Ball_SetBallType(ball, ArcBall);    GPoint3  tmp_center;    bounds.center( tmp_center );    center = GPoint4( tmp_center, 1 );    radius = bounds.get_radius();    cam[X] = cam[Y] = cam[Z] = 0.0f;    dragging = NoDrag;    Ball_Place(ball, qOne, 0.9 /* 0.75 */);}bool Arcball::mouse_down(int button, int x, int y,                          int  width, int  height ){    mousex = startx = x;    mousey = starty = y;    //printf( "mouse_down( button: %d, x: %d, y: %d, width: %d, height: %d\n",    //        button, x, y, width, height );    if( button == 1 ) {         //int width, height;        //glGetViewport(NULL, NULL, &width, &height);        vNow.pnt[X] = 2.0*startx/(float)width-1.0;        vNow.pnt[Y] = -2.0*starty/(float)height+1.0;        Ball_Mouse(ball, vNow);        Ball_BeginDrag(ball);        dragging = Spin;        //printf/( "spinning!\n" );    }    else if( button == 2 )    {        dragging = Dolly;    }    else if( button == 3 )    {        dragging = Zoom;    }    return true;}bool Arcball::mouse_up(int /*button*/, int /*x*/, int /*y*/){    startx = mousex = 0;    starty = mousey = 0;    if( dragging == Spin )        Ball_EndDrag(ball);    dragging = NoDrag;    return false;}bool Arcball::motion(int x, int y, int  width, int  height ){    if( !dragging )        return false;    if( dragging == Spin )    {        mousex = x;        mousey = y;        //int width, height;        //glGetViewport(NULL, NULL, &width, &height);        vNow.pnt[X] = 2.0*mousex/(float)width-1.0;        vNow.pnt[Y] = -2.0*mousey/(float)height+1.0;        Ball_Mouse(ball, vNow);    }    else if( dragging == Dolly )    {	//int width, height;        //	glGetViewport(NULL, NULL, &width, &height);	cam[X] += radius * (float)(x - mousex) / (float)width;	cam[Y] += radius * (float)(mousey - y) / (float)height;        mousex = x;        mousey = y;    }    else if( dragging == Zoom )    {        cam[Z] += 0.02*radius*(float)(y - mousey);        mousey = y;    }    return true;}void Arcball::apply(){    Ball_Update(ball, -1);    glPushMatrix();    glTranslatef(cam[X], cam[Y], cam[Z]);    HMatrix mNow;    Ball_Value(ball, mNow);    glTranslatef(center[X], center[Y], center[Z]);    glMultMatrixd((double *)&mNow);    glTranslatef(-center[X], -center[Y], -center[Z]);}void Arcball::unapply(){    glPopMatrix();}/* glbox.C - End of File ------------------------------------------*/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -