00001
00002
00003
00004
00005
00006
00007
00008 #include <iostream>
00009 #include <vector>
00010 #include <algorithm>
00011 #include <typeinfo>
00012 #include <cstring>
00013 #include <cassert>
00014
00015 using namespace std;
00016
00017 #include "gtex/gl_extensions.H"
00018 #include "gtex/rendering_mode.H"
00019 #include "gtex/basic_texture.H"
00020 #include "gtex/solid_color.H"
00021 #include "gtex/line_drawing.H"
00022
00023 #include "mlib/points.H"
00024
00025 using namespace mlib;
00026
00027
00028
00029 const char *LINE_DRAWING_VERTEX_PROGRAM_STR =
00030 "\
00031 !!ARBvp1.0\n\
00032 \n\
00033 ####################################################################\n\
00034 ### Real-time Silhouettes and Suggestive Contours\n\
00035 ### Vertex program for computing view dependent curvature values\n\
00036 ####################################################################\n\
00037 \n\
00038 ## Inputs: ipos : Vertex position\n\
00039 ## ifpd : First principal direction and curvature (k1 in w component)\n\
00040 ## ispd : Second principal direction and curvature (k2 in w component)\n\
00041 ## ider : Derivative of curvature (unique dcurv tensor values)\n\
00042 \n\
00043 ATTRIB ipos = vertex.position;\n\
00044 ATTRIB ifpd = vertex.attrib[6];\n\
00045 ATTRIB ispd = vertex.attrib[7];\n\
00046 ATTRIB ider = vertex.attrib[15];\n\
00047 \n\
00048 ## Output: opos = Output position\n\
00049 ## tc0 = {radial curvature, derivative of radial curvature, n dot v}\n\
00050 \n\
00051 OUTPUT opos = result.position;\n\
00052 OUTPUT ocol = result.color; # Not used\n\
00053 OUTPUT tc0 = result.texcoord[0]; # {rcurv, drcurv, ndotv}\n\
00054 \n\
00055 PARAM MVP[4] = { state.matrix.mvp }; # Modelview*projection matrix\n\
00056 PARAM MV[4] = { state.matrix.modelview }; # Modelview matrix\n\
00057 PARAM MVIT[4] = { state.matrix.modelview.invtrans }; # Modelview^-1 matrix (used to get eye pos)\n\
00058 \n\
00059 PARAM PARAM_DRAW_ENABLE = program.env[0];\n\
00060 PARAM PARAM_FEATURE = program.env[1];\n\
00061 PARAM EYE_POS = program.env[2];\n\
00062 \n\
00063 # Vertex normal vector:\n\
00064 TEMP normvec;\n\
00065 \n\
00066 # Eye vector:\n\
00067 TEMP eyevec;\n\
00068 \n\
00069 # Computed pricipal direction values:\n\
00070 # *pdvals.x = cos(angle between principal direction and eye vector)\n\
00071 # *pdvals.y = (*pdvals.x)^2\n\
00072 # *pdvals.z = principal curvature times *pdvals.y\n\
00073 # *pdvals.w = not used\n\
00074 TEMP fpdvals, spdvals;\n\
00075 \n\
00076 # Final scalar field values:\n\
00077 # finalsf.x = radial curvature\n\
00078 # finalsf.y = derivative of radial curvature\n\
00079 # finalsf.z = n dot v\n\
00080 # finalsf.w = not used\n\
00081 TEMP finalsf;\n\
00082 \n\
00083 # Temporary register (used during various computations)\n\
00084 TEMP temp;\n\
00085 \n\
00086 #############################################\n\
00087 ## Transform vertex position\n\
00088 #############################################\n\
00089 \n\
00090 " "\
00091 DP4 opos.x, MVP[0], ipos;\n\
00092 DP4 opos.y, MVP[1], ipos;\n\
00093 DP4 opos.z, MVP[2], ipos;\n\
00094 DP4 opos.w, MVP[3], ipos;\n\
00095 \n\
00096 #############################################\n\
00097 ## Compute view dependent curvature values\n\
00098 #############################################\n\
00099 \n\
00100 # Compute normal vector (XXX - Maybe replace with GL normal attribute)\n\
00101 XPD normvec.xyz, ifpd, ispd;\n\
00102 \n\
00103 # Compute eye vector, normalize\n\
00104 SUB eyevec, EYE_POS, ipos;\n\
00105 DP3 eyevec.w, eyevec, eyevec;\n\
00106 RSQ eyevec.w, eyevec.w;\n\
00107 MUL eyevec.xyz, eyevec.w, eyevec;\n\
00108 \n\
00109 # Compute n dot v\n\
00110 DP3 finalsf.z, normvec, eyevec;\n\
00111 \n\
00112 # Assuming that ifpd and eyevec are normalized so that dot product is equal to\n\
00113 # the angle between them:\n\
00114 DP3 fpdvals.x, ifpd, eyevec; # fpdvals.x = u = cos\n\
00115 MUL fpdvals.y, fpdvals.x, fpdvals.x; # fpdvals.y = u^2 = cos^2\n\
00116 MUL fpdvals.z, fpdvals.y, ifpd.w; # fpdvals.z = k1 * u^2\n\
00117 \n\
00118 # Assuming that ispd and eyevec are normalized so that dot product is equal to\n\
00119 # the angle between them:\n\
00120 DP3 spdvals.x, ispd, eyevec; # spdvals.x = v = cos\n\
00121 MUL spdvals.y, spdvals.x, spdvals.x; # spdvals.y = v^2 = cos^2\n\
00122 MUL spdvals.z, spdvals.y, ispd.w; # spdvals.z = k2 * v^2\n\
00123 \n\
00124 # Compute radial curvature:\n\
00125 ADD finalsf.x, fpdvals.z, spdvals.z; # k1 * u^2 + k2 * v^2\n\
00126 \n\
00127 # Compute derivative of radial curvature:\n\
00128 \n\
00129 # First, calculate derivative of normal curvature:\n\
00130 PARAM three= {3.0, 0.0, 0.0, 0.0};\n\
00131 MUL temp.x, fpdvals.x, ider.x; # u*P\n\
00132 MUL temp.y, spdvals.x, ider.y; # v*Q\n\
00133 MUL temp.y, three.x, temp.y; # 3*v*Q\n\
00134 ADD temp.x, temp.x, temp.y; # u*P + 3*v*Q\n\
00135 MUL temp.x, temp.x, fpdvals.y; # u^3*P + 3*u^2*v*Q\n\
00136 \n\
00137 MUL temp.y, fpdvals.x, ider.z; # u*S\n\
00138 MUL temp.y, three.x, temp.y; # 3*u*S\n\
00139 MUL temp.z, spdvals.x, ider.w; # v*T\n\
00140 ADD temp.y, temp.y, temp.z; # 3*u*S + v*T\n\
00141 MUL temp.y, temp.y, spdvals.y; # 3*u*v^2*S + v^3*T\n\
00142 \n\
00143 ADD temp.x, temp.x, temp.y; # u^3*P + 3*u^2*v*Q + 3*u*v^2*S + v^3*T\n\
00144 \n\
00145 # Then add offset to deriv of normal curvature:\n\
00146 # float csc2theta = 1.0f / (u2 + v2);\n\
00147 # sctest_num[i] *= csc2theta;\n\
00148 " "\
00149 # float tr = (themesh->curv2[i] - themesh->curv1[i]) *\n\
00150 # u * v * csc2theta;\n\
00151 # sctest_num[i] -= 2.0f * ndotv[i] * sqr(tr);\n\
00152 \n\
00153 ADD temp.y, fpdvals.y, spdvals.y; # u^2 + v^2\n\
00154 RCP temp.y, temp.y; # 1 / sin^2(theta)\n\
00155 MUL temp.x, temp.x, temp.y; # rescale deriv\n\
00156 \n\
00157 # Calculate torsion (tr):\n\
00158 SUB temp.z, ispd.w, ifpd.w; # (k2 - k1)\n\
00159 MUL temp.z, temp.z, fpdvals.x; # (k2 - k1)*u\n\
00160 MUL temp.z, temp.z, spdvals.x; # (k2 - k1)*u*v\n\
00161 MUL temp.y, temp.y, temp.z; # tr = (k2 - k1)*u*v / sin^2(theta)\n\
00162 MUL temp.y, temp.y, temp.y; # tr^2\n\
00163 PARAM two = {2,0,0,0};\n\
00164 MUL temp.y, two.x, temp.y; # 2 * tr^2\n\
00165 MUL temp.y, temp.y, finalsf.z; # 2 * tr^2 * (n dot v)\n\
00166 SUB temp.x, temp.x, temp.y; # whew!\n\
00167 \n\
00168 # #extra stuff necessary for texture\n\
00169 # # if (extra_sin2theta)\n\
00170 # # sctest_num[i] *= u2 + v2;\n\
00171 # ADD temp.y, fpdvals.y, spdvals.y; # u2 + v2\n\
00172 # MUL temp.x, temp.x, temp.y;\n\
00173 \n\
00174 # # sctest_den[i] = ndotv[i];\n\
00175 # # sctest_num[i] -= scthresh * sctest_den[i];\n\
00176 # PARAM thresh = {3.5,0,0,0};\n\
00177 MUL temp.y, PARAM_FEATURE.x, finalsf.z;\n\
00178 RCP temp.z, PARAM_FEATURE.w;\n\
00179 MUL temp.y, temp.y, temp.z;\n\
00180 SUB temp.x, temp.x, temp.y;\n\
00181 \n\
00182 # #sctest_num[i] = sctest_num[i] * feature_size2 / sctest_den[i];\n\
00183 RCP temp.y, finalsf.z;\n\
00184 MUL temp.x, temp.x, temp.y;\n\
00185 MUL temp.x, temp.x, PARAM_FEATURE.w;\n\
00186 \n\
00187 MOV finalsf.y, temp.x;\n\
00188 \n\
00189 # Scale scalar fields by feature size\n\
00190 MUL finalsf.x, finalsf.x, PARAM_FEATURE.z;\n\
00191 \n\
00192 #TODO: this constant is different than RTSC- FIGURE OUT WHAT IT SHOULD BE\n\
00193 PARAM fs={32,0,0,0};\n\
00194 MUL finalsf.y, finalsf.y, fs.x;\n\
00195 \n\
00196 # If disabling contours or suggestive contours is toggled, set the\n\
00197 # scalar field values to some appropriate constants\n\
00198 MAD finalsf.z, finalsf.z, PARAM_DRAW_ENABLE.x, PARAM_DRAW_ENABLE.y;\n\
00199 MAD finalsf.x, finalsf.x, PARAM_DRAW_ENABLE.z, PARAM_DRAW_ENABLE.w;\n\
00200 \n\
00201 MOV tc0, finalsf;\n\
00202 \n\
00203 END\n\
00204 ";
00205
00206 const char *LINE_DRAWING_FRAGMENT_PROGRAM_NO_SSD_STR =
00207 "\
00208 !!ARBfp1.0 \n\
00209 \n\
00210 ATTRIB tex0 = fragment.texcoord[0];\n\
00211 ATTRIB col0 = fragment.color; \n\
00212 ATTRIB ipos = fragment.position;\n\
00213 \n\
00214 OUTPUT out = result.color;\n\
00215 \n\
00216 PARAM PARAM_DRAW_COLOR = program.env[0];\n\
00217 \n\
00218 TEMP temp, temp2, temp3; #temporary\n\
00219 \n\
00220 TEMP c_color, sc_color, final_color;\n\
00221 \n\
00222 \n\
00223 PARAM one = {0.0,1.0,-1,1};\n\
00224 PARAM half = {0.5, 1.0, 1.0, 1.0};\n\
00225 PARAM big = {1.0, 0, 0, 0};\n\
00226 PARAM blue = {0.0, 0.0, 1.0, 0.0};\n\
00227 PARAM green = {0.0, 1.0, 0.0, 0.0};\n\
00228 \n\
00229 #contours\n\
00230 MOV temp2.x, tex0.z;\n\
00231 ADD temp2.x, temp2.x, half.x;\n\
00232 MOV temp2.y, one.y;\n\
00233 TEX c_color, temp2, texture[0], 2D;\n\
00234 \n\
00235 CMP temp, PARAM_DRAW_COLOR.xxxx, green, {0.0, 0.0, 0.0, 0.0};\n\
00236 ADD_SAT c_color, c_color, temp;\n\
00237 \n\
00238 #SC\n\
00239 MOV temp.x, tex0.x;\n\
00240 ADD temp.x, temp.x, half.x;\n\
00241 MOV temp.y, one.y;\n\
00242 TEX sc_color, temp, texture[1], 2D;\n\
00243 \n\
00244 CMP temp, PARAM_DRAW_COLOR.xxxx, blue, {0.0, 0.0, 0.0, 0.0};\n\
00245 ADD_SAT sc_color, sc_color, temp;\n\
00246 \n\
00247 # RCP temp.w, tex0.y;\n\
00248 # POW temp.w, tex0.y, big.x;\n\
00249 \n\
00250 # MUL temp.w, one.z, temp.w;\n\
00251 # CMP temp.y, tex0.y, temp.w, one.y;\n\
00252 \n\
00253 SUB sc_color, one.yyyy, sc_color;\n\
00254 MUL sc_color, sc_color, tex0.yyyy;\n\
00255 SUB sc_color, one.yyyy, sc_color;\n\
00256 \n\
00257 MUL final_color, sc_color, c_color;\n\
00258 \n\
00259 # fix alpha (may not be necessary)\n\
00260 #PARAM testcnst = {-0.1, 0.1, 0, 0};\n\
00261 #RCP temp.x, tex0.x;\n\
00262 #MUL temp.y, temp.x, testcnst.x;\n\
00263 #MOV temp.zw, testcnst.w;\n\
00264 \n\
00265 #test toon shader\n\
00266 #MOV temp2, tex1;\n\
00267 #MOV temp2.y, ipos.z;\n\
00268 #TEX temp2, temp2, texture[2], 2D;\n\
00269 #ADD temp2, temp2, program.env[1];\n\
00270 #MIN temp2, temp2, {1,1,1,1};\n\
00271 \n\
00272 #MUL temp, temp2, temp;\n\
00273 \n\
00274 MOV out, final_color;\n\
00275 #MOV out.xyz, tex0.z;\n\
00276 \n\
00277 END\n\
00278 ";
00279
00280
00281
00282 const char *LINE_DRAWING_VERTEX_SHADER_STR =
00283 "\
00284 /*\n\
00285 * Line Drawing Vertex Shader\n\
00286 *\n\
00287 */\n\
00288 \n\
00289 #version 110\n\
00290 \n\
00291 uniform bool contours_on; // Enable contour drawing\n\
00292 uniform bool sugcontours_on; // Enable suggestive contour drawing\n\
00293 uniform float scthresh; // Suggestive contour threshold\n\
00294 uniform float feature_size; // Mesh feature size\n\
00295 \n\
00296 uniform vec3 eye_pos; // Eye position in world coordinates\n\
00297 \n\
00298 attribute vec3 pdir1, pdir2; // Principal directions (normalized)\n\
00299 attribute float k1, k2; // Principal curvatures\n\
00300 attribute vec4 dcurv_tensor; // Derivative of curvature tensor\n\
00301 \n\
00302 varying float rcurv; // Radial curvature\n\
00303 varying float drcurv; // Derivative of radial curvature\n\
00304 varying float ndotv; // Normal vector dotted with view vector\n\
00305 \n\
00306 const float FS = 32.0; // Feature size constant from RTSC (may need tweaking)\n\
00307 \n\
00308 void\n\
00309 main()\n\
00310 {\n\
00311 \n\
00312 gl_Position = ftransform();\n\
00313 \n\
00314 // Compute view vector:\n\
00315 vec3 view_vec = normalize(eye_pos - vec3(gl_Vertex));\n\
00316 \n\
00317 // Compute N dot V:\n\
00318 ndotv = dot(gl_Normal, view_vec);\n\
00319 \n\
00320 float u = dot(pdir1, view_vec); // cos(angle between pdir1 and view_vec)\n\
00321 float u2 = u*u;\n\
00322 float v = dot(pdir2, view_vec); // cos(angle between pdir2 and view_vec)\n\
00323 float v2 = v*v;\n\
00324 \n\
00325 // Compute radial curvature:\n\
00326 rcurv = k1*u2 + k2*v2;\n\
00327 \n\
00328 // Compute derivative of radial curvature:\n\
00329 float csc2theta = 1.0/(u2 + v2);\n\
00330 \n\
00331 drcurv = (u*u2*dcurv_tensor.x\n\
00332 + 3.0*u2*v*dcurv_tensor.y\n\
00333 + 3.0*v2*u*dcurv_tensor.z\n\
00334 + v*v2*dcurv_tensor.w)\n\
00335 * csc2theta;\n\
00336 \n\
00337 float tr = (k2 - k1)*u*v*csc2theta;\n\
00338 \n\
00339 drcurv -= 2.0*ndotv*tr*tr;\n\
00340 \n\
00341 float feature_size2 = feature_size*feature_size;\n\
00342 \n\
00343 drcurv -= ndotv*scthresh/feature_size2;\n\
00344 \n\
00345 drcurv *= feature_size2/ndotv;\n\
00346 \n\
00347 drcurv *= FS;\n\
00348 \n\
00349 // Enable/disable features based on uniform values:\n\
00350 ndotv = contours_on ? ndotv : 1.0;\n\
00351 rcurv = sugcontours_on ? rcurv : -1.0;\n\
00352 \n\
00353 }\n\
00354 ";
00355
00356 const char *LINE_DRAWING_FRAGMENT_SHADER_STR =
00357 "\
00358 /*\n\
00359 * Line Drawing Fragment Shader\n\
00360 *\n\
00361 */\n\
00362 \n\
00363 #version 110\n\
00364 \n\
00365 uniform float width; // Line width\n\
00366 \n\
00367 varying float rcurv; // Radial curvature\n\
00368 varying float drcurv; // Derivative of radial curvature\n\
00369 varying float ndotv; // Normal vector dotted with view vector\n\
00370 \n\
00371 void\n\
00372 main()\n\
00373 {\n\
00374 \n\
00375 vec2 values = vec2(rcurv, ndotv);\n\
00376 \n\
00377 vec2 ddx = dFdx(values);\n\
00378 vec2 ddy = dFdy(values);\n\
00379 vec2 grad_len = sqrt(ddx*ddx + ddy*ddy);\n\
00380 grad_len = grad_len*width + 1.0e-6;\n\
00381 vec2 dst_to_zero = abs(values)/grad_len;\n\
00382 \n\
00383 vec2 gaussian = exp(-(dst_to_zero*dst_to_zero));\n\
00384 \n\
00385 \n\
00386 float fade_out = max(((1.0/(0.008*abs(drcurv))) - 0.4), 0.0);\n\
00387 \n\
00388 gl_FragColor.r = 1.0;\n\
00389 gl_FragColor.b = 1.0 - gaussian[0] * max(fade_out, drcurv >= 0.0 ? 1.0 : 0.0);\n\
00390 gl_FragColor.g = 1.0 - gaussian[1];\n\
00391 gl_FragColor.a = 1.0;\n\
00392 \n\
00393 }\n\
00394 ";
00395
00396
00397
00398
00399
00400 static GLuint load_ARB_program(const char *header, GLenum target,
00401 const char *program_string);
00402
00403 #ifdef GL_ARB_shader_objects
00404
00405 GLhandleARB load_ARB_shader(const char *header, GLenum shader_type,
00406 const char *shader_string);
00407
00408 bool link_ARB_shader(const char *header, GLhandleARB prog_handle);
00409
00410 void print_ARB_infolog(GLhandleARB object);
00411
00412 #endif // GL_ARB_shader_objects
00413
00414 void maketexture(double width, double fadeout=0.0);
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424 class LineDrawingRenderingMode : public RenderingMode {
00425
00426 public:
00427
00428 class LineDrawingStripCB : public RenderingModeStripCB {
00429
00430 };
00431
00432 virtual ~LineDrawingRenderingMode() { }
00433
00434 };
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444 class LineDrawingVprogFprogNoSSDMode : public LineDrawingRenderingMode {
00445
00446 public:
00447
00448
00449
00450
00451
00452
00453 class StripCB : public LineDrawingRenderingMode::LineDrawingStripCB {
00454
00455 public:
00456
00457
00458 virtual void faceCB(CBvert* v, CBface* f);
00459
00460 };
00461
00462 LineDrawingVprogFprogNoSSDMode();
00463
00464 ~LineDrawingVprogFprogNoSSDMode();
00465
00466 virtual void setup_for_drawing_outside_dl(const Patch *patch);
00467 virtual void setup_for_drawing_inside_dl(const Patch *patch);
00468
00469 virtual GLStripCB *get_new_strip_cb() const
00470 { return new StripCB(); }
00471
00472 private:
00473
00474 LineDrawingVprogFprogNoSSDMode(const LineDrawingVprogFprogNoSSDMode &other);
00475 LineDrawingVprogFprogNoSSDMode &operator=(const LineDrawingVprogFprogNoSSDMode &rhs);
00476
00477 GLuint vprog_name, fprog_name, c_texture_name, sc_texture_name;
00478
00479 };
00480
00481 LineDrawingVprogFprogNoSSDMode::LineDrawingVprogFprogNoSSDMode()
00482 : vprog_name(0), fprog_name(0), c_texture_name(0), sc_texture_name(0)
00483 {
00484
00485
00486
00487 if(GLExtensions::gl_arb_vertex_program_supported()){
00488
00489 err_mesg(ERR_LEV_INFO, "LineDrawingTexture::init() - Can use ARB vertex programs!");
00490
00491 #ifdef GL_ARB_vertex_program
00492
00493 vprog_name = load_ARB_program("LineDrawingTexture::init() - ",
00494 GL_VERTEX_PROGRAM_ARB,
00495 LINE_DRAWING_VERTEX_PROGRAM_STR);
00496
00497 #endif // GL_ARB_vertex_program
00498
00499 }
00500
00501
00502
00503 if(GLExtensions::gl_arb_fragment_program_supported()){
00504
00505 err_mesg(ERR_LEV_INFO, "LineDrawingTexture::init() - Can use ARB fragment programs!");
00506
00507 #ifdef GL_ARB_fragment_program
00508
00509 fprog_name = load_ARB_program("LineDrawingTexture::init() - ",
00510 GL_FRAGMENT_PROGRAM_ARB,
00511 LINE_DRAWING_FRAGMENT_PROGRAM_NO_SSD_STR);
00512
00513 #endif // GL_ARB_fragment_program
00514
00515 }
00516
00517 if(GLExtensions::gl_arb_multitexture_supported()){
00518
00519 glGenTextures(1, &c_texture_name);
00520 glBindTexture(GL_TEXTURE_2D, c_texture_name);
00521 maketexture(2.0);
00522
00523 glGenTextures(1, &sc_texture_name);
00524 glBindTexture(GL_TEXTURE_2D, sc_texture_name);
00525 maketexture(1.0);
00526
00527 }
00528
00529 }
00530
00531 LineDrawingVprogFprogNoSSDMode::~LineDrawingVprogFprogNoSSDMode()
00532 {
00533
00534 #if defined(GL_ARB_vertex_program) || defined(GL_ARB_fragment_program)
00535
00536 if(vprog_name)
00537 glDeleteProgramsARB(1, &vprog_name);
00538
00539 if(fprog_name)
00540 glDeleteProgramsARB(1, &fprog_name);
00541
00542 #endif
00543
00544 if(c_texture_name)
00545 glDeleteTextures(1, &c_texture_name);
00546
00547 if(sc_texture_name)
00548 glDeleteTextures(1, &sc_texture_name);
00549
00550 }
00551
00552 void
00553 LineDrawingVprogFprogNoSSDMode::setup_for_drawing_outside_dl(const Patch *patch)
00554 {
00555
00556 #ifdef GL_ARB_vertex_program
00557
00558 glEnable(GL_VERTEX_PROGRAM_ARB);
00559 glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vprog_name);
00560
00561 bool draw_contours =
00562 LineDrawingTexture::get_draw_contours();
00563 bool draw_sugcontours =
00564 LineDrawingTexture::get_draw_sugcontours();
00565
00566
00567 glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB, 0,
00568 draw_contours ? 1.0f : 0.0f,
00569 draw_contours ? 0.0f : 1.0f,
00570 draw_sugcontours ? 1.0f : 0.0f,
00571 draw_sugcontours ? 0.0f : 1.0f);
00572
00573 GLfloat sc_thresh = LineDrawingTexture::get_sugcontour_thresh();
00574
00575
00576 glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB, 1,
00577 sc_thresh,
00578 1.0f,
00579 static_cast<GLfloat>(patch->mesh()->avg_len()),
00580 static_cast<GLfloat>(sqr(patch->mesh()->avg_len())) );
00581
00582 Wpt eye = VIEW::eye();
00583
00584 glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB, 2,
00585 static_cast<GLfloat>(eye[0]),
00586 static_cast<GLfloat>(eye[1]),
00587 static_cast<GLfloat>(eye[2]),
00588 1.0f);
00589
00590 #endif // GL_ARB_vertex_program
00591
00592 #ifdef GL_ARB_fragment_program
00593
00594 glEnable(GL_FRAGMENT_PROGRAM_ARB);
00595 glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, fprog_name);
00596
00597 bool draw_color = LineDrawingTexture::get_draw_in_color();
00598
00599
00600 glProgramEnvParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 0,
00601 draw_color ? -1.0f : 1.0f,
00602 draw_color ? -1.0f : 1.0f,
00603 draw_color ? -1.0f : 1.0f,
00604 draw_color ? -1.0f : 1.0f);
00605
00606 #endif // GL_ARB_fragment_program
00607
00608 }
00609
00610 void
00611 LineDrawingVprogFprogNoSSDMode::setup_for_drawing_inside_dl(const Patch *patch)
00612 {
00613
00614 #ifdef GL_ARB_multitexture
00615
00616 glActiveTextureARB(GL_TEXTURE0);
00617 glEnable(GL_TEXTURE_2D);
00618 glBindTexture(GL_TEXTURE_2D, c_texture_name);
00619
00620 glActiveTextureARB(GL_TEXTURE1);
00621 glEnable(GL_TEXTURE_2D);
00622 glBindTexture(GL_TEXTURE_2D, sc_texture_name);
00623
00624 glActiveTextureARB(GL_TEXTURE0);
00625
00626 #endif // GL_ARB_multitexture
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642 }
00643
00644 void
00645 LineDrawingVprogFprogNoSSDMode::StripCB::faceCB(CBvert* v, CBface* f)
00646 {
00647
00648 using mlib::Wvec;
00649
00650
00651 Wvec n;
00652 glNormal3dv(f->vert_normal(v,n).data());
00653
00654 if (v->has_color())
00655 GL_COL(v->color(), alpha*v->alpha());
00656
00657 Wvec pdir1 = v->pdir1();
00658 Wvec pdir2 = v->pdir2();
00659
00660
00661 glVertexAttrib4dARB(6, pdir1[0], pdir1[1], pdir1[2], v->k1());
00662 glVertexAttrib4dARB(7, pdir2[0], pdir2[1], pdir2[2], v->k2());
00663 glVertexAttrib4dvARB(15, v->dcurv_tensor().dcurv);
00664
00665
00666 glVertex3dv(v->loc().data());
00667
00668 }
00669
00670
00671
00672
00673
00674
00675
00676
00677 class LineDrawingGLSLMode : public LineDrawingRenderingMode {
00678
00679 public:
00680
00681
00682
00683
00684
00685
00686 class StripCB : public LineDrawingRenderingMode::LineDrawingStripCB {
00687
00688 public:
00689
00690 StripCB(const LineDrawingGLSLMode *mode_in)
00691 : LineDrawingRenderingMode::LineDrawingStripCB(), mode(mode_in) { }
00692
00693
00694 virtual void faceCB(CBvert* v, CBface* f);
00695
00696 private:
00697
00698 const LineDrawingGLSLMode *mode;
00699
00700 };
00701
00702 LineDrawingGLSLMode();
00703
00704 ~LineDrawingGLSLMode();
00705
00706 virtual void setup_for_drawing_outside_dl(const Patch *patch);
00707 virtual void setup_for_drawing_inside_dl(const Patch *patch);
00708
00709 virtual void after_drawing_outside_dl(const Patch *patch);
00710
00711 virtual GLStripCB *get_new_strip_cb() const
00712 { return new StripCB(this); }
00713
00714 private:
00715
00716 LineDrawingGLSLMode(const LineDrawingGLSLMode &other);
00717 LineDrawingGLSLMode &operator=(const LineDrawingGLSLMode &rhs);
00718
00719 GLint contours_on_uniform_loc;
00720 GLint sugcontours_on_uniform_loc;
00721 GLint scthresh_uniform_loc;
00722 GLint feature_size_uniform_loc;
00723 GLint eye_pos_uniform_loc;
00724 GLint width_uniform_loc;
00725
00726 GLint pdir1_attrib_loc, pdir2_attrib_loc;
00727 GLint k1_attrib_loc, k2_attrib_loc;
00728 GLint dcurv_tensor_attrib_loc;
00729
00730 #ifdef GL_ARB_shader_objects
00731
00732 GLhandleARB vshader_handle, fshader_handle, prog_handle;
00733
00734 #endif // GL_ARB_shader_objects
00735
00736 };
00737
00738 LineDrawingGLSLMode::LineDrawingGLSLMode()
00739 : contours_on_uniform_loc(-1), sugcontours_on_uniform_loc(-1),
00740 scthresh_uniform_loc(-1), feature_size_uniform_loc(-1),
00741 eye_pos_uniform_loc(-1), width_uniform_loc(-1),
00742
00743 #ifdef GL_ARB_shader_objects
00744
00745 vshader_handle(0), fshader_handle(0), prog_handle(0)
00746
00747 #endif
00748
00749 {
00750
00751
00752
00753 if(GLExtensions::gl_arb_vertex_shader_supported()){
00754
00755 err_mesg(ERR_LEV_INFO, "LineDrawingTexture::init() - Can use ARB vertex shaders!");
00756
00757 #if defined(GL_ARB_shader_objects) && defined(GL_ARB_vertex_shader)
00758
00759 vshader_handle = load_ARB_shader("LineDrawingTexture::init() - ",
00760 GL_VERTEX_SHADER_ARB,
00761 LINE_DRAWING_VERTEX_SHADER_STR);
00762
00763 #endif // defined(GL_ARB_shader_objects) && defined(GL_ARB_vertex_shader)
00764
00765 }
00766
00767
00768
00769 if(GLExtensions::gl_arb_fragment_shader_supported()){
00770
00771 err_mesg(ERR_LEV_INFO, "LineDrawingTexture::init() - Can use ARB fragment shaders!");
00772
00773 #if defined(GL_ARB_shader_objects) && defined(GL_ARB_fragment_shader)
00774
00775 fshader_handle = load_ARB_shader("LineDrawingTexture::init() - ",
00776 GL_FRAGMENT_SHADER_ARB,
00777 LINE_DRAWING_FRAGMENT_SHADER_STR);
00778
00779 #endif // defined(GL_ARB_shader_objects) && defined(GL_ARB_fragment_shader)
00780
00781 }
00782
00783
00784
00785 if(GLExtensions::gl_arb_shader_objects_supported()){
00786
00787 #ifdef GL_ARB_shader_objects
00788
00789 prog_handle = glCreateProgramObjectARB();
00790
00791 glAttachObjectARB(prog_handle, vshader_handle);
00792 glAttachObjectARB(prog_handle, fshader_handle);
00793
00794 if(!link_ARB_shader("LineDrawingTexture::init() - ", prog_handle)){
00795
00796 glDeleteObjectARB(prog_handle);
00797 glDeleteObjectARB(vshader_handle);
00798 glDeleteObjectARB(fshader_handle);
00799
00800 prog_handle = vshader_handle = fshader_handle = 0;
00801
00802 } else {
00803
00804 glUseProgramObjectARB(prog_handle);
00805
00806
00807
00808 contours_on_uniform_loc = glGetUniformLocationARB(prog_handle, "contours_on");
00809 sugcontours_on_uniform_loc = glGetUniformLocationARB(prog_handle, "sugcontours_on");
00810 scthresh_uniform_loc = glGetUniformLocationARB(prog_handle, "scthresh");
00811 feature_size_uniform_loc = glGetUniformLocationARB(prog_handle, "feature_size");
00812 eye_pos_uniform_loc = glGetUniformLocationARB(prog_handle, "eye_pos");
00813 width_uniform_loc = glGetUniformLocationARB(prog_handle, "width");
00814
00815
00816
00817 pdir1_attrib_loc = glGetAttribLocationARB(prog_handle, "pdir1");
00818 pdir2_attrib_loc = glGetAttribLocationARB(prog_handle, "pdir2");
00819 k1_attrib_loc = glGetAttribLocationARB(prog_handle, "k1");
00820 k2_attrib_loc = glGetAttribLocationARB(prog_handle, "k2");
00821 dcurv_tensor_attrib_loc = glGetAttribLocationARB(prog_handle, "dcurv_tensor");
00822
00823 glUseProgramObjectARB(0);
00824
00825 }
00826
00827 #endif // GL_ARB_shader_objects
00828
00829 }
00830
00831 }
00832
00833 LineDrawingGLSLMode::~LineDrawingGLSLMode()
00834 {
00835
00836 #ifdef GL_ARB_shader_objects
00837
00838 glDeleteObjectARB(prog_handle);
00839 glDeleteObjectARB(vshader_handle);
00840 glDeleteObjectARB(fshader_handle);
00841
00842 #endif // GL_ARB_shader_objects
00843
00844 }
00845
00846 void
00847 LineDrawingGLSLMode::setup_for_drawing_outside_dl(const Patch *path)
00848 {
00849
00850 #ifdef GL_ARB_shader_objects
00851
00852 glUseProgramObjectARB(prog_handle);
00853
00854 Wpt eye = VIEW::eye();
00855
00856 glUniform3fARB(eye_pos_uniform_loc,
00857 static_cast<GLfloat>(eye[0]),
00858 static_cast<GLfloat>(eye[1]),
00859 static_cast<GLfloat>(eye[2]));
00860
00861
00862 glUniform1fARB(scthresh_uniform_loc,
00863 LineDrawingTexture::get_sugcontour_thresh());
00864
00865
00866 glUniform1iARB(contours_on_uniform_loc,
00867 LineDrawingTexture::get_draw_contours());
00868 glUniform1iARB(sugcontours_on_uniform_loc,
00869 LineDrawingTexture::get_draw_sugcontours());
00870
00871 #endif // GL_ARB_shader_objects
00872
00873 }
00874
00875 void
00876 LineDrawingGLSLMode::setup_for_drawing_inside_dl(const Patch *patch)
00877 {
00878
00879 #ifdef GL_ARB_shader_objects
00880
00881 glUseProgramObjectARB(prog_handle);
00882
00883
00884 glUniform1fARB(feature_size_uniform_loc,
00885 static_cast<GLfloat>(patch->mesh()->avg_len()));
00886 glUniform1fARB(width_uniform_loc, 1.0f);
00887
00888 #endif // GL_ARB_shader_objects
00889
00890 }
00891
00892 void
00893 LineDrawingGLSLMode::after_drawing_outside_dl(const Patch *patch)
00894 {
00895
00896 #ifdef GL_ARB_shader_objects
00897
00898
00899
00900 glUseProgramObjectARB(0);
00901
00902 #endif // GL_ARB_shader_objects
00903
00904 }
00905
00906 void
00907 LineDrawingGLSLMode::StripCB::faceCB(CBvert* v, CBface* f)
00908 {
00909
00910 using mlib::Wvec;
00911
00912
00913 Wvec n;
00914 glNormal3dv(f->vert_normal(v,n).data());
00915
00916 if (v->has_color())
00917 GL_COL(v->color(), alpha*v->alpha());
00918
00919
00920
00921 Wvec pdir1 = v->pdir1();
00922 Wvec pdir2 = v->pdir2();
00923
00924 glVertexAttrib3fARB(mode->pdir1_attrib_loc,
00925 static_cast<GLfloat>(pdir1[0]),
00926 static_cast<GLfloat>(pdir1[1]),
00927 static_cast<GLfloat>(pdir1[2]));
00928 glVertexAttrib3fARB(mode->pdir2_attrib_loc,
00929 static_cast<GLfloat>(pdir2[0]),
00930 static_cast<GLfloat>(pdir2[1]),
00931 static_cast<GLfloat>(pdir2[2]));
00932
00933 glVertexAttrib1fARB(mode->k1_attrib_loc, static_cast<GLfloat>(v->k1()));
00934 glVertexAttrib1fARB(mode->k2_attrib_loc, static_cast<GLfloat>(v->k2()));
00935
00936 double *dcurv = &(v->dcurv_tensor().dcurv[0]);
00937
00938 glVertexAttrib4fARB(mode->dcurv_tensor_attrib_loc,
00939 static_cast<GLfloat>(dcurv[0]),
00940 static_cast<GLfloat>(dcurv[1]),
00941 static_cast<GLfloat>(dcurv[2]),
00942 static_cast<GLfloat>(dcurv[3]));
00943
00944
00945 glVertex3dv(v->loc().data());
00946
00947 }
00948
00949
00950
00951 class LineDrawingRenderingModeSelectionPolicy {
00952
00953 public:
00954
00955 inline static RenderingMode *SelectRenderingMode();
00956
00957 };
00958
00959 inline RenderingMode*
00960 LineDrawingRenderingModeSelectionPolicy::SelectRenderingMode()
00961 {
00962
00963 RenderingMode *mode = 0;
00964
00965 if(GLExtensions::gl_arb_shader_objects_supported() &&
00966 GLExtensions::gl_arb_vertex_shader_supported() &&
00967 GLExtensions::gl_arb_fragment_shader_supported() &&
00968 GLExtensions::gl_nv_fragment_program_option_supported()){
00969
00970 mode = new LineDrawingGLSLMode();
00971
00972 } else if(GLExtensions::gl_arb_vertex_program_supported()){
00973
00974 if(GLExtensions::gl_arb_fragment_program_supported()){
00975
00976 if(GLExtensions::gl_arb_multitexture_supported()){
00977
00978 mode = new LineDrawingVprogFprogNoSSDMode();
00979
00980 }
00981
00982 }
00983
00984 }
00985
00986 return mode;
00987
00988 }
00989
00990 typedef RenderingModeSingleton<LineDrawingRenderingModeSelectionPolicy>
00991 LineDrawingModeSingleton;
00992
00993
00994
00995 bool LineDrawingTexture::draw_in_color = false;
00996 bool LineDrawingTexture::draw_contours = true;
00997 bool LineDrawingTexture::draw_sugcontours = true;
00998 float LineDrawingTexture::sugcontour_thresh = 0.0;
00999
01000 LineDrawingTexture::LineDrawingTexture(Patch* patch, StripCB* cb)
01001 : BasicTexture(patch, cb), solid_color_texture(0)
01002 {
01003
01004
01005
01006
01007
01008
01009
01010 }
01011
01012 LineDrawingTexture::~LineDrawingTexture()
01013 {
01014
01015 delete solid_color_texture;
01016
01017 }
01018
01019 int
01020 LineDrawingTexture::draw(CVIEWptr& v)
01021 {
01022
01023
01024 if(!LineDrawingModeSingleton::Instance().supported()){
01025
01026
01027
01028
01029 if(!solid_color_texture) solid_color_texture = new SolidColorTexture(_patch);
01030
01031 return solid_color_texture->draw(v);
01032
01033 }
01034
01035 assert(cb() != 0);
01036
01037
01038
01039
01040 if(!cb() || !dynamic_cast<LineDrawingRenderingMode::LineDrawingStripCB*>(cb()))
01041 set_cb(LineDrawingModeSingleton::Instance().get_new_strip_cb());
01042
01043 if (_ctrl)
01044 return _ctrl->draw(v);
01045 cb()->alpha = alpha();
01046
01047
01048 check_patch_texture_map();
01049
01050
01051
01052 _patch->apply_texture();
01053
01054
01055 glPushAttrib(GL_ENABLE_BIT | GL_CURRENT_BIT);
01056
01057
01058 GL_COL(_patch->color(), alpha());
01059
01060 LineDrawingModeSingleton::Instance().setup_for_drawing_outside_dl(_patch);
01061
01062
01063 if (BasicTexture::dl_valid(v)) {
01064
01065 BasicTexture::draw(v);
01066
01067 } else {
01068
01069
01070 int dl = _dl.get_dl(v, 1, _patch->stamp());
01071 if (dl)
01072 glNewList(dl, GL_COMPILE);
01073
01074 LineDrawingModeSingleton::Instance().setup_for_drawing_inside_dl(_patch);
01075
01076
01077 _patch->draw_tri_strips(_cb);
01078
01079 LineDrawingModeSingleton::Instance().after_drawing_inside_dl(_patch);
01080
01081
01082 if(_dl.dl(v)){
01083
01084 _dl.close_dl(v);
01085
01086
01087 BasicTexture::draw(v);
01088 }
01089
01090 }
01091
01092 LineDrawingModeSingleton::Instance().after_drawing_outside_dl(_patch);
01093
01094
01095 glPopAttrib();
01096
01097 return _patch->num_faces();
01098
01099 }
01100
01101
01102
01103
01104
01105
01106
01107
01108
01109
01110
01111
01112
01113
01114 void
01115 maketexture(double width, double fadeout)
01116 {
01117
01118 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
01119
01120 int texsize = 1024;
01121 static unsigned char *texture = new unsigned char[texsize*texsize];
01122
01123 int miplevel = 0;
01124
01125 while (texsize) {
01126
01127 for (int i = 0; i < texsize*texsize; i++) {
01128
01129 double x = (double) (i%texsize) - 0.5 * texsize + 0.5;
01130 double y = (double) (i/texsize) - 0.5 * texsize + 0.5;
01131 double val = 1;
01132
01133 if (texsize >= 4){
01134
01135 if (fabs(x) < width && y > 0.0){
01136
01137 val = sqr(max(1.0 - y, 0.0));
01138 val = (1.0*fadeout*miplevel + val)/(1.0 + fadeout*miplevel);
01139
01140 }
01141
01142 }
01143
01144 texture[i] = min(max(int(256.0 * val), 0), 255);
01145
01146 }
01147
01148
01149
01150
01151
01152
01153
01154
01155
01156
01157
01158 glTexImage2D(GL_TEXTURE_2D, miplevel, GL_LUMINANCE, texsize, texsize, 0,
01159 GL_LUMINANCE, GL_UNSIGNED_BYTE, texture);
01160
01161 texsize >>= 1;
01162 ++miplevel;
01163
01164 }
01165
01166 float bgcolor[] = { 1, 1, 1, 1 };
01167 glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, bgcolor);
01168 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
01169 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
01170
01171
01172 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
01173 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
01174
01175 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
01176 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
01177
01178 #ifdef GL_EXT_texture_filter_anisotropic
01179 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1);
01180 #endif
01181
01182 }
01183
01184
01185
01186
01187
01188 GLuint
01189 load_ARB_program(const char *header, GLenum target, const char *program_string)
01190 {
01191
01192 GLuint program_name = 0;
01193
01194 #if defined(GL_ARB_vertex_program) || defined(GL_ARB_fragment_program)
01195
01196 bool success = false;
01197 bool native;
01198
01199 glGenProgramsARB(1, &program_name);
01200 glBindProgramARB(target, program_name);
01201 glProgramStringARB(target, GL_PROGRAM_FORMAT_ASCII_ARB,
01202 strlen(program_string), program_string);
01203
01204 if(target == GL_VERTEX_PROGRAM_ARB){
01205
01206 success = GLExtensions::gl_arb_vertex_program_loaded(header, native,
01207 reinterpret_cast<const unsigned char *>(program_string));
01208
01209 } else if(target == GL_FRAGMENT_PROGRAM_ARB) {
01210
01211 success = GLExtensions::gl_arb_fragment_program_loaded(header, native,
01212 reinterpret_cast<const unsigned char *>(program_string));
01213
01214 }
01215
01216 if(!success){
01217
01218 glDeleteProgramsARB(1, &program_name);
01219 program_name = 0;
01220
01221 }
01222
01223 #endif
01224
01225 return program_name;
01226
01227 }
01228
01229 #ifdef GL_ARB_shader_objects
01230
01231 GLhandleARB
01232 load_ARB_shader(const char *header, GLenum shader_type, const char *shader_string)
01233 {
01234
01235 GLhandleARB shader_handle = glCreateShaderObjectARB(shader_type);
01236
01237 glShaderSourceARB(shader_handle, 1, &shader_string, 0);
01238
01239 glCompileShaderARB(shader_handle);
01240
01241 GLint compile_status;
01242
01243 glGetObjectParameterivARB(shader_handle, GL_OBJECT_COMPILE_STATUS_ARB, &compile_status);
01244
01245 if(!compile_status){
01246
01247 cerr << header
01248 << " Error while compiling shader. Printing info log..." << endl;
01249
01250 print_ARB_infolog(shader_handle);
01251
01252 glDeleteObjectARB(shader_handle);
01253
01254 shader_handle = 0;
01255
01256 }
01257
01258 return shader_handle;
01259
01260 }
01261
01262 bool
01263 link_ARB_shader(const char *header, GLhandleARB prog_handle)
01264 {
01265
01266 glLinkProgramARB(prog_handle);
01267
01268 GLint link_status;
01269
01270 glGetObjectParameterivARB(prog_handle, GL_OBJECT_LINK_STATUS_ARB, &link_status);
01271
01272 if(!link_status){
01273
01274 cerr << header
01275 << " Error while linking shader program. Printing info log..." << endl;
01276
01277 print_ARB_infolog(prog_handle);
01278
01279 }
01280
01281 return link_status != 0;
01282
01283 }
01284
01285 void
01286 print_ARB_infolog(GLhandleARB object)
01287 {
01288
01289 GLint infolog_length;
01290
01291 glGetObjectParameterivARB(object, GL_OBJECT_INFO_LOG_LENGTH_ARB, &infolog_length);
01292
01293 char *infolog = new char[infolog_length + 1];
01294
01295 GLint actual_infolog_length;
01296
01297 glGetInfoLogARB(object, infolog_length, &actual_infolog_length, infolog);
01298
01299 cerr << infolog << endl;
01300
01301 delete [] infolog;
01302
01303 }
01304
01305 #endif // GL_ARB_shader_objects