00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include "light-path.h"
00036
00037 #include <math.h>
00038
00039 #include "perf/perf.h"
00040
00041
00042 namespace glut {
00043
00044
00045
00046 static const float s_eps = 1.0e-6;
00047
00048 struct sort_seg_t {
00049 int index;
00050 float d2;
00051 };
00052
00053
00054
00055
00056
00057
00058
00059
00060 static void
00061 setSegment
00062 (
00063 IN const point3d_t& p0,
00064 IN const point3d_t& p1,
00065 IN const matrix4_t& T,
00066 IN int genTextureId,
00067 IN int outTextureId,
00068 IN Framebuffer * framebuffer,
00069 IN float size,
00070 IN const glut::render_context_t& rc,
00071 OUT poly_request_t * pr
00072 )
00073 {
00074 ASSERT(genTextureId, "null");
00075 ASSERT(outTextureId, "null");
00076 ASSERT(framebuffer, "null");
00077 ASSERT(size > 0, "bad size: %f", size);
00078 ASSERT(pr, "null");
00079
00080 p0.dump(" ray p0");
00081 p1.dump(" ray p1");
00082
00083 const point3d_t& pos = rc.viewer.getPosition();
00084 const point3d_t& facing = rc.viewer.getFacing();
00085
00086 pos.dump(" viewer position");
00087 facing.dump(" viewer facing");
00088
00089 point3d_t mid = 0.5 * (p0 + p1);
00090 point3d_t to = mid - pos;
00091 normalize(to);
00092 mid.dump(" ray midpoint");
00093 to.dump(" from viewer to ray midpoint");
00094
00095 point3d_t ray = p1 - p0;
00096 float ray2 = dotProduct(ray, ray);
00097 if (ray2 < s_eps) {
00098 DPRINTF("null ray?");
00099 return;
00100 }
00101 float rayLength = sqrt(ray2);
00102 DPRINTF(" rayLength = %f", rayLength);
00103 ray = (1.0 / rayLength) * ray;
00104 ray.dump(" ray");
00105
00106 float delta = dotProduct(ray, to) - 1.0;
00107 if (delta > -s_eps && delta < s_eps) {
00108
00109 DPRINTF("Aligned?");
00110 return;
00111 }
00112
00113
00114 point3d_t tang = crossProduct(ray, to);
00115 normalize(tang);
00116 tang.dump(" tangent");
00117
00118
00119 point3d_t norm = crossProduct(ray, tang);
00120 normalize(norm);
00121 norm.dump(" normal");
00122
00123
00124 glMatrixMode(GL_MODELVIEW);
00125 glPushMatrix();
00126 {
00127 FramebufferContext fc(framebuffer, outTextureId, rc);
00128
00129 Viewer viewer2 = rc.viewer;
00130 point3d_t newPos = mid - 5.0 * rayLength * facing;
00131 viewer2.setPosition(newPos);
00132 setOpenGLViewer(viewer2);
00133 viewer2.getPosition().dump(" temporary viewer position");
00134
00135 glEnable(GL_BLEND);
00136 glBlendFunc(GL_SRC_ALPHA, GL_ONE);
00137 glClearColor(0.0, 0.0, 0.0, 0.0);
00138 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00139
00140
00141 glEnable(GL_TEXTURE_2D);
00142 glBindTexture(GL_TEXTURE_2D, genTextureId);
00143 glNormal3fv(&norm.x);
00144 glBegin(GL_POLYGON);
00145
00146
00147 point3d_t vtx = p0 - size * ray + size * tang;
00148 vtx.dump(" temp top left");
00149 glTexCoord2f(0, 0);
00150 glVertex3fv(&vtx.x);
00151
00152
00153 vtx = p0 - size * ray - size * tang;
00154 vtx.dump(" temp bottom left");
00155 glTexCoord2f(0, 1);
00156 glVertex3fv(&vtx.x);
00157
00158
00159 vtx = p1 + size * ray - size * tang;
00160 vtx.dump(" temp bottom right");
00161 glTexCoord2f(1, 1);
00162 glVertex3fv(&vtx.x);
00163
00164
00165 vtx = p1 + size * ray + size * tang;
00166 vtx.dump(" temp top right");
00167 glTexCoord2f(1, 0);
00168 glVertex3fv(&vtx.x);
00169
00170 glEnd();
00171
00172 glDisable(GL_BLEND);
00173 glDisable(GL_TEXTURE_2D);
00174 }
00175 glMatrixMode(GL_MODELVIEW);
00176 glPopMatrix();
00177
00178
00179
00180 const point3d_t& up = rc.viewer.getUp();
00181 point3d_t right = crossProduct(facing, up);
00182 normalize(right);
00183 point3d_t realUp = crossProduct(right, facing);
00184 normalize(realUp);
00185
00186 right.dump(" viewer right");
00187 realUp.dump(" viewer up");
00188
00189
00190 pr->nVertices = 4;
00191 pr->textureId = genTextureId;
00192 pr->normal = -facing;
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203 point3d_t vtx = mid + 0.5 * rayLength * (realUp - right);
00204 vtx.dump(" top left");
00205
00206
00207 pr->vertex[0] = T * vtx;
00208 pr->u[0] = 0;
00209 pr->v[0] = 0;
00210
00211
00212 vtx = mid + 0.5 * rayLength * (-realUp - right);
00213 vtx.dump(" bottom left");
00214
00215
00216 pr->vertex[1] = T * vtx;
00217 pr->u[1] = 0;
00218 pr->v[1] = 1;
00219
00220
00221 vtx = mid + 0.5 * rayLength * (-realUp + right);
00222 vtx.dump(" bottom right");
00223
00224
00225 pr->vertex[2] = T * vtx;
00226 pr->u[2] = 1;
00227 pr->v[2] = 1;
00228
00229
00230 vtx = mid + 0.5 * rayLength * (realUp + right);
00231 vtx.dump(" top right");
00232
00233
00234 pr->vertex[3] = T * vtx;
00235 pr->u[3] = 1;
00236 pr->v[3] = 0;
00237
00238
00239
00240
00241 for (int i = 0; i < pr->nVertices; ++i) {
00242 pr->vertex[i].dump(" transformed");
00243 }
00244 }
00245
00246
00247
00248 static int
00249 compareSegments
00250 (
00251 IN const void * p1,
00252 IN const void * p2
00253 )
00254 throw()
00255 {
00256 const sort_seg_t * pss1 = (const sort_seg_t *) p1;
00257 const sort_seg_t * pss2 = (const sort_seg_t *) p2;
00258
00259 ASSERT(pss1 && pss2, "null");
00260
00261 if (pss1->d2 > pss2->d2) {
00262
00263 return +1;
00264 } else if (pss1->d2 < pss2->d2) {
00265
00266 return -1;
00267 }
00268
00269
00270 return 0;
00271 }
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281 void
00282 drawTransparentPath
00283 (
00284 IN const point3d_t * pointArray,
00285 IN int * textureArray,
00286 IN int nSegments,
00287 IN Framebuffer * framebuffer,
00288 IN float size,
00289 IN int textureId,
00290 IN const render_context_t& rc,
00291 IN RenderQueue * rq
00292 )
00293 {
00294 perf::Timer timer("drawTransparentPath");
00295 ASSERT(pointArray, "null");
00296 ASSERT(textureArray, "null");
00297 ASSERT(nSegments > 0, "bad segment count: %d", nSegments);
00298 ASSERT(framebuffer, "null");
00299 ASSERT(size > 0, "bad size: %f", size);
00300 ASSERT(textureId > 0, "Bad texture ID");
00301 ASSERT(rq, "null");
00302
00303
00304 point3d_t pos = rc.viewer.getPosition();
00305
00306
00307
00308
00309
00310 matrix4_t T;
00311 getModelViewMatrix(T);
00312
00313
00314 const int s_maxSegments = 64;
00315 if (nSegments > s_maxSegments) {
00316 DPRINTF("WARNING: support a max of %d segments", s_maxSegments);
00317 nSegments = s_maxSegments;
00318 }
00319
00320
00321 sort_seg_t array[s_maxSegments];
00322 for (int i = 0; i < nSegments; ++i) {
00323 point3d_t mid = 0.5 * (pointArray[i] + pointArray[i + 1]);
00324 sort_seg_t& ss = array[i];
00325 ss.index = i;
00326 point3d_t diff = mid - pos;
00327 ss.d2 = dotProduct(diff, diff);
00328 }
00329
00330
00331 qsort(array, nSegments, sizeof(sort_seg_t), compareSegments);
00332
00333
00334 for (int i = 0; i < nSegments; ++i) {
00335 const sort_seg_t& ss = array[i];
00336 int idx = ss.index;
00337 poly_request_t * pr = rq->grabRequestSlot();
00338 if (!pr)
00339 return;
00340 setSegment(pointArray[idx], pointArray[idx + 1], T,
00341 textureId, textureArray[idx], framebuffer, size, rc, pr);
00342 }
00343 }
00344
00345
00346
00347 };
00348