~ubuntu-branches/ubuntu/precise/graphviz/precise-security

« back to all changes in this revision

Viewing changes to cmd/smyrna/arcball.c

  • Committer: Bazaar Package Importer
  • Author(s): David Claughton
  • Date: 2010-03-24 22:45:18 UTC
  • mfrom: (1.2.7 upstream) (6.1.7 sid)
  • Revision ID: james.westby@ubuntu.com-20100324224518-do441tthbqjaqjzd
Tags: 2.26.3-4
Add patch to fix segfault in circo. Backported from upstream snapshot
release.  Thanks to Francis Russell for his work on this.
(Closes: #575255)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Id: arcball.c,v 1.6 2009/12/03 19:16:04 arif Exp $Revision: */
 
2
/* vim:set shiftwidth=4 ts=8: */
 
3
 
 
4
/*************************************************************************************/
 
5
/**                                                                                 **/
 
6
/** Copyright (c) 1999-2009 Tatewake.com                                            **/
 
7
/**                                                                                 **/
 
8
/** Permission is hereby granted, free of charge, to any person obtaining a copy    **/
 
9
/** of this software and associated documentation files (the "Software"), to deal   **/
 
10
/** in the Software without restriction, including without limitation the rights    **/
 
11
/** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell       **/
 
12
/** copies of the Software, and to permit persons to whom the Software is           **/
 
13
/** furnished to do so, subject to the following conditions:                        **/
 
14
/**                                                                                 **/
 
15
/** The above copyright notice and this permission notice shall be included in      **/
 
16
/** all copies or substantial portions of the Software.                             **/
 
17
/**                                                                                 **/
 
18
/** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR      **/
 
19
/** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,        **/
 
20
/** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE     **/
 
21
/** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER          **/
 
22
/** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,   **/
 
23
/** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN       **/
 
24
/** THE SOFTWARE.                                                                   **/
 
25
/**                                                                                 **/
 
26
/*************************************************************************************/
 
27
 
 
28
#include "glcompdefs.h"
 
29
#define ARCBALL_C
 
30
#include "smyrnadefs.h"
 
31
#include "arcball.h"
 
32
 
 
33
static void setBounds(ArcBall_t * a, GLfloat NewWidth, GLfloat NewHeight)
 
34
{
 
35
    assert((NewWidth > 1.0f) && (NewHeight > 1.0f));
 
36
    //Set adjustment factor for width/height
 
37
    a->AdjustWidth = 1.0f / ((NewWidth - 1.0f) * 0.5f);
 
38
    a->AdjustHeight = 1.0f / ((NewHeight - 1.0f) * 0.5f);
 
39
}
 
40
 
 
41
static void mapToSphere(ArcBall_t * a, const Point2fT * NewPt,
 
42
                        Vector3fT * NewVec)
 
43
{
 
44
    Point2fT TempPt;
 
45
    GLfloat length;
 
46
 
 
47
    //Copy paramter into temp point
 
48
    TempPt = *NewPt;
 
49
 
 
50
    //Adjust point coords and scale down to range of [-1 ... 1]
 
51
    TempPt.s.X = (TempPt.s.X * a->AdjustWidth) - 1.0f;
 
52
    TempPt.s.Y = 1.0f - (TempPt.s.Y * a->AdjustHeight);
 
53
 
 
54
    //Compute the square of the length of the vector to the point from the center
 
55
    length = (TempPt.s.X * TempPt.s.X) + (TempPt.s.Y * TempPt.s.Y);
 
56
 
 
57
    //If the point is mapped outside of the sphere... (length > radius squared)
 
58
    if (length > 1.0f) {
 
59
        GLfloat norm;
 
60
 
 
61
        //Compute a normalizing factor (radius / sqrt(length))
 
62
        norm = 1.0f / FuncSqrt(length);
 
63
 
 
64
        //Return the "normalized" vector, a point on the sphere
 
65
        NewVec->s.X = TempPt.s.X * norm;
 
66
        NewVec->s.Y = TempPt.s.Y * norm;
 
67
        NewVec->s.Z = 0.0f;
 
68
    } else                      //Else it's on the inside
 
69
    {
 
70
        //Return a vector to a point mapped inside the sphere sqrt(radius squared - length)
 
71
        NewVec->s.X = TempPt.s.X;
 
72
        NewVec->s.Y = TempPt.s.Y;
 
73
        NewVec->s.Z = FuncSqrt(1.0f - length);
 
74
    }
 
75
}
 
76
 
 
77
static Matrix4fT Transform = { {1.0f, 0.0f, 0.0f, 0.0f, // NEW: Final Transform
 
78
                                0.0f, 1.0f, 0.0f, 0.0f,
 
79
                                0.0f, 0.0f, 1.0f, 0.0f,
 
80
                                0.0f, 0.0f, 0.0f, 1.0f}
 
81
};
 
82
 
 
83
static Matrix3fT LastRot = { {1.0f, 0.0f, 0.0f, // NEW: Last Rotation
 
84
                              0.0f, 1.0f, 0.0f,
 
85
                              0.0f, 0.0f, 1.0f}
 
86
};
 
87
 
 
88
static Matrix3fT ThisRot = { {1.0f, 0.0f, 0.0f, // NEW: This Rotation
 
89
                              0.0f, 1.0f, 0.0f,
 
90
                              0.0f, 0.0f, 1.0f}
 
91
};
 
92
 
 
93
//Create/Destroy
 
94
void init_arcBall(ArcBall_t * a, GLfloat NewWidth, GLfloat NewHeight)
 
95
{
 
96
    a->Transform = Transform;
 
97
    a->LastRot = LastRot;
 
98
    a->ThisRot = ThisRot;
 
99
    //Clear initial values
 
100
    a->StVec.s.X =
 
101
        a->StVec.s.Y =
 
102
        a->StVec.s.Z = a->EnVec.s.X = a->EnVec.s.Y = a->EnVec.s.Z = 0.0f;
 
103
 
 
104
    //Set initial bounds
 
105
    setBounds(a, NewWidth, NewHeight);
 
106
 
 
107
    a->isClicked = 0;
 
108
    a->isRClicked = 0;
 
109
    a->isDragging = 0;
 
110
}
 
111
 
 
112
//Mouse down
 
113
static void click(ArcBall_t * a, const Point2fT * NewPt)
 
114
{
 
115
    //Map the point to the sphere
 
116
    mapToSphere(a, NewPt, &a->StVec);
 
117
}
 
118
 
 
119
//Mouse drag, calculate rotation
 
120
static void drag(ArcBall_t * a, const Point2fT * NewPt, Quat4fT * NewRot)
 
121
{
 
122
    //Map the point to the sphere
 
123
    mapToSphere(a, NewPt, &a->EnVec);
 
124
 
 
125
    //Return the quaternion equivalent to the rotation
 
126
    if (NewRot) {
 
127
        Vector3fT Perp;
 
128
 
 
129
        //Compute the vector perpendicular to the begin and end vectors
 
130
        Vector3fCross(&Perp, &a->StVec, &a->EnVec);
 
131
 
 
132
        //Compute the length of the perpendicular vector
 
133
        if (Vector3fLength(&Perp) > Epsilon)    //if its non-zero
 
134
        {
 
135
            //We're ok, so return the perpendicular vector as the transform after all
 
136
            NewRot->s.X = Perp.s.X;
 
137
            NewRot->s.Y = Perp.s.Y;
 
138
            NewRot->s.Z = Perp.s.Z;
 
139
            //In the quaternion values, w is cosine (theta / 2), where theta is rotation angle
 
140
            NewRot->s.W = Vector3fDot(&a->StVec, &a->EnVec);
 
141
        } else                  //if its zero
 
142
        {
 
143
            //The begin and end vectors coincide, so return an identity transform
 
144
            NewRot->s.X = NewRot->s.Y = NewRot->s.Z = NewRot->s.W = 0.0f;
 
145
        }
 
146
    }
 
147
}
 
148
 
 
149
#ifdef UNUSED
 
150
static void arcmouseRClick(ViewInfo * v)
 
151
{
 
152
    Matrix3fSetIdentity(&view->arcball->LastRot);       // Reset Rotation
 
153
    Matrix3fSetIdentity(&view->arcball->ThisRot);       // Reset Rotation
 
154
    Matrix4fSetRotationFromMatrix3f(&view->arcball->Transform, &view->arcball->ThisRot);        // Reset Rotation
 
155
 
 
156
}
 
157
#endif
 
158
 
 
159
void arcmouseClick(ViewInfo * v)
 
160
{
 
161
    view->arcball->isDragging = 1;      // Prepare For Dragging
 
162
    view->arcball->LastRot = view->arcball->ThisRot;    // Set Last Static Rotation To Last Dynamic One
 
163
    click(view->arcball, &view->arcball->MousePt);
 
164
//    printf ("arcmouse click \n");
 
165
 
 
166
}
 
167
 
 
168
void arcmouseDrag(ViewInfo * v)
 
169
{
 
170
    Quat4fT ThisQuat;
 
171
    drag(view->arcball, &view->arcball->MousePt, &ThisQuat);
 
172
    Matrix3fSetRotationFromQuat4f(&view->arcball->ThisRot, &ThisQuat);  // Convert Quaternion Into Matrix3fT
 
173
    Matrix3fMulMatrix3f(&view->arcball->ThisRot, &view->arcball->LastRot);      // Accumulate Last Rotation Into This One
 
174
    Matrix4fSetRotationFromMatrix3f(&view->arcball->Transform, &view->arcball->ThisRot);        // Set Our Final Transform's Rotation From This One
 
175
 
 
176
}
 
177
 
 
178
#ifdef UNUSED
 
179
void Update(ViewInfo * view)
 
180
{
 
181
 
 
182
    if (view->arcball->isRClicked)      // If Right Mouse Clicked, Reset All Rotations
 
183
    {
 
184
        Matrix3fSetIdentity(&view->arcball->LastRot);   // Reset Rotation
 
185
        Matrix3fSetIdentity(&view->arcball->ThisRot);   // Reset Rotation
 
186
        Matrix4fSetRotationFromMatrix3f(&view->arcball->Transform, &view->arcball->ThisRot);    // Reset Rotation
 
187
    }
 
188
 
 
189
    if (!view->arcball->isDragging)     // Not Dragging
 
190
    {
 
191
        if (view->arcball->isClicked)   // First Click
 
192
        {
 
193
            view->arcball->isDragging = 1;      // Prepare For Dragging
 
194
            view->arcball->LastRot = view->arcball->ThisRot;    // Set Last Static Rotation To Last Dynamic One
 
195
            click(view->arcball, &view->arcball->MousePt);
 
196
        }
 
197
    } else {
 
198
        if (view->arcball->isClicked)   // Still Clicked, So Still Dragging
 
199
        {
 
200
            Quat4fT ThisQuat;
 
201
 
 
202
            drag(view->arcball, &view->arcball->MousePt, &ThisQuat);
 
203
            Matrix3fSetRotationFromQuat4f(&view->arcball->ThisRot, &ThisQuat);  // Convert Quaternion Into Matrix3fT
 
204
            Matrix3fMulMatrix3f(&view->arcball->ThisRot, &view->arcball->LastRot);      // Accumulate Last Rotation Into This One
 
205
            Matrix4fSetRotationFromMatrix3f(&view->arcball->Transform, &view->arcball->ThisRot);        // Set Our Final Transform's Rotation From This One
 
206
        } else                  // No Longer Dragging
 
207
            view->arcball->isDragging = 0;
 
208
    }
 
209
}
 
210
#endif