tubeframe.cxx from gzz at Krugle
Show tubeframe.cxx syntax highlighted
/*
tubeframe.cxx
*
* Copyright (c) 2003, Janne Kujala
*
* This file is part of Gzz.
*
* Gzz is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Gzz is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
* Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with Gzz; if not, write to the Free
* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
*
*/
/*
* Written by Janne Kujala
*/
#include "tubeframe.hxx"
#include <GL/glu.h>
#include <iostream>
#include <math.h>
#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__ \
<<gluErrorString(er)<<"\n"; \
abort();\
} \
}
// TubeFrame ----------------------------------------------
void TubeFrame::genTextures() {
if (tex[0]) return;
glGenTextures(3, tex);
GLERR;
Texture::TextureParam param;
Texture::Texture *shad = Texture::Texture::getTexture("TubeFrame");
float *data = new float[512 * 512 * 2];
std::cerr << "generating ambient and shadow\n";
param.setParam("light", "ambient");
shad->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};
See more files for this project here