3 |
#include <sstream> |
#include <sstream> |
4 |
|
|
5 |
/* define positions of tracked matrices inside the NV vertex program registers */ |
/* define positions of tracked matrices inside the NV vertex program registers */ |
6 |
#define m_p_addr 0 // product of projection and modelview matrices |
#define m_p_addr 0 // product of projection and modelview matrices |
7 |
#define paper_addr 4 // object-to-paper-coordinate mapping matrix |
#define paper_addr 4 // object-to-paper-coordinate mapping matrix |
8 |
|
|
9 |
|
/* the matrix that maps v[TEX0] into o[TEXi] is stored starting at c[tex_addr_base + 4*i] */ |
10 |
|
#define tex_addr_base 60 // texture matrix |
11 |
|
|
12 |
namespace Paper { |
namespace Paper { |
13 |
TexGen::TexGen(const float *tex_mat) { |
TexGen::TexGen(const float *tex_mat) { |
14 |
svec[0] = tex_mat[0]; |
this->tex_mat[0] = tex_mat[0]; |
15 |
svec[1] = tex_mat[1]; |
this->tex_mat[1] = tex_mat[1]; |
16 |
svec[2] = tex_mat[2]; |
this->tex_mat[2] = tex_mat[2]; |
17 |
svec[3] = tex_mat[3]; |
this->tex_mat[3] = tex_mat[3]; |
18 |
|
|
19 |
tvec[0] = tex_mat[4]; |
this->tex_mat[4] = tex_mat[4]; |
20 |
tvec[1] = tex_mat[5]; |
this->tex_mat[5] = tex_mat[5]; |
21 |
tvec[2] = tex_mat[6]; |
this->tex_mat[6] = tex_mat[6]; |
22 |
tvec[3] = tex_mat[7]; |
this->tex_mat[7] = tex_mat[7]; |
23 |
|
|
24 |
rvec[0] = tex_mat[8]; |
this->tex_mat[8] = tex_mat[8]; |
25 |
rvec[1] = tex_mat[9]; |
this->tex_mat[9] = tex_mat[9]; |
26 |
rvec[2] = tex_mat[10]; |
this->tex_mat[10] = tex_mat[10]; |
27 |
rvec[3] = tex_mat[11]; |
this->tex_mat[11] = tex_mat[11]; |
28 |
|
|
29 |
qvec[0] = 0; |
this->tex_mat[12] = 0; |
30 |
qvec[0] = 0; |
this->tex_mat[13] = 0; |
31 |
qvec[0] = 0; |
this->tex_mat[14] = 0; |
32 |
qvec[0] = 1; |
this->tex_mat[15] = 1; |
33 |
} |
} |
34 |
|
|
35 |
void TexGen::setUpVP(int unit, LightParam * param) { |
void TexGen::setUpVP(int unit, LightParam * param) { |
36 |
// XXX: This could also be implemented as CallGL code |
// XXX: This could also be implemented as CallGL code |
37 |
#ifdef GL_VERTEX_PROGRAM_NV |
#ifdef GL_VERTEX_PROGRAM_NV |
38 |
GLuint base = unit * 4 + 60; |
GLuint base = unit * 4 + tex_addr_base; |
39 |
glProgramParameter4fvNV(GL_VERTEX_PROGRAM_NV, base + 0, svec); |
glProgramParameter4fvNV(GL_VERTEX_PROGRAM_NV, base + 0, tex_mat); |
40 |
glProgramParameter4fvNV(GL_VERTEX_PROGRAM_NV, base + 1, tvec); |
glProgramParameter4fvNV(GL_VERTEX_PROGRAM_NV, base + 1, tex_mat + 4); |
41 |
glProgramParameter4fvNV(GL_VERTEX_PROGRAM_NV, base + 2, rvec); |
glProgramParameter4fvNV(GL_VERTEX_PROGRAM_NV, base + 2, tex_mat + 8); |
42 |
glProgramParameter4fvNV(GL_VERTEX_PROGRAM_NV, base + 3, qvec); |
glProgramParameter4fvNV(GL_VERTEX_PROGRAM_NV, base + 3, tex_mat + 12); |
43 |
#endif |
#endif |
44 |
} |
} |
45 |
|
|
46 |
string TexGen::getVPCode(int unit) { |
string TexGen::getVPCode(int unit) { |
|
GLuint base = unit * 4 + 60; |
|
|
|
|
47 |
std::ostringstream code; |
std::ostringstream code; |
48 |
|
|
49 |
|
GLuint base = unit * 4 + tex_addr_base; |
50 |
code << "DP4 o[TEX" << unit << "].x, c[" << base + 0 << "], v[TEX0]\n" |
code << "DP4 o[TEX" << unit << "].x, c[" << base + 0 << "], v[TEX0]\n" |
51 |
<< "DP4 o[TEX" << unit << "].y, c[" << base + 1 << "], v[TEX0]\n" |
<< "DP4 o[TEX" << unit << "].y, c[" << base + 1 << "], v[TEX0]\n" |
52 |
<< "DP4 o[TEX" << unit << "].z, c[" << base + 2 << "], v[TEX0]\n" |
<< "DP4 o[TEX" << unit << "].z, c[" << base + 2 << "], v[TEX0]\n" |
67 |
|
|
68 |
glEnable(GL_TEXTURE_2D); |
glEnable(GL_TEXTURE_2D); |
69 |
glTexGenf(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); |
glTexGenf(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); |
70 |
glTexGenfv(GL_S, GL_EYE_PLANE, svec); |
glTexGenfv(GL_S, GL_EYE_PLANE, tex_mat); |
71 |
glTexGenf(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); |
glTexGenf(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); |
72 |
glTexGenfv(GL_T, GL_EYE_PLANE, tvec); |
glTexGenfv(GL_T, GL_EYE_PLANE, tex_mat + 4); |
73 |
glTexGenf(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); |
glTexGenf(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); |
74 |
glTexGenfv(GL_R, GL_EYE_PLANE, rvec); |
glTexGenfv(GL_R, GL_EYE_PLANE, tex_mat + 8); |
75 |
glEnable(GL_TEXTURE_GEN_S); |
glEnable(GL_TEXTURE_GEN_S); |
76 |
glEnable(GL_TEXTURE_GEN_T); |
glEnable(GL_TEXTURE_GEN_T); |
77 |
glEnable(GL_TEXTURE_GEN_R); |
glEnable(GL_TEXTURE_GEN_R); |
78 |
glPopMatrix(); |
glPopMatrix(); |
79 |
} |
} |
80 |
|
|
81 |
void TexGenEmboss::setUpVP(int unit, LightParam * param) { |
void TexGenEmboss::setUpVP(int unit, LightParam *param) { |
82 |
TexGen::setUpVP(unit, param); |
// Suppose |
83 |
|
// x = vertex position |
84 |
|
// p = paper coordinates |
85 |
|
// s = texture coordinates |
86 |
|
// A = paper-to-vertex mapping |
87 |
|
// E = embossing mapping (translates x towards light) |
88 |
|
// M = modelview matrix |
89 |
|
// T = texture matrix |
90 |
|
// |
91 |
|
// The usual eye-linear embossing texgen computes |
92 |
|
// s' = Tp' = T((MEA)^-1 M x) = T(A^-1 E^-1 x) |
93 |
|
// The usual simple texgen computes |
94 |
|
// s = Tp = T((MA)^-1 M x) = T(A^-1 x) ==> x = Ap |
95 |
|
// Thus, the mapping from p to s' is |
96 |
|
// s' = Tp' = T(A^-1 E^-1 x) = T A^-1 E^-1 A p |
97 |
|
// |
98 |
|
// The following code computes T A^-1 E^-1 A and stores it |
99 |
|
// in place of T in the constant registers |
100 |
|
|
101 |
float mat0[16]; |
GLuint base = unit * 4 + tex_addr_base; |
|
glGetFloatv(GL_MODELVIEW_MATRIX, mat0); |
|
102 |
|
|
103 |
float mat[16] = { param->e0.x, param->e0.y, param->e0.z, 0, |
glMatrixMode(GL_MATRIX0_NV); |
104 |
param->e1.x, param->e1.y, param->e1.z, 0, |
glLoadIdentity(); |
|
param->e2.x, param->e2.y, param->e2.z, 0, |
|
|
param->orig.x, param->orig.y, param->orig.z, 1 }; |
|
|
|
|
|
glMatrixMode(GL_MATRIX0_NV); |
|
|
glLoadMatrixf(mat0); |
|
|
glMultMatrixf(mat); |
|
|
glMatrixMode(GL_MODELVIEW); |
|
105 |
|
|
106 |
glTrackMatrixNV(GL_VERTEX_PROGRAM_NV, paper_addr, GL_MATRIX0_NV, GL_INVERSE_TRANSPOSE_NV); |
float eps = this->eps * param->e2.dot(param->e2) |
107 |
|
/ (param->Light - param->Light_w * param->orig).dot(param->e2); |
108 |
|
|
109 |
|
glTranslatef(eps * param->Light.x, eps * param->Light.y, eps * param->Light.z); |
110 |
|
float s = 1 - param->Light_w * eps; |
111 |
|
glScalef(s, s, s); |
112 |
|
|
113 |
|
float mat[16] = { param->e0.x, param->e0.y, param->e0.z, 0, |
114 |
|
param->e1.x, param->e1.y, param->e1.z, 0, |
115 |
|
param->e2.x, param->e2.y, param->e2.z, 0, |
116 |
|
param->orig.x, param->orig.y, param->orig.z, 1 }; |
117 |
|
|
118 |
} |
glMultMatrixf(mat); |
|
|
|
119 |
|
|
120 |
string TexGenEmboss::getVPCode(int unit) { |
// Hack for easily inverting the matrix |
121 |
GLuint base = unit * 4 + 60; |
glTrackMatrixNV(GL_VERTEX_PROGRAM_NV, base, GL_MATRIX0_NV, GL_INVERSE_NV); |
122 |
|
glTrackMatrixNV(GL_VERTEX_PROGRAM_NV, base, GL_NONE, GL_INVERSE_NV); |
123 |
std::ostringstream code; |
float foo[16]; |
124 |
|
glGetProgramParameterfvNV(GL_VERTEX_PROGRAM_NV, base + 0, GL_PROGRAM_PARAMETER_NV, foo); |
125 |
|
glGetProgramParameterfvNV(GL_VERTEX_PROGRAM_NV, base + 1, GL_PROGRAM_PARAMETER_NV, foo + 4); |
126 |
|
glGetProgramParameterfvNV(GL_VERTEX_PROGRAM_NV, base + 2, GL_PROGRAM_PARAMETER_NV, foo + 8); |
127 |
|
glGetProgramParameterfvNV(GL_VERTEX_PROGRAM_NV, base + 3, GL_PROGRAM_PARAMETER_NV, foo + 12); |
128 |
|
glLoadMatrixf(foo); |
129 |
|
|
130 |
code << "DP4 o[TEX" << unit << "].x, c[" << base + 0 << "], v[TEX0]\n" |
glMultMatrixf(mat); |
|
<< "DP4 o[TEX" << unit << "].y, c[" << base + 1 << "], v[TEX0]\n" |
|
|
<< "DP4 o[TEX" << unit << "].z, c[" << base + 2 << "], v[TEX0]\n" |
|
|
<< "DP4 o[TEX" << unit << "].w, c[" << base + 3 << "], v[TEX0]\n"; |
|
131 |
|
|
132 |
// XXX: compute embossing shift |
glMultMatrixf(tex_mat); |
133 |
|
|
134 |
return code.str(); |
// Load the current matrix in c[base:base+4] |
135 |
} |
glTrackMatrixNV(GL_VERTEX_PROGRAM_NV, base, GL_MATRIX0_NV, GL_IDENTITY_NV); |
136 |
|
glTrackMatrixNV(GL_VERTEX_PROGRAM_NV, base, GL_NONE, GL_IDENTITY_NV); |
137 |
|
|
138 |
|
glMatrixMode(GL_MODELVIEW); |
139 |
|
|
140 |
|
} |
141 |
|
|
142 |
|
|
143 |
void TexGenEmboss::setUp(LightParam *param) { |
void TexGenEmboss::setUp(LightParam *param) { |
144 |
glMatrixMode(GL_MODELVIEW); |
glMatrixMode(GL_MODELVIEW); |
159 |
|
|
160 |
glEnable(GL_TEXTURE_2D); |
glEnable(GL_TEXTURE_2D); |
161 |
glTexGenf(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); |
glTexGenf(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); |
162 |
glTexGenfv(GL_S, GL_EYE_PLANE, svec); |
glTexGenfv(GL_S, GL_EYE_PLANE, tex_mat); |
163 |
glTexGenf(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); |
glTexGenf(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); |
164 |
glTexGenfv(GL_T, GL_EYE_PLANE, tvec); |
glTexGenfv(GL_T, GL_EYE_PLANE, tex_mat + 4); |
165 |
glEnable(GL_TEXTURE_GEN_S); |
glEnable(GL_TEXTURE_GEN_S); |
166 |
glEnable(GL_TEXTURE_GEN_T); |
glEnable(GL_TEXTURE_GEN_T); |
167 |
glPopMatrix(); |
glPopMatrix(); |
201 |
|
|
202 |
glEnable(GL_TEXTURE_2D); |
glEnable(GL_TEXTURE_2D); |
203 |
glTexGenf(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); |
glTexGenf(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); |
204 |
glTexGenfv(GL_S, GL_EYE_PLANE, svec); |
glTexGenfv(GL_S, GL_EYE_PLANE, tex_mat); |
205 |
glTexGenf(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); |
glTexGenf(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); |
206 |
glTexGenfv(GL_T, GL_EYE_PLANE, tvec); |
glTexGenfv(GL_T, GL_EYE_PLANE, tex_mat + 4); |
207 |
glEnable(GL_TEXTURE_GEN_S); |
glEnable(GL_TEXTURE_GEN_S); |
208 |
glEnable(GL_TEXTURE_GEN_T); |
glEnable(GL_TEXTURE_GEN_T); |
209 |
glPopMatrix(); |
glPopMatrix(); |
273 |
loadVP(); |
loadVP(); |
274 |
|
|
275 |
/* Track the product of modelview and projection matrices */ |
/* Track the product of modelview and projection matrices */ |
276 |
glTrackMatrixNV(GL_VERTEX_PROGRAM_NV, m_p_addr, GL_MATRIX0_NV, GL_MODELVIEW_PROJECTION_NV); |
glTrackMatrixNV(GL_VERTEX_PROGRAM_NV, m_p_addr, GL_MODELVIEW_PROJECTION_NV, GL_IDENTITY_NV); |
277 |
|
|
278 |
/* Set up VP TexGen parameters for each texture unit */ |
/* Set up VP TexGen parameters for each texture unit */ |
279 |
int unit = 0; |
int unit = 0; |