Graphviz 12.0.1~dev.20240716.0800
Loading...
Searching...
No Matches
arcball.c
Go to the documentation of this file.
1/*************************************************************************************/
23/*************************************************************************************/
24
25#include <glcomp/glcompdefs.h>
26#define ARCBALL_C
27#include "smyrnadefs.h"
28#include "arcball.h"
29
30static void setBounds(ArcBall_t *a, float NewWidth, float NewHeight) {
31 assert((NewWidth > 1.0f) && (NewHeight > 1.0f));
32 //Set adjustment factor for width/height
33 a->AdjustWidth = 1.0f / ((NewWidth - 1.0f) * 0.5f);
34 a->AdjustHeight = 1.0f / ((NewHeight - 1.0f) * 0.5f);
35}
36
37static void mapToSphere(ArcBall_t * a, const Point2fT * NewPt,
38 Vector3fT * NewVec)
39{
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.s.X = (TempPt.s.X * a->AdjustWidth) - 1.0f;
47 TempPt.s.Y = 1.0f - (TempPt.s.Y * a->AdjustHeight);
48
49 //Compute the square of the length of the vector to the point from the center
50 float length = TempPt.s.X * TempPt.s.X + TempPt.s.Y * TempPt.s.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 NewVec->s.X = TempPt.s.X * norm;
60 NewVec->s.Y = TempPt.s.Y * norm;
61 NewVec->s.Z = 0.0f;
62 } else //Else it's on the inside
63 {
64 //Return a vector to a point mapped inside the sphere sqrt(radius squared - length)
65 NewVec->s.X = TempPt.s.X;
66 NewVec->s.Y = TempPt.s.Y;
67 NewVec->s.Z = FuncSqrt(1.0f - length);
68 }
69}
70
71static Matrix4fT Transform = { {1.0f, 0.0f, 0.0f, 0.0f, // NEW: Final Transform
72 0.0f, 1.0f, 0.0f, 0.0f,
73 0.0f, 0.0f, 1.0f, 0.0f,
74 0.0f, 0.0f, 0.0f, 1.0f}
75};
76
77static Matrix3fT LastRot = { {1.0f, 0.0f, 0.0f, // NEW: Last Rotation
78 0.0f, 1.0f, 0.0f,
79 0.0f, 0.0f, 1.0f}
80};
81
82static Matrix3fT ThisRot = { {1.0f, 0.0f, 0.0f, // NEW: This Rotation
83 0.0f, 1.0f, 0.0f,
84 0.0f, 0.0f, 1.0f}
85};
86
87//Create/Destroy
88void init_arcBall(ArcBall_t *a, float NewWidth, float NewHeight) {
90 a->LastRot = LastRot;
91 a->ThisRot = ThisRot;
92 //Clear initial values
93 a->StVec.s.X =
94 a->StVec.s.Y =
95 a->StVec.s.Z = a->EnVec.s.X = a->EnVec.s.Y = a->EnVec.s.Z = 0.0f;
96
97 //Set initial bounds
98 setBounds(a, NewWidth, NewHeight);
99
100 a->isClicked = 0;
101 a->isRClicked = 0;
102 a->isDragging = 0;
103}
104
105//Mouse down
106static void click(ArcBall_t * a, const Point2fT * NewPt)
107{
108 //Map the point to the sphere
109 mapToSphere(a, NewPt, &a->StVec);
110}
111
112//Mouse drag, calculate rotation
113static void drag(ArcBall_t * a, const Point2fT * NewPt, Quat4fT * NewRot)
114{
115 //Map the point to the sphere
116 mapToSphere(a, NewPt, &a->EnVec);
117
118 //Return the quaternion equivalent to the rotation
119 if (NewRot) {
120 Vector3fT Perp;
121
122 //Compute the vector perpendicular to the begin and end vectors
123 Vector3fCross(&Perp, &a->StVec, &a->EnVec);
124
125 //Compute the length of the perpendicular vector
126 if (Vector3fLength(&Perp) > Epsilon) //if its non-zero
127 {
128 //We're ok, so return the perpendicular vector as the transform after all
129 NewRot->s.X = Perp.s.X;
130 NewRot->s.Y = Perp.s.Y;
131 NewRot->s.Z = Perp.s.Z;
132 //In the quaternion values, w is cosine (theta / 2), where theta is rotation angle
133 NewRot->s.W = Vector3fDot(&a->StVec, &a->EnVec);
134 } else //if its zero
135 {
136 //The begin and end vectors coincide, so return an identity transform
137 NewRot->s.X = NewRot->s.Y = NewRot->s.Z = NewRot->s.W = 0.0f;
138 }
139 }
140}
141
143{
144 view->arcball->isDragging = 1; // Prepare For Dragging
145 view->arcball->LastRot = view->arcball->ThisRot; // Set Last Static Rotation To Last Dynamic One
147
148}
149
150void arcmouseDrag(void)
151{
152 Quat4fT ThisQuat;
153 drag(view->arcball, &view->arcball->MousePt, &ThisQuat);
154 Matrix3fSetRotationFromQuat4f(&view->arcball->ThisRot, &ThisQuat); // Convert Quaternion Into Matrix3fT
155 Matrix3fMulMatrix3f(&view->arcball->ThisRot, &view->arcball->LastRot); // Accumulate Last Rotation Into This One
156 Matrix4fSetRotationFromMatrix3f(&view->arcball->Transform, &view->arcball->ThisRot); // Set Our Final Transform's Rotation From This One
157
158}
static void click(ArcBall_t *a, const Point2fT *NewPt)
Definition arcball.c:106
static void mapToSphere(ArcBall_t *a, const Point2fT *NewPt, Vector3fT *NewVec)
Definition arcball.c:37
void arcmouseClick(void)
Definition arcball.c:142
void arcmouseDrag(void)
Definition arcball.c:150
static void drag(ArcBall_t *a, const Point2fT *NewPt, Quat4fT *NewRot)
Definition arcball.c:113
static void setBounds(ArcBall_t *a, float NewWidth, float NewHeight)
Definition arcball.c:30
static Matrix3fT LastRot
Definition arcball.c:77
void init_arcBall(ArcBall_t *a, float NewWidth, float NewHeight)
Definition arcball.c:88
static Matrix3fT ThisRot
Definition arcball.c:82
static Matrix4fT Transform
Definition arcball.c:71
#define Quat4fT
Definition arcball.h:200
#define Epsilon
Definition arcball.h:210
#define FuncSqrt
Definition arcball.h:206
#define Vector3fT
Definition arcball.h:203
#define Point2fT
Definition arcball.h:198
static double norm(int n, const double *x)
ViewInfo * view
Definition viewport.c:38
Vector3fT EnVec
Definition arcball.h:545
Point2fT MousePt
Definition arcball.h:551
Matrix3fT LastRot
Definition arcball.h:549
Matrix3fT ThisRot
Definition arcball.h:550
Matrix4fT Transform
Definition arcball.h:548
float AdjustWidth
Definition arcball.h:546
int isDragging
Definition arcball.h:554
int isClicked
Definition arcball.h:552
float AdjustHeight
Definition arcball.h:547
int isRClicked
Definition arcball.h:553
Vector3fT StVec
Definition arcball.h:544
ArcBall_t * arcball
Definition smyrnadefs.h:365