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