-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathProjector.cc
130 lines (99 loc) · 3.04 KB
/
Projector.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
// Projector.cc Classes for easily simulating OpenGL
// projection/unprojection
// created 5/5/99 [email protected]
#include "Projector.h"
#include "Trackball.h"
#include "TbObj.h"
#include "plvGlobals.h"
// these variables are declared and initialized in plvAnalyze.cc
extern unsigned int g_zbufferMaxUI;
extern float g_zbufferMaxF;
Projector::Projector (Trackball* tb, TbObj* tbobj)
{
// Some naughty clients of this code try to initialize a Projector
// before there's an OpenGL context (e.g. during static variable
// initialization). Some OpenGL implementations don't appreciate
// our trying to run OpenGL commands at this time, so try to prevent this...
if (!g_glVersion)
return;
GLdouble model[16], proj[16];
glGetDoublev(GL_PROJECTION_MATRIX, proj); // current GL state
int vp[4];
glGetIntegerv(GL_VIEWPORT, vp);
width = vp[2]; height = vp[3];
int matrixMode;
glGetIntegerv (GL_MATRIX_MODE, &matrixMode);
glMatrixMode (GL_MODELVIEW);
glPushMatrix();
if (tb || tbobj) { // if both NULL, use current state
// things that want true identity modelview have to set it that way
// themselves, then call with both tb and tbobj NULL
glLoadIdentity ();
if (tb)
tb->applyXform();
if (tbobj)
tbobj->gl_xform();
}
glGetDoublev(GL_MODELVIEW_MATRIX, model); // applied from trackball
glPopMatrix();
glMatrixMode ((GLenum) matrixMode);
xfForward = Xform<float>(proj) * Xform<float>(model);
}
Pnt3
Projector::operator() (const Pnt3& world) const
{
Pnt3 screen = world;
xfForward (screen);
float winX = width * (screen[0] + 1) / 2;
float winY = height * (screen[1] + 1) / 2;
float winZ = (screen[2] + 1) / 2;
return Pnt3 (winX, winY, winZ);
}
void
Projector::xformBy (const Xform<float>& xfRel)
{
// BUGBUG suspect code! needs testing.
xfForward = xfForward * xfRel;
}
//////////////////////////////////////////////////////////////////////
//
// Unprojector
//
//////////////////////////////////////////////////////////////////////
Unprojector::Unprojector (Trackball* tb, TbObj* tbobj)
: Projector (tb, tbobj)
{
xfBack = xfForward;
xfBack.invert();
}
Pnt3
Unprojector::operator() (int x, int y, unsigned int z) const
{
float tx = (2. * x / width) - 1;
float ty = (2. * y / height) - 1;
// The line below used to just say (2. * z / (float) g_zbufferMaxUI),
// but MSVC++ v.6 does the wrong thing without the extra parens! -- DRK
float tz = (2. * z / ((float)g_zbufferMaxUI)) - 1;
return xfBack.unproject (tx, ty, tz);
}
Pnt3
Unprojector::operator() (int x, int y, float z) const
{
float tx = (2. * x / width) - 1;
float ty = (2. * y / height) - 1;
float tz = (2. * z / g_zbufferMaxF) - 1;
return xfBack.unproject (tx, ty, tz);
}
Pnt3
Unprojector::forward (const Pnt3& world) const
{
return Projector::operator() (world);
}
void
Unprojector::xformBy (const Xform<float>& xfRel)
{
Projector::xformBy (xfRel);
// BUGBUG suspect code! needs testing.
Xform<float> xfRelInv = xfRel; xfRelInv.invert();
xfBack = xfRelInv * xfBack;
}