Parent Directory
|
Revision Log
* Update INSTALL, README * Update contact information if file headers
1 /* 2 normalmap GIMP plugin 3 4 Copyright (C) 2002-2008 Shawn Kirst <skirst@insightbb.com> 5 6 This program is free software; you can redistribute it and/or 7 modify it under the terms of the GNU General Public 8 License as published by the Free Software Foundation; either 9 version 2 of the License, or (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program; see the file COPYING. If not, write to 18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 19 Boston, MA 02111-1307, USA. 20 */ 21 22 #include <string.h> 23 #include <math.h> 24 #include <ctype.h> 25 #include <gtk/gtk.h> 26 #include <gtk/gtkgl.h> 27 #include <GL/glew.h> 28 #include <libgimp/gimp.h> 29 #include <libgimp/gimpui.h> 30 31 #include "scale.h" 32 33 #include "objects/quad.h" 34 #include "objects/cube.h" 35 #include "objects/sphere.h" 36 #include "objects/torus.h" 37 #include "objects/teapot.h" 38 39 #include "pixmaps/object.xpm" 40 #include "pixmaps/light.xpm" 41 #include "pixmaps/scene.xpm" 42 #include "pixmaps/full.xpm" 43 44 #define IS_POT(x) (((x) & ((x) - 1)) == 0) 45 46 typedef float matrix[16]; 47 typedef float vec4[4]; 48 typedef float vec3[3]; 49 typedef float vec2[2]; 50 51 typedef enum 52 { 53 BUMPMAP_NORMAL = 0, BUMPMAP_PARALLAX, BUMPMAP_POM, BUMPMAP_RELIEF, 54 BUMPMAP_MAX 55 } BUMPMAP_TYPE; 56 57 typedef enum 58 { 59 ROTATE_OBJECT = 0, ROTATE_LIGHT, ROTATE_SCENE, 60 ROTATE_MAX 61 } ROTATE_TYPE; 62 63 typedef enum 64 { 65 OBJECT_QUAD = 0, OBJECT_CUBE, OBJECT_SPHERE, OBJECT_TORUS, OBJECT_TEAPOT, 66 OBJECT_MAX 67 } OBJECT_TYPE; 68 69 static int _active = 0; 70 static int _gl_error = 0; 71 static gint32 normalmap_drawable_id = -1; 72 static GtkWidget *window = 0; 73 static GtkWidget *glarea = 0; 74 static GtkWidget *rotate_obj_btn = 0; 75 static GtkWidget *object_opt = 0; 76 static GtkWidget *controls_table = 0; 77 static GtkWidget *bumpmapping_opt = 0; 78 static GtkWidget *specular_check = 0; 79 static GtkWidget *gloss_opt = 0; 80 static GtkWidget *specular_exp_range = 0; 81 static GtkWidget *ambient_color_btn = 0; 82 static GtkWidget *diffuse_color_btn = 0; 83 static GtkWidget *specular_color_btn = 0; 84 static GtkWidget *uvscale_spin1 = 0; 85 static GtkWidget *uvscale_spin2 = 0; 86 87 static int fullscreen = 0; 88 89 static GLuint diffuse_tex = 0; 90 static GLuint gloss_tex = 0; 91 static GLuint normal_tex = 0; 92 static GLuint white_tex = 0; 93 94 static struct 95 { 96 float *verts; 97 unsigned short *indices; 98 unsigned int num_verts; 99 unsigned int num_indices; 100 GLuint vbo; 101 } object_info[OBJECT_MAX] = 102 { 103 {quad_verts, quad_indices, QUAD_NUM_VERTS, QUAD_NUM_INDICES, 0}, 104 {cube_verts, cube_indices, CUBE_NUM_VERTS, CUBE_NUM_INDICES, 0}, 105 {sphere_verts, sphere_indices, SPHERE_NUM_VERTS, SPHERE_NUM_INDICES, 0}, 106 {torus_verts, torus_indices, TORUS_NUM_VERTS, TORUS_NUM_INDICES, 0}, 107 {teapot_verts, teapot_indices, TEAPOT_NUM_VERTS, TEAPOT_NUM_INDICES, 0} 108 }; 109 110 static const float anisotropy = 4.0f; 111 112 static int has_glsl = 0; 113 static int has_npot = 0; 114 static int has_generate_mipmap = 0; 115 static int has_aniso = 0; 116 static int num_mtus = 0; 117 118 static int max_instructions = 0; 119 static int max_indirections = 0; 120 121 static GLhandleARB programs[BUMPMAP_MAX]; 122 123 static const char *vert_source = 124 "varying vec2 tex;\n" 125 "varying vec3 vpos;\n" 126 "varying vec3 normal;\n" 127 "varying vec3 tangent;\n" 128 "varying vec3 binormal;\n" 129 "\n" 130 "uniform vec2 uvscale;\n" 131 "\n" 132 "void main()\n" 133 "{\n" 134 " gl_Position = ftransform();\n" 135 " tex = gl_MultiTexCoord0.xy * uvscale;\n" 136 " vpos = (gl_ModelViewMatrix * gl_Vertex).xyz;\n" 137 " tangent = gl_NormalMatrix * gl_MultiTexCoord3.xyz;\n" 138 " binormal = gl_NormalMatrix * gl_MultiTexCoord4.xyz;\n" 139 " normal = gl_NormalMatrix * gl_Normal;\n" 140 "}\n"; 141 142 static const char *normal_frag_source = 143 "varying vec2 tex;\n" 144 "varying vec3 vpos;\n" 145 "varying vec3 normal;\n" 146 "varying vec3 tangent;\n" 147 "varying vec3 binormal;\n" 148 149 "uniform sampler2D sNormal;\n" 150 "uniform sampler2D sDiffuse;\n" 151 "uniform sampler2D sGloss;\n\n" 152 153 "uniform vec3 lightDir;\n" 154 "uniform bool specular;\n" 155 "uniform float specular_exp;\n" 156 "uniform vec3 ambient_color;\n" 157 "uniform vec3 diffuse_color;\n" 158 "uniform vec3 specular_color;\n\n" 159 160 "void main()\n" 161 "{\n" 162 " vec3 V = normalize(vpos);\n" 163 " vec3 N = texture2D(sNormal, tex).rgb * 2.0 - 1.0;\n" 164 " N = normalize(N.x * tangent + N.y * binormal + N.z * normal);\n" 165 " vec3 diffuse = texture2D(sDiffuse, tex).rgb;\n" 166 " float NdotL = clamp(dot(N, lightDir), 0.0, 1.0);\n" 167 " vec3 color = diffuse * diffuse_color * NdotL;\n" 168 " if(specular)\n" 169 " {\n" 170 " vec3 gloss = texture2D(sGloss, tex).rgb;\n" 171 " vec3 R = reflect(V, N);\n" 172 " float RdotL = clamp(dot(R, lightDir), 0.0, 1.0);\n" 173 " color += gloss * specular_color * pow(RdotL, specular_exp);\n" 174 " }\n" 175 " gl_FragColor.rgb = ambient_color * diffuse + color;\n" 176 "}\n"; 177 178 static const char *parallax_frag_source = 179 "varying vec2 tex;\n" 180 "varying vec3 vpos;\n" 181 "varying vec3 normal;\n" 182 "varying vec3 tangent;\n" 183 "varying vec3 binormal;\n" 184 185 "uniform sampler2D sNormal;\n" 186 "uniform sampler2D sDiffuse;\n" 187 "uniform sampler2D sGloss;\n\n" 188 189 "uniform vec3 lightDir;\n" 190 "uniform bool specular;\n" 191 "uniform float specular_exp;\n" 192 "uniform vec3 ambient_color;\n" 193 "uniform vec3 diffuse_color;\n" 194 "uniform vec3 specular_color;\n\n" 195 196 "void main()\n" 197 "{\n" 198 " mat3 TBN = mat3(tangent, binormal, normal);\n" 199 " vec3 V = normalize(vpos);\n" 200 " vec3 V_ts = V * TBN;\n" 201 " float height = texture2D(sNormal, tex).a;\n" 202 " float offset = height * 0.025 - 0.0125;\n" 203 " vec2 tc = tex + offset * V_ts.xy;\n" 204 " height += texture2D(sNormal, tc).a;\n" 205 " offset = 0.025 * (height - 1.0);\n" 206 " tc = tex + offset * V_ts.xy;\n" 207 " vec3 N = texture2D(sNormal, tc).rgb * 2.0 - 1.0;\n" 208 " N = normalize(N.x * tangent + N.y * binormal + N.z * normal);\n" 209 " vec3 diffuse = texture2D(sDiffuse, tc).rgb;\n" 210 " float NdotL = clamp(dot(N, lightDir), 0.0, 1.0);\n" 211 " vec3 color = diffuse * diffuse_color * NdotL;\n" 212 " if(specular)\n" 213 " {\n" 214 " vec3 gloss = texture2D(sGloss, tc).rgb;\n" 215 " vec3 R = reflect(V, N);\n" 216 " float RdotL = clamp(dot(R, lightDir), 0.0, 1.0);\n" 217 " color += gloss * specular_color * pow(RdotL, specular_exp);\n" 218 " }\n" 219 " gl_FragColor.rgb = ambient_color * diffuse + color;\n" 220 "}\n"; 221 222 static const char *pom_frag_source = 223 "varying vec2 tex;\n" 224 "varying vec3 vpos;\n" 225 "varying vec3 normal;\n" 226 "varying vec3 tangent;\n" 227 "varying vec3 binormal;\n" 228 "\n" 229 "uniform sampler2D sNormal;\n" 230 "uniform sampler2D sDiffuse;\n" 231 "uniform sampler2D sGloss;\n" 232 "\n" 233 "uniform vec3 lightDir;\n" 234 "uniform bool specular;\n" 235 "uniform vec3 ambient_color;\n" 236 "uniform vec3 diffuse_color;\n" 237 "uniform vec3 specular_color;\n" 238 "uniform float specular_exp;\n" 239 "uniform vec2 planes;\n" 240 "uniform float depth_factor;\n" 241 "\n" 242 "void ray_intersect(sampler2D reliefMap, inout vec4 p, inout vec3 v)\n" 243 "{\n" 244 " const int search_steps = 20;\n" 245 "\n" 246 " v /= float(search_steps);\n" 247 "\n" 248 " vec4 pp = p;\n" 249 " for(int i = 0; i < search_steps - 1; ++i)\n" 250 " {\n" 251 " p.w = texture2D(reliefMap, p.xy).w;\n" 252 " if(p.w > p.z)\n" 253 " {\n" 254 " pp = p;\n" 255 " p.xyz += v;\n" 256 " }\n" 257 " }\n" 258 "\n" 259 " float f = (pp.w - pp.z) / (p.z - pp.z - p.w + pp.w);\n" 260 " p = mix(pp, p, f);\n" 261 "}\n" 262 "\n" 263 "void ray_intersect_ATI(sampler2D reliefMap, inout vec4 p, inout vec3 v)" 264 "{\n" 265 " float h0 = 1.0 - texture2D(reliefMap, p.xy + v.xy * 1.000).a;\n" 266 " float h1 = 1.0 - texture2D(reliefMap, p.xy + v.xy * 0.875).a;\n" 267 " float h2 = 1.0 - texture2D(reliefMap, p.xy + v.xy * 0.750).a;\n" 268 " float h3 = 1.0 - texture2D(reliefMap, p.xy + v.xy * 0.625).a;\n" 269 " float h4 = 1.0 - texture2D(reliefMap, p.xy + v.xy * 0.500).a;\n" 270 " float h5 = 1.0 - texture2D(reliefMap, p.xy + v.xy * 0.375).a;\n" 271 " float h6 = 1.0 - texture2D(reliefMap, p.xy + v.xy * 0.250).a;\n" 272 " float h7 = 1.0 - texture2D(reliefMap, p.xy + v.xy * 0.125).a;\n" 273 "\n" 274 " float x, y, xh, yh;\n" 275 " if (h7 > 0.875) { x = 0.937; y = 0.938; xh = h7; yh = h7; }\n" 276 " else if(h6 > 0.750) { x = 0.750; y = 0.875; xh = h6; yh = h7; }\n" 277 " else if(h5 > 0.625) { x = 0.625; y = 0.750; xh = h5; yh = h6; }\n" 278 " else if(h4 > 0.500) { x = 0.500; y = 0.625; xh = h4; yh = h5; }\n" 279 " else if(h3 > 0.375) { x = 0.375; y = 0.500; xh = h3; yh = h4; }\n" 280 " else if(h2 > 0.250) { x = 0.250; y = 0.375; xh = h2; yh = h3; }\n" 281 " else if(h1 > 0.125) { x = 0.125; y = 0.250; xh = h1; yh = h2; }\n" 282 " else { x = 0.000; y = 0.125; xh = h0; yh = h1; }\n" 283 "\n" 284 " float parallax = (x * (y - yh) - y * (x - xh)) / ((y - yh) - (x - xh));\n" 285 " p.xyz += v * (1.0 - parallax);\n" 286 "}\n" 287 "\n" 288 "void main()\n" 289 "{\n" 290 "\n" 291 " vec3 V = normalize(vpos);\n" 292 " float a = dot(normal, -V);\n" 293 " vec3 v = vec3(dot(V, tangent), dot(V, binormal), a);\n" 294 " vec3 scale = vec3(1.0, 1.0, depth_factor);\n" 295 " v *= scale.z / (scale * v.z);\n" 296 " vec4 p = vec4(tex, vec2(0.0, 1.0));\n" 297 "#ifdef ATI\n" 298 " ray_intersect_ATI(sNormal, p, v);\n" 299 "#else\n" 300 " ray_intersect(sNormal, p, v);\n" 301 "#endif\n" 302 "\n" 303 " vec2 uv = p.xy;\n" 304 " vec3 N = texture2D(sNormal, uv).xyz * 2.0 - 1.0;\n" 305 " vec3 diffuse = texture2D(sDiffuse, uv).rgb;\n" 306 "\n" 307 " N.z = sqrt(1.0 - dot(N.xy, N.xy));\n" 308 " N = normalize(N.x * tangent + N.y * binormal + N.z * normal);\n" 309 "\n" 310 " float NdotL = clamp(dot(N, lightDir), 0.0, 1.0);\n" 311 "\n" 312 " vec3 color = diffuse * diffuse_color * NdotL;\n" 313 "\n" 314 " if(specular)\n" 315 " {\n" 316 " vec3 gloss = texture2D(sGloss, uv).rgb;\n" 317 " vec3 R = reflect(V, N);\n" 318 " float RdotL = clamp(dot(R, lightDir), 0.0, 1.0);\n" 319 " color += gloss * specular_color * pow(RdotL, specular_exp);\n" 320 " }\n" 321 "\n" 322 " gl_FragColor.rgb = ambient_color * diffuse + color;\n" 323 "}\n"; 324 325 static const char *relief_frag_source = 326 "varying vec2 tex;\n" 327 "varying vec3 vpos;\n" 328 "varying vec3 normal;\n" 329 "varying vec3 tangent;\n" 330 "varying vec3 binormal;\n" 331 "\n" 332 "uniform sampler2D sNormal;\n" 333 "uniform sampler2D sDiffuse;\n" 334 "uniform sampler2D sGloss;\n" 335 "\n" 336 "uniform vec3 lightDir;\n" 337 "uniform bool specular;\n" 338 "uniform vec3 ambient_color;\n" 339 "uniform vec3 diffuse_color;\n" 340 "uniform vec3 specular_color;\n" 341 "uniform float specular_exp;\n" 342 "uniform vec2 planes;\n" 343 "uniform float depth_factor;\n" 344 "\n" 345 "float ray_intersect(sampler2D reliefMap, vec2 dp, vec2 ds)\n" 346 "{\n" 347 " const int linear_search_steps = 20;\n" 348 "\n" 349 " float size = 1.0 / float(linear_search_steps);\n" 350 " float depth = 0.0;\n" 351 " float best_depth = 1.0;\n" 352 "\n" 353 " for(int i = 0; i < linear_search_steps - 1; ++i)\n" 354 " {\n" 355 " depth += size;\n" 356 " float t = texture2D(reliefMap, dp + ds * depth).a;\n" 357 " if(best_depth > 0.996)\n" 358 " if(depth >= t)\n" 359 " best_depth = depth;\n" 360 " }\n" 361 " depth = best_depth;\n" 362 "\n" 363 " const int binary_search_steps = 5;\n" 364 "\n" 365 " for(int i = 0; i < binary_search_steps; ++i)\n" 366 " {\n" 367 " size *= 0.5;\n" 368 " float t = texture2D(reliefMap, dp + ds * depth).a;\n" 369 " if(depth >= t)\n" 370 " {\n" 371 " best_depth = depth;\n" 372 " depth -= 2.0 * size;\n" 373 " }\n" 374 " depth += size;\n" 375 " }\n" 376 "\n" 377 " return(best_depth);\n" 378 "}\n" 379 "\n" 380 "void main()\n" 381 "{\n" 382 "\n" 383 " vec3 V = normalize(vpos);\n" 384 " float a = dot(normal, -V);\n" 385 " vec2 s = vec2(dot(V, tangent), dot(V, binormal));\n" 386 " s *= depth_factor / a;\n" 387 " vec2 ds = s;\n" 388 " vec2 dp = tex;\n" 389 " float d = ray_intersect(sNormal, dp, ds);\n" 390 "\n" 391 " vec2 uv = dp + ds * d;\n" 392 " vec3 N = texture2D(sNormal, uv).xyz * 2.0 - 1.0;\n" 393 " vec3 diffuse = texture2D(sDiffuse, uv).rgb;\n" 394 "\n" 395 " N.z = sqrt(1.0 - dot(N.xy, N.xy));\n" 396 " N = normalize(N.x * tangent + N.y * binormal + N.z * normal);\n" 397 "\n" 398 " float NdotL = clamp(dot(N, lightDir), 0.0, 1.0);\n" 399 "\n" 400 " vec3 color = diffuse * diffuse_color * NdotL;\n" 401 "\n" 402 " if(specular)\n" 403 " {\n" 404 " vec3 gloss = texture2D(sGloss, uv).rgb;\n" 405 " vec3 R = reflect(V, N);\n" 406 " float RdotL = clamp(dot(R, lightDir), 0.0, 1.0);\n" 407 " color += gloss * specular_color * pow(RdotL, specular_exp);\n" 408 " }\n" 409 "\n" 410 " gl_FragColor.rgb = ambient_color * diffuse + color;\n" 411 "}\n"; 412 413 static int bumpmapping = BUMPMAP_NORMAL; 414 static int specular = 0; 415 static int rotate_type = ROTATE_OBJECT; 416 static int object_type = OBJECT_QUAD; 417 418 static vec3 ambient_color = {0.2f, 0.2f, 0.2f}; 419 static vec3 diffuse_color = {1, 1, 1}; 420 static vec3 specular_color = {1, 1, 1}; 421 static float specular_exp = 32.0f; 422 static vec3 uvscale = {1, 1}; 423 424 static const float depth_factor = 0.05f; 425 426 static int mx; 427 static int my; 428 static vec3 object_rot; 429 static vec3 light_rot; 430 static vec3 scene_rot; 431 static float zoom; 432 433 #define M(r,c) m[(c << 2) + r] 434 #define T(r,c) t[(c << 2) + r] 435 436 static void mat_invert(matrix m) 437 { 438 float invdet; 439 matrix t; 440 441 invdet = (float)1.0 / (M(0, 0) * (M(1, 1) * M(2, 2) - M(1, 2) * M(2, 1)) - 442 M(0, 1) * (M(1, 0) * M(2, 2) - M(1, 2) * M(2, 0)) + 443 M(0, 2) * (M(1, 0) * M(2, 1) - M(1, 1) * M(2, 0))); 444 445 T(0,0) = invdet * (M(1, 1) * M(2, 2) - M(1, 2) * M(2, 1)); 446 T(0,1) = -invdet * (M(0, 1) * M(2, 2) - M(0, 2) * M(2, 1)); 447 T(0,2) = invdet * (M(0, 1) * M(1, 2) - M(0, 2) * M(1, 1)); 448 T(0,3) = 0; 449 450 T(1,0) = -invdet * (M(1, 0) * M(2, 2) - M(1, 2) * M(2, 0)); 451 T(1,1) = invdet * (M(0, 0) * M(2, 2) - M(0, 2) * M(2, 0)); 452 T(1,2) = -invdet * (M(0, 0) * M(1, 2) - M(0, 2) * M(1, 0)); 453 T(1,3) = 0; 454 455 T(2,0) = invdet * (M(1, 0) * M(2, 1) - M(1, 1) * M(2, 0)); 456 T(2,1) = -invdet * (M(0, 0) * M(2, 1) - M(0, 1) * M(2, 0)); 457 T(2,2) = invdet * (M(0, 0) * M(1, 1) - M(0, 1) * M(1, 0)); 458 T(2,3) = 0; 459 460 T(3,0) = -(M(3, 0) * T(0, 0) + M(3, 1) * T(1, 0) + M(3, 2) * T(2, 0)); 461 T(3,1) = -(M(3, 0) * T(0, 1) + M(3, 1) * T(1, 1) + M(3, 2) * T(2, 1)); 462 T(3,2) = -(M(3, 0) * T(0, 2) + M(3, 1) * T(1, 2) + M(3, 2) * T(2, 2)); 463 T(3,3) = 1; 464 465 memcpy(m, t, 16 * sizeof(float)); 466 } 467 468 static void mat_transpose(matrix m) 469 { 470 matrix t; 471 t[0 ] = m[0 ]; t[1 ] = m[4 ]; t[2 ] = m[8 ]; t[3 ] = m[12]; 472 t[4 ] = m[1 ]; t[5 ] = m[5 ]; t[6 ] = m[9 ]; t[7 ] = m[13]; 473 t[8 ] = m[2 ]; t[9 ] = m[6 ]; t[10] = m[10]; t[11] = m[14]; 474 t[12] = m[3 ]; t[13] = m[7 ]; t[14] = m[11]; t[15] = m[15]; 475 memcpy(m, t, sizeof(matrix)); 476 } 477 478 static void mat_mult_vec(vec3 v, matrix m) 479 { 480 vec3 t; 481 t[0] = M(0, 0) * v[0] + M(0, 1) * v[1] + M(0, 2) * v[2]; 482 t[1] = M(1, 0) * v[0] + M(1, 1) * v[1] + M(1, 2) * v[2]; 483 t[2] = M(2, 0) * v[0] + M(2, 1) * v[1] + M(2, 2) * v[2]; 484 485 v[0] = t[0]; 486 v[1] = t[1]; 487 v[2] = t[2]; 488 } 489 490 static inline void vec3_set(vec3 v, float x, float y, float z) 491 { 492 v[0] = x; 493 v[1] = y; 494 v[2] = z; 495 } 496 497 static inline void vec3_copy(vec3 r, vec3 v) 498 { 499 r[0] = v[0]; 500 r[1] = v[1]; 501 r[2] = v[2]; 502 } 503 504 static void vec4_normalize(vec4 r, vec4 v) 505 { 506 float len = sqrtf(v[0] * v[0] + v[1] * v[1] + v[2] * v[2] + v[3] * v[3]); 507 if(len != 0) 508 { 509 float ilen = 1.0f / len; 510 r[0] = v[0] * ilen; 511 r[1] = v[1] * ilen; 512 r[2] = v[2] * ilen; 513 r[3] = v[3] * ilen; 514 } 515 else 516 r[0] = r[1] = r[2] = r[3] = 0; 517 } 518 519 static void vec3_normalize(vec3 r, vec3 v) 520 { 521 float len = sqrtf(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]); 522 if(len != 0.0f) 523 { 524 float ilen = 1.0f / len; 525 r[0] = v[0] * ilen; 526 r[1] = v[1] * ilen; 527 r[2] = v[2] * ilen; 528 } 529 else 530 r[0] = r[1] = r[2] = 0; 531 } 532 533 static inline void quat_ident(vec4 q) 534 { 535 q[0] = q[1] = q[2] = 0; 536 q[3] = 1; 537 } 538 539 static void quat_mul(vec4 r, vec4 a, vec4 b) 540 { 541 r[0] = a[0] * b[3] + b[0] * a[3] + a[1] * b[2] - a[2] * b[1]; 542 r[1] = a[1] * b[3] + b[1] * a[3] + a[2] * b[0] - a[0] * b[2]; 543 r[2] = a[2] * b[3] + b[2] * a[3] + a[0] * b[1] - a[1] * b[0]; 544 r[3] = a[3] * b[3] - a[0] * b[0] - a[1] * b[1] - a[2] * b[2]; 545 } 546 547 static void quat_rotate(vec4 q, float a, float x, float y, float z) 548 { 549 float hs, len, ilen; 550 551 len = sqrtf(x * x + y * y + z * z); 552 if(len == 0) return; 553 ilen = 1.0f / len; 554 x *= ilen; 555 y *= ilen; 556 z *= ilen; 557 558 a = (a * (M_PI / 180.0f)) * 0.5f; 559 560 hs = sinf(a); 561 q[0] = x * hs; 562 q[1] = y * hs; 563 q[2] = z * hs; 564 q[3] = cosf(a); 565 } 566 567 static void quat_get_direction(vec3 v, vec4 q) 568 { 569 v[0] = 2.0f * (q[0] * q[2] - q[3] * q[1]); 570 v[1] = 2.0f * (q[1] * q[2] + q[3] * q[0]); 571 v[2] = 1.0f - 2.0f * (q[0] * q[0] + q[1] * q[1]); 572 } 573 574 #undef M 575 #undef T 576 577 static void init(GtkWidget *widget, gpointer data) 578 { 579 int i, err; 580 unsigned char white[16] = {0xff, 0xff, 0xff, 0xff, 581 0xff, 0xff, 0xff, 0xff, 582 0xff, 0xff, 0xff, 0xff, 583 0xff, 0xff, 0xff, 0xff}; 584 GdkGLContext *glcontext = gtk_widget_get_gl_context(widget); 585 GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable(widget); 586 GtkWidget *menu; 587 GList *curr; 588 589 if(!gdk_gl_drawable_gl_begin(gldrawable, glcontext)) 590 return; 591 592 err = glewInit(); 593 if(err != GLEW_OK) 594 { 595 g_message((char*)glewGetErrorString(err)); 596 _gl_error = 1; 597 } 598 599 glClearColor(0, 0, 0.4f, 0); 600 glDepthFunc(GL_LEQUAL); 601 glEnable(GL_DEPTH_TEST); 602 603 glLineWidth(3); 604 605 _gl_error = 0; 606 607 if(!GLEW_ARB_multitexture) 608 { 609 g_message("GL_ARB_multitexture is required for the 3D preview"); 610 _gl_error = 1; 611 } 612 613 if(!GLEW_ARB_texture_env_combine) 614 { 615 g_message("GL_ARB_texture_env_combine is required for the 3D preview"); 616 _gl_error = 1; 617 } 618 619 if(!GLEW_ARB_texture_env_dot3) 620 { 621 g_message("GL_ARB_texture_env_dot3 is required for the 3D preview"); 622 _gl_error = 1; 623 } 624 625 if(_gl_error) return; 626 627 glGenTextures(1, &diffuse_tex); 628 glGenTextures(1, &gloss_tex); 629 glGenTextures(1, &normal_tex); 630 glGenTextures(1, &white_tex); 631 632 glGetIntegerv(GL_MAX_TEXTURE_UNITS, &num_mtus); 633 634 glActiveTexture(GL_TEXTURE0); 635 glEnable(GL_TEXTURE_2D); 636 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); 637 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_DOT3_RGB); 638 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PRIMARY_COLOR); 639 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR); 640 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_TEXTURE); 641 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR); 642 643 glActiveTexture(GL_TEXTURE1); 644 glEnable(GL_TEXTURE_2D); 645 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); 646 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE); 647 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS); 648 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR); 649 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_TEXTURE); 650 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR); 651 652 glBindTexture(GL_TEXTURE_2D, white_tex); 653 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 654 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 655 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 656 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 657 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 4, 4, 0, 658 GL_LUMINANCE, GL_UNSIGNED_BYTE, white); 659 660 if(num_mtus > 2) 661 { 662 glActiveTexture(GL_TEXTURE2); 663 glEnable(GL_TEXTURE_2D); 664 glBindTexture(GL_TEXTURE_2D, white_tex); 665 } 666 667 has_glsl = GLEW_ARB_shader_objects && GLEW_ARB_vertex_shader && 668 GLEW_ARB_fragment_shader; 669 has_npot = GLEW_ARB_texture_non_power_of_two; 670 has_generate_mipmap = GLEW_SGIS_generate_mipmap; 671 has_aniso = GLEW_EXT_texture_filter_anisotropic; 672 673 if(has_glsl) 674 { 675 GLhandleARB prog, vert_shader, frag_shader; 676 int res, len, loc; 677 const char *sources[2]; 678 char *info; 679 680 /* Get max # of instructions and indirections supported by the hardware. 681 * Used to determine if parallax occlusion and relief mapping should be 682 * enabled and if the "ATI" version of parallax occlusion mapping should 683 * be used. 684 */ 685 if(GLEW_ARB_fragment_program) 686 { 687 glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, 1); 688 glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, 689 GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB, 690 &max_instructions); 691 glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, 692 GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB, 693 &max_indirections); 694 glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, 0); 695 } 696 697 vert_shader = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB); 698 glShaderSourceARB(vert_shader, 1, &vert_source, 0); 699 glCompileShaderARB(vert_shader); 700 glGetObjectParameterivARB(vert_shader, GL_OBJECT_COMPILE_STATUS_ARB, &res); 701 if(!res) 702 { 703 glGetObjectParameterivARB(vert_shader, GL_OBJECT_INFO_LOG_LENGTH_ARB, &len); 704 info = g_malloc(len + 1); 705 glGetInfoLogARB(vert_shader, len, 0, info); 706 g_message("Vertex shader failed to compile:\n%s\n", info); 707 g_free(info); 708 } 709 710 prog = glCreateProgramObjectARB(); 711 glAttachObjectARB(prog, vert_shader); 712 713 frag_shader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB); 714 glShaderSourceARB(frag_shader, 1, &normal_frag_source, 0); 715 glCompileShaderARB(frag_shader); 716 glGetObjectParameterivARB(frag_shader, GL_OBJECT_COMPILE_STATUS_ARB, &res); 717 if(res) 718 glAttachObjectARB(prog, frag_shader); 719 else 720 { 721 glGetObjectParameterivARB(frag_shader, GL_OBJECT_INFO_LOG_LENGTH_ARB, &len); 722 info = g_malloc(len + 1); 723 glGetInfoLogARB(frag_shader, len, 0, info); 724 g_message("Normal mapping fragment shader failed to compile:\n%s\n", 725 info); 726 g_free(info); 727 glDeleteObjectARB(prog); 728 prog = 0; 729 } 730 glDeleteObjectARB(frag_shader); 731 732 if(prog) 733 { 734 glLinkProgramARB(prog); 735 glGetObjectParameterivARB(prog, GL_OBJECT_LINK_STATUS_ARB, &res); 736 737 if(!res) 738 { 739 glGetObjectParameterivARB(prog, GL_OBJECT_INFO_LOG_LENGTH_ARB, &len); 740 info = g_malloc(len + 1); 741 glGetInfoLogARB(prog, len, 0, info); 742 g_message("Normal mapping program failed to link:\n%s\n", info); 743 g_free(info); 744 glDeleteObjectARB(prog); 745 prog = 0; 746 } 747 } 748 749 programs[BUMPMAP_NORMAL] = prog; 750 751 prog = glCreateProgramObjectARB(); 752 glAttachObjectARB(prog, vert_shader); 753 754 frag_shader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB); 755 glShaderSourceARB(frag_shader, 1, ¶llax_frag_source, 0); 756 glCompileShaderARB(frag_shader); 757 glGetObjectParameterivARB(frag_shader, GL_OBJECT_COMPILE_STATUS_ARB, &res); 758 if(res) 759 glAttachObjectARB(prog, frag_shader); 760 else 761 { 762 glGetObjectParameterivARB(frag_shader, GL_OBJECT_INFO_LOG_LENGTH_ARB, &len); 763 info = g_malloc(len + 1); 764 glGetInfoLogARB(frag_shader, len, 0, info); 765 g_message("Parallax mapping fragment shader failed to compile:\n%s\n", 766 info); 767 g_free(info); 768 glDeleteObjectARB(prog); 769 prog = 0; 770 } 771 glDeleteObjectARB(frag_shader); 772 773 if(prog) 774 { 775 glLinkProgramARB(prog); 776 glGetObjectParameterivARB(prog, GL_OBJECT_LINK_STATUS_ARB, &res); 777 778 if(!res) 779 { 780 glGetObjectParameterivARB(prog, GL_OBJECT_INFO_LOG_LENGTH_ARB, &len); 781 info = g_malloc(len + 1); 782 glGetInfoLogARB(prog, len, 0, info); 783 g_message("Parallax mapping program failed to link:\n%s\n", info); 784 g_free(info); 785 glDeleteObjectARB(prog); 786 prog = 0; 787 } 788 } 789 790 programs[BUMPMAP_PARALLAX] = prog; 791 792 if(max_instructions >= 200) 793 { 794 prog = glCreateProgramObjectARB(); 795 glAttachObjectARB(prog, vert_shader); 796 797 if(max_indirections < 100) 798 sources[0] = "#define ATI 1\n"; 799 else 800 sources[0] = ""; 801 802 sources[1] = pom_frag_source; 803 804 frag_shader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB); 805 glShaderSourceARB(frag_shader, 2, sources, 0); 806 glCompileShaderARB(frag_shader); 807 glGetObjectParameterivARB(frag_shader, GL_OBJECT_COMPILE_STATUS_ARB, &res); 808 if(res) 809 glAttachObjectARB(prog, frag_shader); 810 else 811 { 812 glGetObjectParameterivARB(frag_shader, GL_OBJECT_INFO_LOG_LENGTH_ARB, &len); 813 info = g_malloc(len + 1); 814 glGetInfoLogARB(frag_shader, len, 0, info); 815 g_message("Parallax Occlusion mapping fragment shader failed to compile:\n%s\n", 816 info); 817 g_free(info); 818 glDeleteObjectARB(prog); 819 prog = 0; 820 } 821 glDeleteObjectARB(frag_shader); 822 823 if(prog) 824 { 825 glLinkProgramARB(prog); 826 glGetObjectParameterivARB(prog, GL_OBJECT_LINK_STATUS_ARB, &res); 827 828 if(!res) 829 { 830 glGetObjectParameterivARB(prog, GL_OBJECT_INFO_LOG_LENGTH_ARB, &len); 831 info = g_malloc(len + 1); 832 glGetInfoLogARB(prog, len, 0, info); 833 g_message("Parallax Occlusion mapping program failed to link:\n%s\n", 834 info); 835 g_free(info); 836 glDeleteObjectARB(prog); 837 prog = 0; 838 } 839 } 840 841 programs[BUMPMAP_POM] = prog; 842 } 843 else 844 programs[BUMPMAP_POM] = 0; 845 846 if(max_instructions >= 200 && max_indirections >= 100) 847 { 848 prog = glCreateProgramObjectARB(); 849 glAttachObjectARB(prog, vert_shader); 850 851 frag_shader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB); 852 glShaderSourceARB(frag_shader, 1, &relief_frag_source, 0); 853 glCompileShaderARB(frag_shader); 854 glGetObjectParameterivARB(frag_shader, GL_OBJECT_COMPILE_STATUS_ARB, &res); 855 if(res) 856 glAttachObjectARB(prog, frag_shader); 857 else 858 { 859 glGetObjectParameterivARB(frag_shader, GL_OBJECT_INFO_LOG_LENGTH_ARB, &len); 860 info = g_malloc(len + 1); 861 glGetInfoLogARB(frag_shader, len, 0, info); 862 g_message("Relief mapping fragment shader failed to compile:\n%s\n", 863 info); 864 g_free(info); 865 glDeleteObjectARB(prog); 866 prog = 0; 867 } 868 glDeleteObjectARB(frag_shader); 869 870 if(prog) 871 { 872 glLinkProgramARB(prog); 873 glGetObjectParameterivARB(prog, GL_OBJECT_LINK_STATUS_ARB, &res); 874 875 if(!res) 876 { 877 glGetObjectParameterivARB(prog, GL_OBJECT_INFO_LOG_LENGTH_ARB, &len); 878 info = g_malloc(len + 1); 879 glGetInfoLogARB(prog, len, 0, info); 880 g_message("Relief mapping program failed to link:\n%s\n", info); 881 g_free(info); 882 glDeleteObjectARB(prog); 883 prog = 0; 884 } 885 } 886 887 programs[BUMPMAP_RELIEF] = prog; 888 } 889 else 890 programs[BUMPMAP_RELIEF] = 0; 891 892 glDeleteObjectARB(vert_shader); 893 894 if(programs[BUMPMAP_NORMAL]) 895 { 896 glUseProgramObjectARB(programs[BUMPMAP_NORMAL]); 897 loc = glGetUniformLocationARB(programs[BUMPMAP_NORMAL], "sNormal"); 898 glUniform1iARB(loc, 0); 899 loc = glGetUniformLocationARB(programs[BUMPMAP_NORMAL], "sDiffuse"); 900 glUniform1iARB(loc, 1); 901 loc = glGetUniformLocationARB(programs[BUMPMAP_NORMAL], "sGloss"); 902 glUniform1iARB(loc, 2); 903 } 904 905 if(programs[BUMPMAP_PARALLAX]) 906 { 907 glUseProgramObjectARB(programs[BUMPMAP_PARALLAX]); 908 loc = glGetUniformLocationARB(programs[BUMPMAP_PARALLAX], "sNormal"); 909 glUniform1iARB(loc, 0); 910 loc = glGetUniformLocationARB(programs[BUMPMAP_PARALLAX], "sDiffuse"); 911 glUniform1iARB(loc, 1); 912 loc = glGetUniformLocationARB(programs[BUMPMAP_PARALLAX], "sGloss"); 913 glUniform1iARB(loc, 2); 914 } 915 916 if(programs[BUMPMAP_POM]) 917 { 918 glUseProgramObjectARB(programs[BUMPMAP_POM]); 919 loc = glGetUniformLocationARB(programs[BUMPMAP_POM], "sNormal"); 920 glUniform1iARB(loc, 0); 921 loc = glGetUniformLocationARB(programs[BUMPMAP_POM], "sDiffuse"); 922 glUniform1iARB(loc, 1); 923 loc = glGetUniformLocationARB(programs[BUMPMAP_POM], "sGloss"); 924 glUniform1iARB(loc, 2); 925 loc = glGetUniformLocationARB(programs[BUMPMAP_POM], "depth_factor"); 926 glUniform1fARB(loc, depth_factor); 927 } 928 929 if(programs[BUMPMAP_RELIEF]) 930 { 931 glUseProgramObjectARB(programs[BUMPMAP_RELIEF]); 932 loc = glGetUniformLocationARB(programs[BUMPMAP_RELIEF], "sNormal"); 933 glUniform1iARB(loc, 0); 934 loc = glGetUniformLocationARB(programs[BUMPMAP_RELIEF], "sDiffuse"); 935 glUniform1iARB(loc, 1); 936 loc = glGetUniformLocationARB(programs[BUMPMAP_RELIEF], "sGloss"); 937 glUniform1iARB(loc, 2); 938 loc = glGetUniformLocationARB(programs[BUMPMAP_RELIEF], "depth_factor"); 939 glUniform1fARB(loc, depth_factor); 940 } 941 942 glUseProgramObjectARB(0); 943 944 for(i = 0; i < OBJECT_MAX; ++i) 945 { 946 glGenBuffersARB(1, &object_info[i].vbo); 947 glBindBufferARB(GL_ARRAY_BUFFER_ARB, object_info[i].vbo); 948 glBufferDataARB(GL_ARRAY_BUFFER_ARB, 949 object_info[i].num_verts * 16 * sizeof(float), 950 object_info[i].verts, GL_STATIC_DRAW_ARB); 951 } 952 953 glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); 954 955 menu = gtk_option_menu_get_menu(GTK_OPTION_MENU(bumpmapping_opt)); 956 curr = gtk_container_get_children(GTK_CONTAINER(menu)); 957 for(i = 0; i < BUMPMAP_MAX && curr; ++i) 958 { 959 if(programs[i] == 0) 960 gtk_widget_set_sensitive(GTK_WIDGET(curr->data), 0); 961 curr = curr->next; 962 } 963 } 964 else 965 { 966 gtk_widget_set_sensitive(gloss_opt, 0); 967 gtk_widget_set_sensitive(bumpmapping_opt, 0); 968 gtk_widget_set_sensitive(specular_check, 0); 969 gtk_widget_set_sensitive(specular_exp_range, 0); 970 gtk_widget_set_sensitive(ambient_color_btn, 0); 971 gtk_widget_set_sensitive(diffuse_color_btn, 0); 972 gtk_widget_set_sensitive(specular_color_btn, 0); 973 } 974 975 object_rot[0] = object_rot[1] = object_rot[2] = 0; 976 light_rot[0] = light_rot[1] = light_rot[2] = 0; 977 scene_rot[0] = scene_rot[1] = scene_rot[2] = 0; 978 zoom = 2; 979 980 gdk_gl_drawable_gl_end(gldrawable); 981 } 982 983 static void draw_object(int obj, vec3 l, matrix m) 984 { 985 const int vsize = 16 * sizeof(float); 986 int i; 987 vec3 c, t, b, n; 988 vec2 uv; 989 float *verts; 990 unsigned short *indices; 991 992 if(obj < 0 || obj >= OBJECT_MAX) return; 993 994 if(has_glsl) 995 { 996 glBindBufferARB(GL_ARRAY_BUFFER_ARB, object_info[obj].vbo); 997 998 #define OFFSET(x) ((void*)((x) * sizeof(float))) 999 1000 glVertexPointer(4, GL_FLOAT, vsize, OFFSET(0)); 1001 glNormalPointer(GL_FLOAT, vsize, OFFSET(12)); 1002 glClientActiveTexture(GL_TEXTURE4); 1003 glTexCoordPointer(3, GL_FLOAT, vsize, OFFSET(9)); 1004 glEnableClientState(GL_TEXTURE_COORD_ARRAY); 1005 glClientActiveTexture(GL_TEXTURE3); 1006 glTexCoordPointer(3, GL_FLOAT, vsize, OFFSET(6)); 1007 glEnableClientState(GL_TEXTURE_COORD_ARRAY); 1008 glClientActiveTexture(GL_TEXTURE0); 1009 glTexCoordPointer(2, GL_FLOAT, vsize, OFFSET(4)); 1010 glEnableClientState(GL_TEXTURE_COORD_ARRAY); 1011 glEnableClientState(GL_VERTEX_ARRAY); 1012 glEnableClientState(GL_NORMAL_ARRAY); 1013 1014 #undef OFFSET 1015 1016 glDrawElements(GL_TRIANGLES, object_info[obj].num_indices, 1017 GL_UNSIGNED_SHORT, object_info[obj].indices); 1018 1019 glDisableClientState(GL_VERTEX_ARRAY); 1020 glDisableClientState(GL_NORMAL_ARRAY); 1021 glClientActiveTexture(GL_TEXTURE4); 1022 glDisableClientState(GL_TEXTURE_COORD_ARRAY); 1023 glClientActiveTexture(GL_TEXTURE3); 1024 glDisableClientState(GL_TEXTURE_COORD_ARRAY); 1025 glClientActiveTexture(GL_TEXTURE0); 1026 glDisableClientState(GL_TEXTURE_COORD_ARRAY); 1027 1028 glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); 1029 } 1030 else 1031 { 1032 verts = object_info[obj].verts; 1033 indices = object_info[obj].indices; 1034 1035 glBegin(GL_TRIANGLES); 1036 for(i = 0; i < object_info[obj].num_indices; ++i) 1037 { 1038 vec3_copy(t, &verts[16 * indices[i] + 6]); 1039 vec3_copy(b, &verts[16 * indices[i] + 9]); 1040 vec3_copy(n, &verts[16 * indices[i] + 12]); 1041 mat_mult_vec(t, m); 1042 mat_mult_vec(b, m); 1043 mat_mult_vec(n, m); 1044 c[0] = (l[0] * t[0] + l[1] * t[1] + l[2] * t[2]); 1045 c[1] = (l[0] * b[0] + l[1] * b[1] + l[2] * b[2]); 1046 c[2] = (l[0] * n[0] + l[1] * n[1] + l[2] * n[2]); 1047 vec3_normalize(c, c); 1048 c[0] = c[0] * 0.5f + 0.5f; 1049 c[1] = c[1] * 0.5f + 0.5f; 1050 c[2] = c[2] * 0.5f + 0.5f; 1051 1052 uv[0] = verts[16 * indices[i] + 4] * uvscale[0]; 1053 uv[1] = verts[16 * indices[i] + 5] * uvscale[1]; 1054 1055 glColor3fv(c); 1056 glNormal3fv(&verts[16 * indices[i] + 12]); 1057 glMultiTexCoord2fv(GL_TEXTURE0, uv); 1058 glMultiTexCoord2fv(GL_TEXTURE1, uv); 1059 if(num_mtus > 2) 1060 glMultiTexCoord2fv(GL_TEXTURE2, uv); 1061 glVertex3fv(&verts[16 * indices[i]]); 1062 } 1063 glEnd(); 1064 } 1065 } 1066 1067 static gint expose(GtkWidget *widget, GdkEventExpose *event) 1068 { 1069 matrix m; 1070 vec3 l; 1071 vec4 qx, qy, qz, qt, qrot; 1072 int loc; 1073 GdkGLContext *glcontext = gtk_widget_get_gl_context(widget); 1074 GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable(widget); 1075 GLhandleARB prog = 0; 1076 1077 if(event->count > 0) return(1); 1078 1079 if(!gdk_gl_drawable_gl_begin(gldrawable, glcontext)) 1080 return(1); 1081 1082 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 1083 1084 if(_gl_error) 1085 { 1086 gdk_gl_drawable_swap_buffers(gldrawable); 1087 gdk_gl_drawable_gl_end(gldrawable); 1088 return(1); 1089 } 1090 1091 glMatrixMode(GL_MODELVIEW); 1092 glLoadIdentity(); 1093 glRotatef(scene_rot[0], 1, 0, 0); 1094 glRotatef(scene_rot[1], 0, 1, 0); 1095 glRotatef(scene_rot[2], 0, 0, 1); 1096 glTranslatef(0, 0, -zoom); 1097 glRotatef(object_rot[0], 1, 0, 0); 1098 glRotatef(object_rot[1], 0, 1, 0); 1099 glRotatef(object_rot[2], 0, 0, 1); 1100 1101 glGetFloatv(GL_MODELVIEW_MATRIX, m); 1102 mat_invert(m); 1103 mat_transpose(m); 1104 1105 quat_ident(qx); 1106 quat_ident(qy); 1107 quat_ident(qz); 1108 quat_rotate(qx, -light_rot[0], 1, 0, 0); 1109 quat_rotate(qy, -light_rot[1], 0, 1, 0); 1110 quat_rotate(qz, -light_rot[2], 0, 0, 1); 1111 quat_mul(qt, qx, qy); 1112 quat_mul(qrot, qt, qz); 1113 vec4_normalize(qrot, qrot); 1114 quat_get_direction(l, qrot); 1115 1116 if(has_glsl) 1117 { 1118 prog = programs[bumpmapping]; 1119 glUseProgramObjectARB(prog); 1120 loc = glGetUniformLocationARB(prog, "specular"); 1121 glUniform1iARB(loc, specular); 1122 loc = glGetUniformLocationARB(prog, "ambient_color"); 1123 glUniform3fvARB(loc, 1, ambient_color); 1124 loc = glGetUniformLocationARB(prog, "diffuse_color"); 1125 glUniform3fvARB(loc, 1, diffuse_color); 1126 loc = glGetUniformLocationARB(prog, "specular_color"); 1127 glUniform3fvARB(loc, 1, specular_color); 1128 loc = glGetUniformLocationARB(prog, "specular_exp"); 1129 glUniform1fARB(loc, specular_exp); 1130 loc = glGetUniformLocationARB(prog, "lightDir"); 1131 glUniform3fvARB(loc, 1, l); 1132 loc = glGetUniformLocationARB(prog, "uvscale"); 1133 glUniform2fvARB(loc, 1, uvscale); 1134 } 1135 1136 draw_object(object_type, l, m); 1137 1138 if(has_glsl) 1139 glUseProgramObjectARB(0); 1140 1141 gdk_gl_drawable_swap_buffers(gldrawable); 1142 gdk_gl_drawable_gl_end(gldrawable); 1143 1144 return(1); 1145 } 1146 1147 static gint configure(GtkWidget *widget, GdkEventConfigure *event) 1148 { 1149 GdkGLContext *glcontext; 1150 GdkGLDrawable *gldrawable; 1151 int w, h; 1152 1153 g_return_val_if_fail(widget && event, FALSE); 1154 1155 glcontext = gtk_widget_get_gl_context(widget); 1156 gldrawable = gtk_widget_get_gl_drawable(widget); 1157 1158 if(!gdk_gl_drawable_gl_begin(gldrawable,glcontext)) 1159 return(1); 1160 1161 w = widget->allocation.width; 1162 h = widget->allocation.height; 1163 1164 glViewport(0, 0, w, h); 1165 1166 glMatrixMode(GL_PROJECTION); 1167 glLoadIdentity(); 1168 gluPerspective(60, (float)w / (float)h, 0.1f, 100); 1169 1170 glMatrixMode(GL_MODELVIEW); 1171 glLoadIdentity(); 1172 1173 gdk_gl_drawable_gl_end(gldrawable); 1174 1175 return(1); 1176 } 1177 1178 static gint button_press(GtkWidget *widget, GdkEventButton *event) 1179 { 1180 mx = event->x; 1181 my = event->y; 1182 return(1); 1183 } 1184 1185 static gint motion_notify(GtkWidget *widget, GdkEventMotion *event) 1186 { 1187 int x, y; 1188 float dx, dy; 1189 float *rot; 1190 GdkModifierType state; 1191 1192 if(event->is_hint) 1193 { 1194 #ifndef WIN32 1195 gdk_window_get_pointer(event->window, &x, &y, &state); 1196 #endif 1197 } 1198 else 1199 { 1200 x = event->x; 1201 y = event->y; 1202 state = event->state; 1203 } 1204 1205 dx = -0.25f * (float)(mx - x); 1206 dy = -0.25f * (float)(my - y); 1207 1208 rot = object_rot; 1209 if(rotate_type == ROTATE_LIGHT) 1210 rot = light_rot; 1211 else if(rotate_type == ROTATE_SCENE) 1212 rot = scene_rot; 1213 1214 if(state & GDK_BUTTON1_MASK) 1215 { 1216 rot[1] += cosf(rot[0] / 180.0f * M_PI) * dx; 1217 rot[2] -= sinf(rot[0] / 180.0f * M_PI) * dx; 1218 rot[0] += dy; 1219 } 1220 else if(state & GDK_BUTTON3_MASK) 1221 { 1222 zoom += (-dy * 0.2f); 1223 } 1224 1225 mx = x; 1226 my = y; 1227 1228 gtk_widget_queue_draw(widget); 1229 1230 return(1); 1231 } 1232 1233 static void window_destroy(GtkWidget *widget, gpointer data) 1234 { 1235 gtk_widget_destroy(glarea); 1236 _active = 0; 1237 } 1238 1239 static void get_nearest_pot(int w, int h, int *w_pot, int *h_pot) 1240 { 1241 int n, next_pot, prev_pot, d1, d2; 1242 1243 if(!IS_POT(w)) 1244 { 1245 next_pot = 1; 1246 for(n = 1; n <= 12; ++n) 1247 { 1248 prev_pot = next_pot; 1249 next_pot = 1 << n; 1250 if(next_pot >= w) break; 1251 } 1252 1253 if(next_pot < w) 1254 *w_pot = next_pot; 1255 else 1256 { 1257 d1 = w - prev_pot; 1258 d2 = next_pot - w; 1259 if(d1 < d2) 1260 *w_pot = prev_pot; 1261 else 1262 *w_pot = next_pot; 1263 } 1264 } 1265 else 1266 *w_pot = w; 1267 1268 if(!IS_POT(h)) 1269 { 1270 next_pot = 1; 1271 for(n = 1; n <= 12; ++n) 1272 { 1273 prev_pot = next_pot; 1274 next_pot = 1 << n; 1275 if(next_pot >= h) break; 1276 } 1277 1278 if(next_pot < h) 1279 *h_pot = next_pot; 1280 else 1281 { 1282 d1 = h - prev_pot; 1283 d2 = next_pot - h; 1284 if(d1 < d2) 1285 *h_pot = prev_pot; 1286 else 1287 *h_pot = next_pot; 1288 } 1289 } 1290 else 1291 *h_pot = h; 1292 } 1293 1294 static void diffusemap_callback(gint32 id, gpointer data) 1295 { 1296 GimpDrawable *drawable; 1297 int w, h, bpp, mipw, miph, n; 1298 int w_pot, h_pot; 1299 unsigned char *pixels, *tmp, *mip; 1300 GimpPixelRgn src_rgn; 1301 GLenum type = 0; 1302 1303 if(_gl_error) return; 1304 1305 if(id == normalmap_drawable_id) 1306 { 1307 if(white_tex != 0) 1308 { 1309 glActiveTexture(GL_TEXTURE1); 1310 glBindTexture(GL_TEXTURE_2D, white_tex); 1311 } 1312 gtk_widget_queue_draw(glarea); 1313 return; 1314 } 1315 1316 drawable = gimp_drawable_get(id); 1317 1318 w = drawable->width; 1319 h = drawable->height; 1320 bpp = drawable->bpp; 1321 1322 switch(bpp) 1323 { 1324 case 1: type = GL_LUMINANCE; break; 1325 case 2: type = GL_LUMINANCE_ALPHA; break; 1326 case 3: type = GL_RGB; break; 1327 case 4: type = GL_RGBA; break; 1328 } 1329 1330 pixels = g_malloc(w * h * bpp); 1331 gimp_pixel_rgn_init(&src_rgn, drawable, 0, 0, w, h, 0, 0); 1332 gimp_pixel_rgn_get_rect(&src_rgn, pixels, 0, 0, w, h); 1333 1334 if(!has_npot && !(IS_POT(w) && IS_POT(h))) 1335 { 1336 get_nearest_pot(w, h, &w_pot, &h_pot); 1337 tmp = g_malloc(h_pot * w_pot * bpp); 1338 scale_pixels(tmp, w_pot, h_pot, pixels, w, h, bpp); 1339 g_free(pixels); 1340 pixels = tmp; 1341 w = w_pot; 1342 h = h_pot; 1343 } 1344 1345 glActiveTexture(GL_TEXTURE1); 1346 glBindTexture(GL_TEXTURE_2D, diffuse_tex); 1347 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 1348 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 1349 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 1350 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); 1351 if(has_aniso) 1352 glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, &anisotropy); 1353 if(has_generate_mipmap) 1354 glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_TRUE); 1355 glTexImage2D(GL_TEXTURE_2D, 0, type, w, h, 0, 1356 type, GL_UNSIGNED_BYTE, pixels); 1357 1358 if(!has_generate_mipmap) 1359 { 1360 mipw = w; 1361 miph = h; 1362 n = 0; 1363 while((mipw != 1) && (miph != 1)) 1364 { 1365 if(mipw > 1) mipw >>= 1; 1366 if(miph > 1) miph >>= 1; 1367 ++n; 1368 mip = g_malloc(mipw * miph * bpp); 1369 scale_pixels(mip, mipw, miph, pixels, w, h, bpp); 1370 glTexImage2D(GL_TEXTURE_2D, n, bpp, mipw, miph, 0, 1371 (bpp == 4) ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE, 1372 mip); 1373 g_free(mip); 1374 } 1375 } 1376 1377 g_free(pixels); 1378 1379 gimp_drawable_detach(drawable); 1380 1381 gtk_widget_queue_draw(glarea); 1382 } 1383 1384 static void glossmap_callback(gint32 id, gpointer data) 1385 { 1386 GimpDrawable *drawable; 1387 int w, h, bpp, mipw, miph, n; 1388 int w_pot, h_pot; 1389 unsigned char *pixels, *tmp, *mip; 1390 GimpPixelRgn src_rgn; 1391 GLenum type = 0; 1392 1393 if(_gl_error) return; 1394 if(num_mtus < 3) return; 1395 1396 if(id == normalmap_drawable_id) 1397 { 1398 if(white_tex != 0) 1399 { 1400 glActiveTexture(GL_TEXTURE2); 1401 glBindTexture(GL_TEXTURE_2D, white_tex); 1402 } 1403 gtk_widget_queue_draw(glarea); 1404 return; 1405 } 1406 1407 drawable = gimp_drawable_get(id); 1408 1409 w = drawable->width; 1410 h = drawable->height; 1411 bpp = drawable->bpp; 1412 1413 switch(bpp) 1414 { 1415 case 1: type = GL_LUMINANCE; break; 1416 case 2: type = GL_LUMINANCE_ALPHA; break; 1417 case 3: type = GL_RGB; break; 1418 case 4: type = GL_RGBA; break; 1419 } 1420 1421 pixels = g_malloc(w * h * bpp); 1422 gimp_pixel_rgn_init(&src_rgn, drawable, 0, 0, w, h, 0, 0); 1423 gimp_pixel_rgn_get_rect(&src_rgn, pixels, 0, 0, w, h); 1424 1425 if(!has_npot && !(IS_POT(w) && IS_POT(h))) 1426 { 1427 get_nearest_pot(w, h, &w_pot, &h_pot); 1428 tmp = g_malloc(h_pot * w_pot * bpp); 1429 scale_pixels(tmp, w_pot, h_pot, pixels, w, h, bpp); 1430 g_free(pixels); 1431 pixels = tmp; 1432 w = w_pot; 1433 h = h_pot; 1434 } 1435 1436 glActiveTexture(GL_TEXTURE2); 1437 glBindTexture(GL_TEXTURE_2D, gloss_tex); 1438 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 1439 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 1440 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 1441 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); 1442 if(has_aniso) 1443 glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, &anisotropy); 1444 if(has_generate_mipmap) 1445 glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_TRUE); 1446 glTexImage2D(GL_TEXTURE_2D, 0, type, w, h, 0, 1447 type, GL_UNSIGNED_BYTE, pixels); 1448 1449 if(!has_generate_mipmap) 1450 { 1451 mipw = w; 1452 miph = h; 1453 n = 0; 1454 while((mipw != 1) && (miph != 1)) 1455 { 1456 if(mipw > 1) mipw >>= 1; 1457 if(miph > 1) miph >>= 1; 1458 ++n; 1459 mip = g_malloc(mipw * miph * bpp); 1460 scale_pixels(mip, mipw, miph, pixels, w, h, bpp); 1461 glTexImage2D(GL_TEXTURE_2D, n, bpp, mipw, miph, 0, 1462 (bpp == 4) ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE, 1463 mip); 1464 g_free(mip); 1465 } 1466 } 1467 1468 g_free(pixels); 1469 1470 gimp_drawable_detach(drawable); 1471 1472 gtk_widget_queue_draw(glarea); 1473 } 1474 1475 static void object_selected(GtkWidget *widget, gpointer data) 1476 { 1477 object_type = (int)(long)data; 1478 gtk_widget_queue_draw(glarea); 1479 } 1480 1481 static void bumpmapping_clicked(GtkWidget *widget, gpointer data) 1482 { 1483 bumpmapping = (int)(long)data; 1484 gtk_widget_queue_draw(glarea); 1485 } 1486 1487 static void toggle_fullscreen(GtkWidget *widget, gpointer data) 1488 { 1489 fullscreen = !fullscreen; 1490 if(fullscreen) 1491 { 1492 gtk_window_fullscreen(GTK_WINDOW(window)); 1493 gtk_widget_hide(controls_table); 1494 } 1495 else 1496 { 1497 gtk_window_unfullscreen(GTK_WINDOW(window)); 1498 gtk_widget_show(controls_table); 1499 } 1500 } 1501 1502 static void toggle_clicked(GtkWidget *widget, gpointer data) 1503 { 1504 *((int*)data) = !(*((int*)data)); 1505 gtk_widget_queue_draw(glarea); 1506 } 1507 1508 static void specular_exp_changed(GtkWidget *widget, gpointer data) 1509 { 1510 specular_exp = gtk_range_get_value(GTK_RANGE(widget)); 1511 gtk_widget_queue_draw(glarea); 1512 } 1513 1514 static void color_changed(GtkWidget *widget, gpointer data) 1515 { 1516 float *c = (float*)data; 1517 GimpRGB color; 1518 1519 gimp_color_button_get_color(GIMP_COLOR_BUTTON(widget), &color); 1520 c[0] = color.r; 1521 c[1] = color.g; 1522 c[2] = color.b; 1523 1524 gtk_widget_queue_draw(glarea); 1525 } 1526 1527 static void rotate_type_toggled(GtkWidget *widget, gpointer data) 1528 { 1529 if(gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(widget))) 1530 rotate_type = (int)(long)data; 1531 } 1532 1533 static void uvscale_changed(GtkWidget *widget, gpointer data) 1534 { 1535 int n = (int)(long)data; 1536 float v = gtk_spin_button_get_value(GTK_SPIN_BUTTON(widget)); 1537 GtkWidget *btn = g_object_get_data(G_OBJECT(widget), "chain"); 1538 1539 uvscale[n] = v; 1540 if(gimp_chain_button_get_active(GIMP_CHAIN_BUTTON(btn))) 1541 { 1542 if(n == 0) 1543 { 1544 uvscale[1] = v; 1545 gtk_spin_button_set_value(GTK_SPIN_BUTTON(uvscale_spin2), v); 1546 } 1547 else 1548 { 1549 uvscale[0] = v; 1550 gtk_spin_button_set_value(GTK_SPIN_BUTTON(uvscale_spin1), v); 1551 } 1552 } 1553 1554 gtk_widget_queue_draw(glarea); 1555 } 1556 1557 static void reset_view_clicked(GtkWidget *widget, gpointer data) 1558 { 1559 GimpRGB c; 1560 1561 object_rot[0] = object_rot[1] = object_rot[2] = 0; 1562 light_rot[0] = light_rot[1] = light_rot[2] = 0; 1563 scene_rot[0] = scene_rot[1] = scene_rot[2] = 0; 1564 zoom = 2; 1565 1566 specular_exp = 32.0f; 1567 ambient_color[0] = ambient_color[1] = ambient_color[2] = 0.2f; 1568 diffuse_color[0] = diffuse_color[1] = diffuse_color[2] = 1.0f; 1569 specular_color[0] = specular_color[1] = specular_color[2] = 1.0f; 1570 uvscale[0] = uvscale[1] = 1; 1571 1572 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(rotate_obj_btn), 1); 1573 gtk_option_menu_set_history(GTK_OPTION_MENU(object_opt), 0); 1574 gtk_option_menu_set_history(GTK_OPTION_MENU(bumpmapping_opt), 0); 1575 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(specular_check), 0); 1576 gtk_range_set_value(GTK_RANGE(specular_exp_range), specular_exp); 1577 gtk_spin_button_set_value(GTK_SPIN_BUTTON(uvscale_spin1), uvscale[0]); 1578 gtk_spin_button_set_value(GTK_SPIN_BUTTON(uvscale_spin2), uvscale[1]); 1579 1580 gimp_rgb_set(&c, ambient_color[0], ambient_color[1], ambient_color[2]); 1581 gimp_color_button_set_color(GIMP_COLOR_BUTTON(ambient_color_btn), &c); 1582 gimp_rgb_set(&c, diffuse_color[0], diffuse_color[1], diffuse_color[2]); 1583 gimp_color_button_set_color(GIMP_COLOR_BUTTON(diffuse_color_btn), &c); 1584 gimp_rgb_set(&c, specular_color[0], specular_color[1], specular_color[2]); 1585 gimp_color_button_set_color(GIMP_COLOR_BUTTON(specular_color_btn), &c); 1586 1587 bumpmapping = 0; 1588 specular = 0; 1589 rotate_type = ROTATE_OBJECT; 1590 object_type = OBJECT_QUAD; 1591 1592 gtk_widget_queue_draw(glarea); 1593 } 1594 1595 void show_3D_preview(GimpDrawable *drawable) 1596 { 1597 int i; 1598 GtkWidget *vbox; 1599 GtkWidget *table, *table2; 1600 GtkWidget *opt; 1601 GtkWidget *menu; 1602 GtkWidget *menuitem; 1603 GtkWidget *check; 1604 GtkWidget *btn; 1605 GtkWidget *hscale; 1606 GtkWidget *label; 1607 GtkObject *adj; 1608 GtkWidget *spin; 1609 GtkWidget *toolbar; 1610 GtkToolItem *toolbtn; 1611 GtkTooltips *tooltips; 1612 GtkWidget *icon; 1613 GdkPixbuf *pixbuf; 1614 GSList *group = 0; 1615 GdkGLConfig *glconfig; 1616 GimpRGB color; 1617 const char *object_strings[OBJECT_MAX] = 1618 { 1619 "Quad", "Cube", "Sphere", "Torus", "Teapot" 1620 }; 1621 const char *bumpmap_strings[BUMPMAP_MAX] = 1622 { 1623 "Normal", "Parallax", "Parallax Occlusion", "Relief" 1624 }; 1625 1626 bumpmapping = 0; 1627 specular = 0; 1628 specular_exp = 32.0f; 1629 ambient_color[0] = ambient_color[1] = ambient_color[2] = 0.2f; 1630 diffuse_color[0] = diffuse_color[1] = diffuse_color[2] = 1.0f; 1631 specular_color[0] = specular_color[1] = specular_color[2] = 1.0f; 1632 uvscale[0] = uvscale[1] = 1; 1633 1634 if(_active) return; 1635 1636 normalmap_drawable_id = drawable->drawable_id; 1637 1638 glconfig = gdk_gl_config_new_by_mode(GDK_GL_MODE_RGBA | 1639 GDK_GL_MODE_DEPTH | 1640 GDK_GL_MODE_DOUBLE); 1641 if(glconfig == 0) 1642 { 1643 g_message("Could not initialize OpenGL context!"); 1644 return; 1645 } 1646 1647 window = gtk_window_new(GTK_WINDOW_TOPLEVEL); 1648 gtk_window_set_title(GTK_WINDOW(window), "Normalmap - 3D Preview"); 1649 gtk_container_set_resize_mode(GTK_CONTAINER(window), GTK_RESIZE_QUEUE); 1650 gtk_container_set_reallocate_redraws(GTK_CONTAINER(window), TRUE); 1651 gtk_signal_connect(GTK_OBJECT(window), "destroy", 1652 GTK_SIGNAL_FUNC(window_destroy), 0); 1653 1654 vbox = gtk_vbox_new(0, 0); 1655 gtk_container_add(GTK_CONTAINER(window), vbox); 1656 gtk_widget_show(vbox); 1657 1658 tooltips = gtk_tooltips_new(); 1659 1660 toolbar = gtk_toolbar_new(); 1661 gtk_widget_show(toolbar); 1662 gtk_toolbar_set_style(GTK_TOOLBAR(toolbar), GTK_TOOLBAR_ICONS); 1663 gtk_box_pack_start(GTK_BOX(vbox), toolbar, 0, 0, 0); 1664 1665 group = NULL; 1666 1667 toolbtn = gtk_radio_tool_button_new(group); 1668 rotate_obj_btn = (GtkWidget*)toolbtn; 1669 gtk_tool_button_set_label(GTK_TOOL_BUTTON(toolbtn), ""); 1670 pixbuf = gdk_pixbuf_new_from_xpm_data(object_xpm); 1671 icon = gtk_image_new_from_pixbuf(pixbuf); 1672 gtk_widget_show(icon); 1673 gtk_tool_button_set_icon_widget(GTK_TOOL_BUTTON(toolbtn), icon); 1674 gtk_tool_item_set_tooltip(GTK_TOOL_ITEM(toolbtn), tooltips, "Rotate object", 0); 1675 gtk_widget_show(GTK_WIDGET(toolbtn)); 1676 gtk_container_add(GTK_CONTAINER(toolbar), GTK_WIDGET(toolbtn)); 1677 gtk_signal_connect(GTK_OBJECT(toolbtn), "toggled", 1678 GTK_SIGNAL_FUNC(rotate_type_toggled), 1679 (gpointer)ROTATE_OBJECT); 1680 group = gtk_radio_tool_button_get_group(GTK_RADIO_TOOL_BUTTON(toolbtn)); 1681 1682 toolbtn = gtk_radio_tool_button_new(group); 1683 gtk_tool_button_set_label(GTK_TOOL_BUTTON(toolbtn), ""); 1684 pixbuf = gdk_pixbuf_new_from_xpm_data(light_xpm); 1685 icon = gtk_image_new_from_pixbuf(pixbuf); 1686 gtk_widget_show(icon); 1687 gtk_tool_button_set_icon_widget(GTK_TOOL_BUTTON(toolbtn), icon); 1688 gtk_tool_item_set_tooltip(GTK_TOOL_ITEM(toolbtn), tooltips, "Rotate light", 0); 1689 gtk_widget_show(GTK_WIDGET(toolbtn)); 1690 gtk_container_add(GTK_CONTAINER(toolbar), GTK_WIDGET(toolbtn)); 1691 gtk_signal_connect(GTK_OBJECT(toolbtn), "toggled", 1692 GTK_SIGNAL_FUNC(rotate_type_toggled), 1693 (gpointer)ROTATE_LIGHT); 1694 group = gtk_radio_tool_button_get_group(GTK_RADIO_TOOL_BUTTON(toolbtn)); 1695 1696 toolbtn = gtk_radio_tool_button_new(group); 1697 gtk_tool_button_set_label(GTK_TOOL_BUTTON(toolbtn), ""); 1698 pixbuf = gdk_pixbuf_new_from_xpm_data(scene_xpm); 1699 icon = gtk_image_new_from_pixbuf(pixbuf); 1700 gtk_widget_show(icon); 1701 gtk_tool_button_set_icon_widget(GTK_TOOL_BUTTON(toolbtn), icon); 1702 gtk_tool_item_set_tooltip(GTK_TOOL_ITEM(toolbtn), tooltips, "Rotate scene", 0); 1703 gtk_widget_show(GTK_WIDGET(toolbtn)); 1704 gtk_container_add(GTK_CONTAINER(toolbar), GTK_WIDGET(toolbtn)); 1705 gtk_signal_connect(GTK_OBJECT(toolbtn), "toggled", 1706 GTK_SIGNAL_FUNC(rotate_type_toggled), 1707 (gpointer)ROTATE_SCENE); 1708 group = gtk_radio_tool_button_get_group(GTK_RADIO_TOOL_BUTTON(toolbtn)); 1709 1710 toolbtn = gtk_separator_tool_item_new(); 1711 gtk_widget_show(GTK_WIDGET(toolbtn)); 1712 gtk_container_add(GTK_CONTAINER(toolbar), GTK_WIDGET(toolbtn)); 1713 1714 toolbtn = gtk_toggle_tool_button_new(); 1715 gtk_tool_button_set_label(GTK_TOOL_BUTTON(toolbtn), ""); 1716 pixbuf = gdk_pixbuf_new_from_xpm_data(full_xpm); 1717 icon = gtk_image_new_from_pixbuf(pixbuf); 1718 gtk_widget_show(icon); 1719 gtk_tool_button_set_icon_widget(GTK_TOOL_BUTTON(toolbtn), icon); 1720 gtk_tool_item_set_tooltip(GTK_TOOL_ITEM(toolbtn), tooltips, "Toggle fullscreen", 0); 1721 gtk_widget_show(GTK_WIDGET(toolbtn)); 1722 gtk_container_add(GTK_CONTAINER(toolbar), GTK_WIDGET(toolbtn)); 1723 gtk_signal_connect(GTK_OBJECT(toolbtn), "clicked", 1724 GTK_SIGNAL_FUNC(toggle_fullscreen), 0); 1725 1726 toolbtn = gtk_separator_tool_item_new(); 1727 gtk_widget_show(GTK_WIDGET(toolbtn)); 1728 gtk_container_add(GTK_CONTAINER(toolbar), GTK_WIDGET(toolbtn)); 1729 1730 toolbtn = gtk_tool_item_new(); 1731 gtk_widget_show(GTK_WIDGET(toolbtn)); 1732 gtk_container_add(GTK_CONTAINER(toolbar), GTK_WIDGET(toolbtn)); 1733 label = gtk_label_new("Object type: "); 1734 gtk_widget_show(label); 1735 gtk_container_add(GTK_CONTAINER(toolbtn), label); 1736 1737 toolbtn = gtk_tool_item_new(); 1738 gtk_widget_show(GTK_WIDGET(toolbtn)); 1739 gtk_container_add(GTK_CONTAINER(toolbar), GTK_WIDGET(toolbtn)); 1740 1741 opt = gtk_option_menu_new(); 1742 object_opt = opt; 1743 gtk_widget_show(opt); 1744 gtk_container_add(GTK_CONTAINER(toolbtn), opt); 1745 1746 menu = gtk_menu_new(); 1747 1748 for(i = 0; i < OBJECT_MAX; ++i) 1749 { 1750 menuitem = gtk_menu_item_new_with_label(object_strings[i]); 1751 gtk_signal_connect(GTK_OBJECT(menuitem), "activate", 1752 GTK_SIGNAL_FUNC(object_selected), 1753 (gpointer)(long)i); 1754 gtk_widget_show(menuitem); 1755 gtk_menu_append(GTK_MENU(menu), menuitem); 1756 } 1757 1758 gtk_option_menu_set_menu(GTK_OPTION_MENU(opt), menu); 1759 1760 glarea = gtk_drawing_area_new(); 1761 gtk_widget_set_usize(glarea, 500, 300); 1762 gtk_widget_set_gl_capability(glarea, glconfig, 0, 1, GDK_GL_RGBA_TYPE); 1763 gtk_widget_set_events(glarea, GDK_EXPOSURE_MASK | 1764 GDK_BUTTON_PRESS_MASK | 1765 GDK_POINTER_MOTION_MASK); 1766 gtk_signal_connect(GTK_OBJECT(glarea), "realize", 1767 GTK_SIGNAL_FUNC(init), 0); 1768 gtk_signal_connect(GTK_OBJECT(glarea), "expose_event", 1769 GTK_SIGNAL_FUNC(expose), 0); 1770 gtk_signal_connect(GTK_OBJECT(glarea), "motion_notify_event", 1771 GTK_SIGNAL_FUNC(motion_notify), 0); 1772 gtk_signal_connect(GTK_OBJECT(glarea), "button_press_event", 1773 GTK_SIGNAL_FUNC(button_press), 0); 1774 gtk_signal_connect(GTK_OBJECT(glarea), "configure_event", 1775 GTK_SIGNAL_FUNC(configure), 0); 1776 1777 gtk_box_pack_start(GTK_BOX(vbox), glarea, 1, 1, 0); 1778 1779 table = gtk_table_new(11, 2, 0); 1780 controls_table = table; 1781 gtk_container_set_border_width(GTK_CONTAINER(table), 5); 1782 gtk_table_set_col_spacings(GTK_TABLE(table), 5); 1783 gtk_table_set_row_spacings(GTK_TABLE(table), 5); 1784 gtk_box_pack_start(GTK_BOX(vbox), table, 0, 0, 0); 1785 gtk_widget_show(table); 1786 1787 opt = gtk_option_menu_new(); 1788 gtk_widget_show(opt); 1789 menu = gimp_drawable_menu_new(0, diffusemap_callback, 0, normalmap_drawable_id); 1790 gtk_option_menu_set_menu(GTK_OPTION_MENU(opt), menu); 1791 gimp_table_attach_aligned(GTK_TABLE(table), 0, 0, "Diffuse map:", 0, 0.5, 1792 opt, 1, 0); 1793 1794 opt = gtk_option_menu_new(); 1795 gloss_opt = opt; 1796 gtk_widget_show(opt); 1797 menu = gimp_drawable_menu_new(0, glossmap_callback, 0, normalmap_drawable_id); 1798 gtk_option_menu_set_menu(GTK_OPTION_MENU(opt), menu); 1799 gimp_table_attach_aligned(GTK_TABLE(table), 0, 1, "Gloss map:", 0, 0.5, 1800 opt, 1, 0); 1801 1802 opt = gtk_option_menu_new(); 1803 bumpmapping_opt = opt; 1804 gtk_widget_show(opt); 1805 1806 gimp_table_attach_aligned(GTK_TABLE(table), 0, 2, 1807 "Bump mapping:", 0, 0.5, 1808 opt, 1, 0); 1809 1810 menu = gtk_menu_new(); 1811 1812 for(i = 0; i < BUMPMAP_MAX; ++i) 1813 { 1814 menuitem = gtk_menu_item_new_with_label(bumpmap_strings[i]); 1815 gtk_signal_connect(GTK_OBJECT(menuitem), "activate", 1816 GTK_SIGNAL_FUNC(bumpmapping_clicked), 1817 (gpointer)(long)i); 1818 gtk_widget_show(menuitem); 1819 gtk_menu_append(GTK_MENU(menu), menuitem); 1820 } 1821 1822 gtk_option_menu_set_menu(GTK_OPTION_MENU(opt), menu); 1823 1824 check = gtk_check_button_new_with_label("Specular lighting"); 1825 specular_check = check; 1826 gtk_widget_show(check); 1827 gtk_table_attach(GTK_TABLE(table), check, 1, 2, 3, 4, 1828 (GtkAttachOptions)(GTK_EXPAND | GTK_FILL), 1829 (GtkAttachOptions)(0), 0, 0); 1830 gtk_signal_connect(GTK_OBJECT(check), "clicked", 1831 GTK_SIGNAL_FUNC(toggle_clicked), &specular); 1832 1833 specular_exp_range = hscale = gtk_hscale_new(GTK_ADJUSTMENT(gtk_adjustment_new(32, 0, 256, 1, 8, 0))); 1834 gtk_widget_show(hscale); 1835 gtk_scale_set_value_pos(GTK_SCALE(hscale), GTK_POS_RIGHT); 1836 gimp_table_attach_aligned(GTK_TABLE(table), 0, 4, "Specular exponent:", 0, 0.5, 1837 hscale, 1, 0); 1838 gtk_signal_connect(GTK_OBJECT(hscale), "value_changed", 1839 GTK_SIGNAL_FUNC(specular_exp_changed), 0); 1840 1841 1842 gimp_rgb_set(&color, ambient_color[0], ambient_color[1], ambient_color[2]); 1843 ambient_color_btn = btn = gimp_color_button_new("Ambient color", 0, 15, &color, GIMP_COLOR_AREA_FLAT); 1844 gtk_widget_show(btn); 1845 gimp_color_button_set_color(GIMP_COLOR_BUTTON(btn), &color); 1846 gimp_table_attach_aligned(GTK_TABLE(table), 0, 5, "Ambient color:", 0, 0.5, 1847 btn, 1, 0); 1848 gtk_signal_connect(GTK_OBJECT(btn), "color_changed", 1849 GTK_SIGNAL_FUNC(color_changed), (gpointer)ambient_color); 1850 1851 gimp_rgb_set(&color, diffuse_color[0], diffuse_color[1], diffuse_color[2]); 1852 diffuse_color_btn = btn = gimp_color_button_new("Diffuse color", 0, 15, &color, GIMP_COLOR_AREA_FLAT); 1853 gtk_widget_show(btn); 1854 gimp_color_button_set_color(GIMP_COLOR_BUTTON(btn), &color); 1855 gimp_table_attach_aligned(GTK_TABLE(table), 0, 6, "Diffuse color:", 0, 0.5, 1856 btn, 1, 0); 1857 gtk_signal_connect(GTK_OBJECT(btn), "color_changed", 1858 GTK_SIGNAL_FUNC(color_changed), (gpointer)diffuse_color); 1859 1860 gimp_rgb_set(&color, specular_color[0], specular_color[1], specular_color[2]); 1861 specular_color_btn = btn = gimp_color_button_new("Specular color", 0, 15, &color, GIMP_COLOR_AREA_FLAT); 1862 gtk_widget_show(btn); 1863 gimp_color_button_set_color(GIMP_COLOR_BUTTON(btn), &color); 1864 gimp_table_attach_aligned(GTK_TABLE(table), 0, 7, "Specular color:", 0, 0.5, 1865 btn, 1, 0); 1866 gtk_signal_connect(GTK_OBJECT(btn), "color_changed", 1867 GTK_SIGNAL_FUNC(color_changed), (gpointer)specular_color); 1868 1869 table2 = gtk_table_new(2, 2, 0); 1870 gtk_widget_show(table2); 1871 gtk_table_set_col_spacings(GTK_TABLE(table2), 5); 1872 gtk_table_set_row_spacings(GTK_TABLE(table2), 5); 1873 gimp_table_attach_aligned(GTK_TABLE(table), 0, 8, "UV scale:", 0, 0.5, 1874 table2, 1, 0); 1875 1876 adj = gtk_adjustment_new(1, 0, 1000, 1, 10, 10); 1877 spin = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 1, 4); 1878 uvscale_spin1 = spin; 1879 gtk_widget_show(spin); 1880 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_IF_VALID); 1881 gtk_signal_connect(GTK_OBJECT(spin), "value_changed", 1882 GTK_SIGNAL_FUNC(uvscale_changed), (gpointer)0); 1883 gtk_table_attach(GTK_TABLE(table2), spin, 0, 1, 0, 1, 1884 (GtkAttachOptions)(GTK_EXPAND | GTK_FILL), 1885 (GtkAttachOptions)(0), 0, 0); 1886 1887 adj = gtk_adjustment_new(1, 0, 1000, 1, 10, 10); 1888 spin = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 1, 4); 1889 uvscale_spin2 = spin; 1890 gtk_widget_show(spin); 1891 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_IF_VALID); 1892 gtk_signal_connect(GTK_OBJECT(spin), "value_changed", 1893 GTK_SIGNAL_FUNC(uvscale_changed), (gpointer)1); 1894 gtk_table_attach(GTK_TABLE(table2), spin, 0, 1, 1, 2, 1895 (GtkAttachOptions)(GTK_EXPAND | GTK_FILL), 1896 (GtkAttachOptions)(0), 0, 0); 1897 1898 btn = gimp_chain_button_new(GIMP_CHAIN_RIGHT); 1899 gtk_widget_show(btn); 1900 gimp_chain_button_set_active(GIMP_CHAIN_BUTTON(btn), 1); 1901 gtk_table_attach(GTK_TABLE(table2), btn, 1, 2, 0, 2, 1902 (GtkAttachOptions)(0), 1903 (GtkAttachOptions)(0), 0, 0); 1904 1905 g_object_set_data(G_OBJECT(uvscale_spin1), "chain", btn); 1906 g_object_set_data(G_OBJECT(uvscale_spin2), "chain", btn); 1907 1908 btn = gtk_button_new_with_label("Reset view"); 1909 gtk_widget_show(btn); 1910 gtk_table_attach(GTK_TABLE(table), btn, 0, 2, 10, 11, 1911 (GtkAttachOptions)(GTK_EXPAND | GTK_FILL), 1912 (GtkAttachOptions)(0), 0, 0); 1913 gtk_signal_connect(GTK_OBJECT(btn), "clicked", 1914 GTK_SIGNAL_FUNC(reset_view_clicked), 0); 1915 1916 gtk_widget_show(glarea); 1917 gtk_widget_show(window); 1918 1919 _active = 1; 1920 } 1921 1922 void destroy_3D_preview(void) 1923 { 1924 if(!_active) return; 1925 gtk_widget_destroy(window); 1926 _active = 0; 1927 } 1928 1929 void update_3D_preview(unsigned int w, unsigned int h, int bpp, 1930 unsigned char *image) 1931 { 1932 int w_pot, h_pot, mipw, miph, n; 1933 unsigned char *pixels = image; 1934 unsigned char *mip; 1935 1936 if(!_active) return; 1937 if(_gl_error) return; 1938 1939 if(!has_npot && !(IS_POT(w) && IS_POT(h))) 1940 { 1941 get_nearest_pot(w, h, &w_pot, &h_pot); 1942 pixels = g_malloc(h_pot * w_pot * bpp); 1943 scale_pixels(pixels, w_pot, h_pot, image, w, h, bpp); 1944 w = w_pot; 1945 h = h_pot; 1946 } 1947 1948 glActiveTexture(GL_TEXTURE0); 1949 glBindTexture(GL_TEXTURE_2D, normal_tex); 1950 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 1951 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 1952 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 1953 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); 1954 if(has_aniso) 1955 glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, &anisotropy); 1956 if(has_generate_mipmap) 1957 glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_TRUE); 1958 glTexImage2D(GL_TEXTURE_2D, 0, bpp, w, h, 0, 1959 (bpp == 4) ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE, pixels); 1960 1961 if(!has_generate_mipmap) 1962 { 1963 mipw = w; 1964 miph = h; 1965 n = 0; 1966 while((mipw != 1) && (miph != 1)) 1967 { 1968 if(mipw > 1) mipw >>= 1; 1969 if(miph > 1) miph >>= 1; 1970 ++n; 1971 mip = g_malloc(mipw * miph * bpp); 1972 scale_pixels(mip, mipw, miph, pixels, w, h, bpp); 1973 glTexImage2D(GL_TEXTURE_2D, n, bpp, mipw, miph, 0, 1974 (bpp == 4) ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE, 1975 mip); 1976 g_free(mip); 1977 } 1978 } 1979 1980 if(pixels != image) 1981 g_free(pixels); 1982 1983 gtk_widget_queue_draw(glarea); 1984 } 1985 1986 int is_3D_preview_active(void) 1987 { 1988 return(_active); 1989 }
| ViewVC Help | |
| Powered by ViewVC 1.0.4 |