Graphviz 14.1.4~dev.20260320.0055
Loading...
Searching...
No Matches
arcball.c
Go to the documentation of this file.
1/*************************************************************************************/
23/*************************************************************************************/
24
25#include "config.h"
26
27#include <glcomp/glcompdefs.h>
28#include <math.h>
29#define ARCBALL_C
30#include "smyrnadefs.h"
31#include "arcball.h"
32
33static void setBounds(ArcBall_t *a, double NewWidth, double NewHeight) {
34 assert(NewWidth > 1.0 && NewHeight > 1.0);
35 //Set adjustment factor for width/height
36 a->AdjustWidth = 1.0 / ((NewWidth - 1.0) * 0.5);
37 a->AdjustHeight = 1.0 / ((NewHeight - 1.0) * 0.5);
38}
39
40static Vector3fT mapToSphere(ArcBall_t *a, const Point2fT *NewPt) {
41 Point2fT TempPt;
42
43 //Copy paramter into temp point
44 TempPt = *NewPt;
45
46 //Adjust point coords and scale down to range of [-1 ... 1]
47 TempPt.X = TempPt.X * a->AdjustWidth - 1.0;
48 TempPt.Y = 1.0 - TempPt.Y * a->AdjustHeight;
49
50 //Compute the square of the length of the vector to the point from the center
51 double length = TempPt.X * TempPt.X + TempPt.Y * TempPt.Y;
52
53 //If the point is mapped outside of the sphere... (length > radius squared)
54 if (length > 1.0) {
55
56 //Compute a normalizing factor (radius / sqrt(length))
57 double norm = 1.0 / sqrt(length);
58
59 //Return the "normalized" vector, a point on the sphere
60 return (Vector3fT){.X = TempPt.X * norm, .Y = TempPt.Y * norm};
61 } else //Else it's on the inside
62 {
63 //Return a vector to a point mapped inside the sphere sqrt(radius squared - length)
64 return (Vector3fT){.X = TempPt.X, .Y = TempPt.Y, .Z = sqrt(1.0 - length)};
65 }
66}
67
68static Matrix4fT Transform = { {1.0, 0, 0, 0, // NEW: Final Transform
69 0, 1.0, 0, 0,
70 0, 0, 1.0, 0,
71 0, 0, 0, 1.0}
72};
73
74static Matrix3fT LastRot = { {1.0, 0, 0, // NEW: Last Rotation
75 0, 1.0, 0,
76 0, 0, 1.0}
77};
78
79static Matrix3fT ThisRot = { {1.0, 0, 0, // NEW: This Rotation
80 0, 1.0, 0,
81 0, 0, 1.0}
82};
83
84//Create/Destroy
85ArcBall_t init_arcBall(double NewWidth, double NewHeight) {
86 ArcBall_t a = {.Transform = Transform, .LastRot = LastRot,
87 .ThisRot = ThisRot};
88
89 //Set initial bounds
90 setBounds(&a, NewWidth, NewHeight);
91 return a;
92}
93
94//Mouse down
95static void click(ArcBall_t * a, const Point2fT * NewPt)
96{
97 //Map the point to the sphere
98 a->StVec = mapToSphere(a, NewPt);
99}
100
101//Mouse drag, calculate rotation
102static Quat4fT drag(ArcBall_t *a, const Point2fT *NewPt) {
103 //Map the point to the sphere
104 a->EnVec = mapToSphere(a, NewPt);
105
106 //Return the quaternion equivalent to the rotation
107 // compute the vector perpendicular to the begin and end vectors
108 const Vector3fT Perp = Vector3fCross(a->StVec, a->EnVec);
109
110 // compute the length of the perpendicular vector
111 if (Vector3fLength(Perp) > Epsilon) { // if it’s non-zero
112 // we're OK, so return the perpendicular vector as the transform after
113 // all
114 return (Quat4fT){.X = Perp.X,
115 .Y = Perp.Y,
116 .Z = Perp.Z,
117 // in the quaternion values, W is cosine (theta / 2), where theta is
118 // rotation angle
119 .W = Vector3fDot(a->StVec, a->EnVec)};
120 } else { // if it’s zero
121 // the begin and end vectors coincide, so return an identity transform
122 return (Quat4fT){0};
123 }
124}
125
127{
128 view->arcball->isDragging = 1; // Prepare For Dragging
129 view->arcball->LastRot = view->arcball->ThisRot; // Set Last Static Rotation To Last Dynamic One
131
132}
133
134void arcmouseDrag(void)
135{
136 Quat4fT ThisQuat = drag(view->arcball, &view->arcball->MousePt);
137 view->arcball->ThisRot = Matrix3fSetRotationFromQuat4f(ThisQuat); // Convert Quaternion Into Matrix3fT
138 Matrix3fMulMatrix3f(&view->arcball->ThisRot, view->arcball->LastRot); // Accumulate Last Rotation Into This One
139 Matrix4fSetRotationFromMatrix3f(&view->arcball->Transform, &view->arcball->ThisRot); // Set Our Final Transform's Rotation From This One
140
141}
static void click(ArcBall_t *a, const Point2fT *NewPt)
Definition arcball.c:95
void arcmouseClick(void)
Definition arcball.c:126
void arcmouseDrag(void)
Definition arcball.c:134
ArcBall_t init_arcBall(double NewWidth, double NewHeight)
Definition arcball.c:85
static Matrix3fT LastRot
Definition arcball.c:74
static void setBounds(ArcBall_t *a, double NewWidth, double NewHeight)
Definition arcball.c:33
static Quat4fT drag(ArcBall_t *a, const Point2fT *NewPt)
Definition arcball.c:102
static Matrix3fT ThisRot
Definition arcball.c:79
static Matrix4fT Transform
Definition arcball.c:68
static Vector3fT mapToSphere(ArcBall_t *a, const Point2fT *NewPt)
Definition arcball.c:40
#define Quat4fT
Definition arcball.h:131
#define Epsilon
Definition arcball.h:137
#define Vector3fT
Definition arcball.h:133
#define Point2fT
Definition arcball.h:129
static Extype_t length(Exid_t *rhs, Exdisc_t *disc)
Definition compile.c:1615
static double norm(int n, const double *x)
ViewInfo * view
Definition viewport.c:40
double AdjustHeight
Definition arcball.h:418
Vector3fT EnVec
Definition arcball.h:416
Point2fT MousePt
Definition arcball.h:422
Matrix3fT LastRot
Definition arcball.h:420
double AdjustWidth
Definition arcball.h:417
Matrix3fT ThisRot
Definition arcball.h:421
Matrix4fT Transform
Definition arcball.h:419
int isDragging
Definition arcball.h:423
Vector3fT StVec
Definition arcball.h:415
ArcBall_t * arcball
Definition smyrnadefs.h:331