Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Gimp/plug-ins/map-object/   (Gimp Bildeditor Version 3.2.0©)  Datei vom 14.2.2026 mit Größe 11 kB image not shown  

Quelle  arcball.c   Sprache: C

 

/************************************/
/* ArcBall.c (c) Ken Shoemake, 1993 */
/* Modified by Tom Bech, 1996       */
/************************************/

#include "config.h"

#include <libgimp/gimp.h>

#include "arcball.h"

/* Global variables */
/* ================ */

Quat qOne = { 0, 0, 0, 1 };

static HVect         center;
static double        radius;
static Quat          qNow, qDown, qDrag;
static HVect         vNow, vDown, vFrom, vTo, vrFrom, vrTo;
static HMatrix       mNow, mDown;
static unsigned int  showResult, dragging;
static ConstraintSet sets[NSets];
static int           setSizes[NSets];
static AxisSet       axisSet;
static int           axisIndex;

static HMatrix mId =
{
  { 1, 0, 0, 0 },
  { 0, 1, 0, 0 },
  { 0, 0, 1, 0 },
  { 0, 0, 0, 1 }
};

static double otherAxis[][4] =
{
  {-0.48, 0.80, 0.36, 1}
};

/* Internal methods */
/* ================ */

static void     Qt_ToMatrix(Quat q,HMatrix out);
static Quat     Qt_Conj(Quat q);
static Quat     Qt_Mul(Quat qL, Quat qR);
static Quat     Qt_FromBallPoints(HVect from, HVect to);
static void     Qt_ToBallPoints(Quat q, HVect *arcFrom, HVect *arcTo);

static HVect    V3_(double x, double y, double z);
static double   V3_Norm(HVect v);
static HVect    V3_Unit(HVect v);
static HVect    V3_Scale(HVect v, double s);
static HVect    V3_Negate(HVect v);
/*
static HVect    V3_Add(HVect v1, HVect v2);
*/

static HVect    V3_Sub(HVect v1, HVect v2);
static double   V3_Dot(HVect v1, HVect v2);
/*
static HVect    V3_Cross(HVect v1, HVect v2);
static HVect    V3_Bisect(HVect v0, HVect v1);
*/


static HVect    MouseOnSphere(HVect mouse, HVect ballCenter, double ballRadius);
static HVect    ConstrainToAxis(HVect loose, HVect axis);
static int      NearestConstraintAxis(HVect loose, HVect *axes, int nAxes);

/* Establish reasonable initial values for controller. */
/* =================================================== */

void
ArcBall_Init (void)
{
  int i;

  center = qOne;
  radius = 1.0;
  vDown = vNow = qOne;
  qDown = qNow = qOne;
  for (i=15; i>=0; i--)
    ((double *)mNow)[i] = ((double *)mDown)[i] = ((double *)mId)[i];

  showResult = dragging = FALSE;
  axisSet = NoAxes;
  sets[CameraAxes] = mId[X];
  setSizes[CameraAxes] = 3;
  sets[BodyAxes] = mDown[X];
  setSizes[BodyAxes] = 3;
  sets[OtherAxes] = otherAxis[X];
  setSizes[OtherAxes] = 1;
}

/* Set the center and size of the controller. */
/* ========================================== */

void
ArcBall_Place (HVect  Center,
               double Radius)
{
  center = Center;
  radius = Radius;
}

/* Incorporate new mouse position. */
/* =============================== */

void
ArcBall_Mouse (HVect v_Now)
{
  vNow = v_Now;
}

/* Choose a constraint set, or none. */
/* ================================= */

void
ArcBall_UseSet (AxisSet axis_Set)
{
  if (!dragging) axisSet = axis_Set;
}

/* Using vDown, vNow, dragging, and axisSet, compute rotation etc. */
/* =============================================================== */

void
ArcBall_Update (void)
{
  int setSize = setSizes[axisSet];
  HVect *set = (HVect *)(sets[axisSet]);

  vFrom = MouseOnSphere(vDown, center, radius);
  vTo = MouseOnSphere(vNow, center, radius);
  if (dragging)
    {
      if (axisSet!=NoAxes)
        {
          vFrom = ConstrainToAxis(vFrom, set[axisIndex]);
          vTo = ConstrainToAxis(vTo, set[axisIndex]);
        }
      qDrag = Qt_FromBallPoints(vFrom, vTo);
      qNow = Qt_Mul(qDrag, qDown);
    }
  else
    {
      if (axisSet!=NoAxes) axisIndex = NearestConstraintAxis(vTo, set, setSize);
    }
  Qt_ToBallPoints(qDown, &vrFrom, &vrTo);
  Qt_ToMatrix(Qt_Conj(qNow), mNow); /* Gives transpose for GL. */
}

/* Return rotation matrix defined by controller use. */
/* ================================================= */

void
ArcBall_Value (HMatrix m_Now)
{
  ArcBall_CopyMat (mNow, m_Now);
}

/* Extract rotation angles from matrix */
/* =================================== */

void
ArcBall_Values (double *alpha,
                double *beta,
                double *gamma)
{
  if ((*beta=asin(-mNow[0][2]))!=0.0)
    {
      *gamma=atan2(mNow[1][2],mNow[2][2]);
      *alpha=atan2(mNow[0][1],mNow[0][0]);
    }
  else
    {
      *gamma=atan2(mNow[1][0],mNow[1][1]);
      *alpha=0.0;
    }
}

/* Begin drag sequence. */
/* ==================== */

void
ArcBall_BeginDrag (void)
{
  dragging = TRUE;
  vDown = vNow;
}

/* Stop drag sequence. */
/* =================== */

void
ArcBall_EndDrag (void)
{
  dragging = FALSE;
  qDown = qNow;

  ArcBall_CopyMat (mNow, mDown);
}

/*===================*/
/***** BallAux.c *****/
/*===================*/

/* 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.    */
/* ============================================================= */

static Quat
Qt_Mul (Quat qL,
        Quat qR)
{
  Quat qq;
  qq.w = qL.w*qR.w - qL.x*qR.x - qL.y*qR.y - qL.z*qR.z;
  qq.x = qL.w*qR.x + qL.x*qR.w + qL.y*qR.z - qL.z*qR.y;
  qq.y = qL.w*qR.y + qL.y*qR.w + qL.z*qR.x - qL.x*qR.z;
  qq.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.                             */
/* ============================================================== */

static void
Qt_ToMatrix (Quat    q,
             HMatrix out)
{
  double Nq = q.x*q.x + q.y*q.y + q.z*q.z + q.w*q.w;
  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 conjugate of quaternion. */
/* =============================== */

static Quat
Qt_Conj (Quat q)
{
  Quat qq;
  qq.x = -q.x; qq.y = -q.y; qq.z = -q.z; qq.w = q.w;
  return (qq);
}

/* Return vector formed from components */
/* ==================================== */

static HVect
V3_ (double x,
     double y,
     double z)
{
  HVect v;
  v.x = x; v.y = y; v.z = z; v.w = 0;
  return (v);
}

/* Return norm of v, defined as sum of squares of components */
/* ========================================================= */

static double
V3_Norm (HVect v)
{
  return ( v.x*v.x + v.y*v.y + v.z*v.z );
}

/* Return unit magnitude vector in direction of v */
/* ============================================== */

static HVect
V3_Unit (HVect v)
{
  static HVect u = {0, 0, 0, 0};
  double vlen = sqrt(V3_Norm(v));

  if (vlen != 0.0)
    {
      u.x = v.x/vlen;
      u.y = v.y/vlen;
      u.z = v.z/vlen;
    }
  return (u);
}

/* Return version of v scaled by s */
/* =============================== */

static HVect
V3_Scale (HVect v,
          double s)
{
  HVect u;
  u.x = s*v.x; u.y = s*v.y; u.z = s*v.z; u.w = v.w;
  return (u);
}

/* Return negative of v */
/* ==================== */

static HVect
V3_Negate (HVect v)
{
  static HVect u = {0, 0, 0, 0};
  u.x = -v.x; u.y = -v.y; u.z = -v.z;
  return (u);
}

/* Return sum of v1 and v2 */
/* ======================= */
/*
static HVect
V3_Add (HVect v1,
        HVect v2)
{
  static HVect v = {0, 0, 0, 0};
  v.x = v1.x+v2.x; v.y = v1.y+v2.y; v.z = v1.z+v2.z;
  return (v);
}
*/

/* Return difference of v1 minus v2 */
/* ================================ */

static HVect
V3_Sub (HVect v1,
        HVect v2)
{
  static HVect v = {0, 0, 0, 0};
  v.x = v1.x-v2.x; v.y = v1.y-v2.y; v.z = v1.z-v2.z;
  return (v);
}

/* Halve arc between unit vectors v0 and v1. */
/* ========================================= */
/*
static HVect
V3_Bisect (HVect v0,
           HVect v1)
{
  HVect v = {0, 0, 0, 0};
  double Nv;

  v = V3_Add(v0, v1);
  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 */
/* =============================== */

static double
V3_Dot (HVect v1,
        HVect v2)
{
  return (v1.x*v2.x + v1.y*v2.y + v1.z*v2.z);
}


/* Return cross product, v1 x v2 */
/* ============================= */
/*
static HVect
V3_Cross (HVect v1,
          HVect v2)
{
  static HVect v = {0, 0, 0, 0};
  v.x = v1.y*v2.z-v1.z*v2.y;
  v.y = v1.z*v2.x-v1.x*v2.z;
  v.z = v1.x*v2.y-v1.y*v2.x;
  return (v);
}
*/


void
ArcBall_CopyMat (HMatrix inm,
                 HMatrix outm)
{
  int x=0,y=0;

  for (x=0;x<4;x++)
    {
      for (y=0;y<4;y++)
        {
          outm[y][x]=inm[y][x];
        }
    }
}

/*=====================================================*/
/**** BallMath.c - Essential routines for ArcBall.  ****/
/*=====================================================*/

/* Convert window coordinates to sphere coordinates. */
/* ================================================= */

static HVect
MouseOnSphere (HVect  mouse,
               HVect  ballCenter,
               double ballRadius)
{
  HVect ballMouse;
  register double mag;

  ballMouse.x = (mouse.x - ballCenter.x) / ballRadius;
  ballMouse.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.x *= scale; ballMouse.y *= scale;
      ballMouse.z = 0.0;
    }
  else ballMouse.z = sqrt(1 - mag);
  ballMouse.w = 0.0;
  return (ballMouse);
}

/* Construct a unit quaternion from two points on unit sphere */
/* ========================================================== */

static Quat
Qt_FromBallPoints (HVect from,
                   HVect to)
{
  Quat qu;
  qu.x = from.y*to.z - from.z*to.y;
  qu.y = from.z*to.x - from.x*to.z;
  qu.z = from.x*to.y - from.y*to.x;
  qu.w = from.x*to.x + from.y*to.y + from.z*to.z;
  return (qu);
}

/* Convert a unit quaternion to two points on unit sphere */
/* ====================================================== */

static void
Qt_ToBallPoints (Quat   q,
                 HVect *arcFrom,
                 HVect *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->x = q.w*arcFrom->x - q.z*arcFrom->y;
  arcTo->y = q.w*arcFrom->y + q.z*arcFrom->x;
  arcTo->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. */
/* =============================================== */

static HVect
ConstrainToAxis (HVect loose,
                 HVect axis)
{
  HVect onPlane;
  register double norm;

  onPlane = V3_Sub(loose, V3_Scale(axis, V3_Dot(axis, loose)));
  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. */
/* ========================================== */

static int
NearestConstraintAxis (HVect  loose,
                       HVect *axes,
                       int    nAxes)
{
  HVect onPlane;
  register double 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);
}

Messung
CHZG
839710093

¤ Dauer der Verarbeitung: 0.6 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover


Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.