#include "tubeframe.hxx" #include #include #include #include "../libutil/buildmipmaps.hxx" using Util::buildmipmaps; #include "../libtexture/Texture.hxx" #define GLERR { int er = glGetError(); if(er != GL_NO_ERROR) {\ std::cout << "ERROR "<<__FILE__<<" "<<__LINE__ \ <render(¶m, 512, 512, 1, 2, data); glBindTexture(GL_TEXTURE_2D, tex[0]); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); buildmipmaps(GL_TEXTURE_2D, GL_LUMINANCE_ALPHA, 512, 512, GL_LUMINANCE_ALPHA, GL_FLOAT, data); std::cerr << "generating diffuse\n"; param.setParam("light", "diffuse"); shad->render(¶m, 512, 512, 1, 1, data); glBindTexture(GL_TEXTURE_2D, tex[1]); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); buildmipmaps(GL_TEXTURE_2D, GL_LUMINANCE, 512, 512, GL_LUMINANCE, GL_FLOAT, data); std::cerr << "generating specular\n"; param.setParam("light", "specular"); param.setParam("power", "16"); shad->render(¶m, 512, 512, 1, 1, data); glBindTexture(GL_TEXTURE_2D, tex[2]); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); buildmipmaps(GL_TEXTURE_2D, GL_LUMINANCE, 512, 512, GL_LUMINANCE, GL_FLOAT, data); delete[] data; delete shad; } TubeFrame::TubeFrame() { std::cerr << "constructing TubeFrame\n"; genTextures(); lights[0][0] = 0.1; lights[0][1] = 0.1; lights[0][2] = 0.3; // ambient lights[1][0] = 0.6; lights[1][1] = 0.0; lights[1][2] = 0.0; // diffuse lights[2][0] = 1.0; lights[2][1] = 1.0; lights[2][2] = 1.0; // specular std::cerr << "done\n"; } /* Render a rectangle with all the required passes using the given texture slice */ void TubeFrame::renderquad(float x0, float y0, float x1, float y1, float s0, float t0, float s1, float t1) { glEnable(GL_BLEND); glEnable(GL_TEXTURE_2D); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); for (int i = 0; i <= 2; i++) { if (i == 1) glBlendFunc(GL_ONE, GL_ONE); glColor3fv(lights[i]); glBindTexture(GL_TEXTURE_2D, tex[i]); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glBegin(GL_QUAD_STRIP); glTexCoord2f(s0, t0); glVertex2f(x0, y0); glTexCoord2f(s0, t1); glVertex2f(x0, y1); glTexCoord2f(s1, t0); glVertex2f(x1, y0); glTexCoord2f(s1, t1); glVertex2f(x1, y1); glEnd(); } } #define lerp(t, a, b) ( a + (t) * (b - a) ) /* Render a rectangle using renderquad and repeating the texture region (s0,t0)-(s1,t1) horizontally for each block of width w starting from the x0-side */ void TubeFrame::rendertube_h(float x0, float y0, float x1, float y1, float w, float s0, float t0, float s1, float t1, float s) { int n = (int)((x1 - x0) / w); for (int i = 0; i < n; i++) { renderquad(x0, y0, x0 + w, y1, s0, t0, s1, t1); x0 += w; } float f = (x1 - x0) / w; if (f > 0) { renderquad(x0, y0, x1, y1, s0, t0, lerp(f, s0, s1), t1); } } /* Analogous to rendertube_h */ void TubeFrame::rendertube_v(float x0, float y0, float x1, float y1, float w, float s0, float t0, float s1, float t1, float s) { int n = (int)((y1 - y0) / w); for (int i = 0; i < n; i++) { renderquad(x0, y0, x1, y0 + w, s0, t0, s1, t1); y0 += w; } float f = (y1 - y0) / w; if (f > 0) { renderquad(x0, y0, x1, y1, s0, t0, s1, lerp(f, t0, t1)); } } /* Render the quadrant of the frame starting from the corner (x0,y0) * and continuing to the middle point (x1,y1) of the frame. * * (s0,t0)-(s1,t1) is the corresponding texture quadrant, * w is the size of the corner block in object coordinates and * c is the size of the corner block in the texture */ void TubeFrame::rendercorner(float x0, float y0, float x1, float y1, float w, float s0, float t0, float s1, float t1, float c) { float dx = s1 > s0 ? 1 : -1; float dy = t1 > t0 ? 1 : -1; float side = 1 - 2 * c; renderquad(x0, y0, x0 + w * dx, y0 + w * dy, s0, t0, s0 + c * dx, t0 + c * dy); rendertube_h(x0 + w * dx, y0, x1, y0 + w * dy, side / c * w * dx, s0 + c * dx, t0, 2*s1-s0-c*dx, t0 + c * dy, side * dx); rendertube_v(x0, y0 + w * dy, x0 + w * dx, y1, side / c * w * dy, s0, t0 + c * dy, s0 + c * dx, 2*t1-t0-c*dy, side * dy); } void TubeFrame::render(float x0, float y0, float x1, float y1, float w) { glPushAttrib(GL_COLOR_BUFFER_BIT | GL_CURRENT_BIT | GL_TEXTURE_BIT); float fac = .2; glDisable(GL_TEXTURE_2D); glColor3f(0.9, 0.9, 0.8); glBegin(GL_QUAD_STRIP); glVertex2f(x0 + w * fac, y0 + w * fac); glVertex2f(x0 + w * fac, y1 - w * fac); glVertex2f(x1 - w * fac, y0 + w * fac); glVertex2f(x1 - w * fac, y1 - w * fac); glEnd(); float corner = .25; rendercorner(x0, y0, .5 * (x0 + x1), .5 * (y0 + y1), w, 0, 0, .5, .5, corner); rendercorner(x1, y0, .5 * (x0 + x1), .5 * (y0 + y1), w, 1, 0, .5, .5, corner); rendercorner(x0, y1, .5 * (x0 + x1), .5 * (y0 + y1), w, 0, 1, .5, .5, corner); rendercorner(x1, y1, .5 * (x0 + x1), .5 * (y0 + y1), w, 1, 1, .5, .5, corner); glPopAttrib(); } GLuint TubeFrame::tex[3] = {0,0,0}; // TubeConnector ---------------------------------------------- void TubeConnector::genTextures() { if (tex[0]) return; glGenTextures(4, tex); GLERR; Texture::TextureParam param; Texture::Texture *shad = Texture::Texture::getTexture("TubeConnector"); float *data = new float[512 * 128 * 2]; std::cerr << "generating ambient\n"; param.setParam("light", "ambient"); shad->render(¶m, 512, 128, 1, 2, data); glBindTexture(GL_TEXTURE_2D, tex[0]); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); buildmipmaps(GL_TEXTURE_2D, GL_LUMINANCE_ALPHA, 512, 128, GL_LUMINANCE_ALPHA, GL_FLOAT, data); std::cerr << "generating diffuse\n"; param.setParam("light", "diffuse"); shad->render(¶m, 512, 128, 1, 1, data); glBindTexture(GL_TEXTURE_2D, tex[1]); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); buildmipmaps(GL_TEXTURE_2D, GL_LUMINANCE, 512, 128, GL_LUMINANCE, GL_FLOAT, data); std::cerr << "generating specular\n"; param.setParam("light", "specular"); param.setParam("power", "16"); shad->render(¶m, 512, 128, 1, 1, data); glBindTexture(GL_TEXTURE_2D, tex[2]); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); buildmipmaps(GL_TEXTURE_2D, GL_LUMINANCE, 512, 128, GL_LUMINANCE, GL_FLOAT, data); std::cerr << "generating shadow\n"; param.setParam("light", "shadow"); shad->render(¶m, 512, 128, 1, 1, data); glBindTexture(GL_TEXTURE_2D, tex[3]); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); buildmipmaps(GL_TEXTURE_2D, GL_ALPHA, 512, 128, GL_ALPHA, GL_FLOAT, data); delete[] data; delete shad; } TubeConnector::TubeConnector() { genTextures(); lights[0][0] = 0.1; lights[0][1] = 0.1; lights[0][2] = 0.3; // ambient lights[1][0] = 0.6; lights[1][1] = 0.0; lights[1][2] = 0.0; // diffuse lights[2][0] = 1.0; lights[2][1] = 1.0; lights[2][2] = 1.0; // specular } void TubeConnector::render(float x0, float y0, float w0, float x1, float y1, float w1) { float vx = x1 - x0, vy = y1 - y0; float m = 1 / sqrt(vx * vx + vy * vy); vx *= m; vy *= m; float x[4] = { x0 + w0 * vy, x0 - w0 * vy, x1 + w1 * vy, x1 - w1 * vy }; float y[4] = { y0 - w0 * vx, y0 + w0 * vx, y1 - w1 * vx, y1 + w1 * vx }; glPushAttrib(GL_COLOR_BUFFER_BIT | GL_CURRENT_BIT | GL_TEXTURE_BIT); glEnable(GL_BLEND); glEnable(GL_TEXTURE_2D); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // Shadow glColor3f(0,0,0); glBindTexture(GL_TEXTURE_2D, tex[3]); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glBegin(GL_QUAD_STRIP); float dx0 = .2*w0, dx1 = .2*w1; float dy0 = -.2*w0, dy1 = -.2*w1; glTexCoord4f(0, 0, 0, w0); glVertex2f(x[0]+dx0, y[0]+dy0); glTexCoord4f(0, w0, 0, w0); glVertex2f(x[1]+dx0, y[1]+dy0); glTexCoord4f(w1, 0, 0, w1); glVertex2f(x[2]+dx1, y[2]+dy1); glTexCoord4f(w1, w1, 0, w1); glVertex2f(x[3]+dx1, y[3]+dy1); glEnd(); for (int i = 0; i <= 2; i++) { if (i == 1) glBlendFunc(GL_ONE, GL_ONE); glColor3fv(lights[i]); glBindTexture(GL_TEXTURE_2D, tex[i]); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glBegin(GL_QUAD_STRIP); glTexCoord4f(0, 0, 0, w0); glVertex2f(x[0], y[0]); glTexCoord4f(0, w0, 0, w0); glVertex2f(x[1], y[1]); for (float t = 0; t < 1; t += .25) { float a = (5+t)*(1./6); float w = lerp(a, w0, w1); glTexCoord4f(a*w, 0, 0, w); glVertex2f(lerp(a,x[0],x[2])+lerp(a,dx0,dx1)*(t*t), lerp(a,y[0],y[2])+lerp(a,dy0,dy1)*(t*t)); glTexCoord4f(a*w, w, 0, w); glVertex2f(lerp(a,x[1],x[3])+lerp(a,dx0,dx1)*(t*t), lerp(a,y[1],y[3])+lerp(a,dy0,dy1)*(t*t)); } glTexCoord4f(w1, 0, 0, w1); glVertex2f(x[2]+dx1, y[2]+dy1); glTexCoord4f(w1, w1, 0, w1); glVertex2f(x[3]+dx1, y[3]+dy1); glEnd(); } glPopAttrib(); GLERR } GLuint TubeConnector::tex[4] = {0,0,0,0};