/*
* Copyright (c) 2002-2006 Samit Basu
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include "GLRenderEngine.hpp"
#include <qimage.h>
#include <qpainter.h>
#include <QtOpenGL>
#include <math.h>
GLRenderEngine::GLRenderEngine(QGLWidget *widget, double x1, double y1,
double width, double height) {
m_x1 = x1;
m_y1 = y1;
m_width = width;
m_height = height;
m_widget = widget;
glEnable(GL_TEXTURE_2D);
}
QGLWidget* GLRenderEngine::widget() {
return m_widget;
}
GLRenderEngine::~GLRenderEngine() {
}
void GLRenderEngine::clear(std::vector<double> color) {
if (color[0] != -1) {
glClearColor(color[0], color[1], color[2], 0.0f);
glClearDepth(1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
}
void GLRenderEngine::toPixels(double x, double y, double z,
double &a, double &b, bool &clipped) {
toPixels(x,y,z,a,b);
clipped = ((a < viewp[0]) || (a > (viewp[0] + viewp[2])) ||
(b < viewp[1]) || (b > (viewp[1] + viewp[3])));
}
void GLRenderEngine::toPixels(double x, double y, double z,
double &a, double &b) {
double c1, c2, c3;
gluProject(x,y,z,model,proj,viewp,&c1,&c2,&c3);
a = c1;
b = c2;
}
void GLRenderEngine::unitx(double &x, double &y, double &z) {
// we need a unitvector such that model*v = [1;0;0]
double m00, m01, m02;
double m10, m11, m12;
double m20, m21, m22;
double det;
det = m00*(m11*m22-m12*m21) - m01*(m10*m22-m12*m21) + m02*(m10*m21-m11*m20);
x = (m11*m21-m12*m21)/det;
y = -(m10*m22-m12*m21)/det;
z = (m10*m21-m11*m20)/det;
}
void GLRenderEngine::unity(double &x, double &y, double &z) {
}
void GLRenderEngine::toPixels(double x, double y, double z,
int &a, int &b) {
double c1, c2;
toPixels(x,y,z,c1,c2);
a = (int) c1;
b = (int) c2;
}
void GLRenderEngine::scale(double sx, double sy, double sz) {
glMatrixMode(GL_MODELVIEW);
glScaled(sx,sy,sz);
glGetDoublev(GL_MODELVIEW_MATRIX,model);
}
void GLRenderEngine::lookAt(double px, double py, double pz,
double tx, double ty, double tz,
double ux, double uy, double uz) {
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(px,py,pz,tx,ty,tz,ux,uy,uz);
glGetDoublev(GL_MODELVIEW_MATRIX,model);
}
static void gluMultMatrixVecd(const double matrix[16], const double in[4], double out[4])
{
int i;
for (i=0; i<4; i++) {
out[i] =
in[0] * matrix[0*4+i] +
in[1] * matrix[1*4+i] +
in[2] * matrix[2*4+i] +
in[3] * matrix[3*4+i];
}
}
void GLRenderEngine::mapPoint(double x, double y, double z,
double &a, double &b, double &c) {
double out[4];
double in[4];
in[0] = x;
in[1] = y;
in[2] = z;
in[3] = 1.0;
gluMultMatrixVecd(model,in,out);
a = out[0];
b = out[1];
c = out[2];
}
void GLRenderEngine::project(double xmin, double xmax, double ymin,
double ymax, double zmin, double zmax) {
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(xmin,xmax,ymin,ymax,zmin,zmax);
glGetDoublev(GL_PROJECTION_MATRIX,proj);
}
void GLRenderEngine::viewport(double x0, double y0,
double width, double height) {
glViewport((int)x0,(int)y0,(int)width,(int)height);
glGetIntegerv(GL_VIEWPORT,viewp);
}
void GLRenderEngine::quad(double x1, double y1, double z1,
double x2, double y2, double z2,
double x3, double y3, double z3,
double x4, double y4, double z4) {
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glBegin(GL_QUADS);
glVertex3f(x1,y1,z1);
glVertex3f(x2,y2,z2);
glVertex3f(x3,y3,z3);
glVertex3f(x4,y4,z4);
glEnd();
}
void GLRenderEngine::quadline(double x1, double y1, double z1,
double x2, double y2, double z2,
double x3, double y3, double z3,
double x4, double y4, double z4) {
glBegin(GL_LINE_LOOP);
glVertex3f(x1,y1,z1);
glVertex3f(x2,y2,z2);
glVertex3f(x3,y3,z3);
glVertex3f(x4,y4,z4);
glEnd();
}
void GLRenderEngine::color(std::vector<double> col) {
glColor3f(col[0],col[1],col[2]);
}
void GLRenderEngine::setLineStyle(std::string style) {
if (style == "-") {
glDisable(GL_LINE_STIPPLE);
return;
}
if (style == "--") {
glEnable(GL_LINE_STIPPLE);
glLineStipple(1,0x00FF);
return;
}
if (style == ":") {
glEnable(GL_LINE_STIPPLE);
glLineStipple(1,0xDDDD);
return;
}
if (style == "-.") {
glEnable(GL_LINE_STIPPLE);
glLineStipple(1,0xF0D0);
return;
}
if (style == "none") {
glEnable(GL_LINE_STIPPLE);
glLineStipple(1,0x0000);
return;
}
}
void GLRenderEngine::lineWidth(double n) {
glLineWidth(n);
}
void GLRenderEngine::line(double x1, double y1, double z1,
double x2, double y2, double z2) {
glBegin(GL_LINES);
glVertex3f(x1,y1,z1);
glVertex3f(x2,y2,z2);
glEnd();
}
void GLRenderEngine::line(double x1, double y1, double x2, double y2) {
glBegin(GL_LINES);
glVertex2f(x1,y1);
glVertex2f(x2,y2);
glEnd();
}
void GLRenderEngine::lineSeries(std::vector<double> xs,
std::vector<double> ys,
std::vector<double> zs) {
glBegin(GL_LINE_STRIP);
for (int i=0;i<xs.size();i++)
glVertex3f(xs[i],ys[i],zs[i]);
glEnd();
}
void GLRenderEngine::debug() {
double tmodel[16];
double tproj[16];
GLint tviewp[4];
glGetDoublev(GL_MODELVIEW_MATRIX,tmodel);
glGetDoublev(GL_PROJECTION_MATRIX,tproj);
glGetIntegerv(GL_VIEWPORT,tviewp);
// qDebug("GL Modelview matrix (before setupdirect)");
// qDebug("%f %f %f %f",tmodel[0],tmodel[4],tmodel[8],tmodel[12]);
// qDebug("%f %f %f %f",tmodel[1],tmodel[5],tmodel[9],tmodel[13]);
// qDebug("%f %f %f %f",tmodel[2],tmodel[6],tmodel[10],tmodel[14]);
// qDebug("%f %f %f %f",tmodel[3],tmodel[7],tmodel[11],tmodel[15]);
// qDebug("GL Projection matrix (before setupdirect)");
// qDebug("%f %f %f %f",tproj[0],tproj[4],tproj[8],tproj[12]);
// qDebug("%f %f %f %f",tproj[1],tproj[5],tproj[9],tproj[13]);
// qDebug("%f %f %f %f",tproj[2],tproj[6],tproj[10],tproj[14]);
// qDebug("%f %f %f %f",tproj[3],tproj[7],tproj[11],tproj[15]);
// qDebug("GL Viewport (before setupdirect)");
// qDebug("%d %d %d %d",tviewp[0],tviewp[1],tviewp[2],tviewp[3]);
}
void GLRenderEngine::setupDirectDraw() {
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glViewport((int)m_x1,(int)m_y1,(int)m_width,(int)m_height);
glOrtho(m_x1,m_x1+m_width,m_y1,m_y1+m_height,-1,1);
glDisable(GL_DEPTH_TEST);
}
void GLRenderEngine::releaseDirectDraw() {
glEnable(GL_DEPTH_TEST);
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glViewport(viewp[0],viewp[1],viewp[2],viewp[3]);
}
static int NextPowerTwo(int w) {
int x = 1;
while (x < w)
x <<= 1;
return x;
}
void GLRenderEngine::getModelviewMatrix(double amodel[16]) {
for (int i=0;i<16;i++)
amodel[i] = model[i];
}
void GLRenderEngine::getProjectionMatrix(double aproj[16]) {
for (int i=0;i<16;i++)
aproj[i] = proj[16];
}
void GLRenderEngine::getViewport(int aviewp[4]) {
for (int i=0;i<4;i++)
aviewp[i] = viewp[i];
}
void GLRenderEngine::putText(double x, double y, std::string txt,
std::vector<double> color,
AlignmentFlag xflag, AlignmentFlag yflag,
QFont fnt, double rotation) {
QFontMetrics fm(fnt);
QRect sze(fm.boundingRect(txt.c_str()));
int x0 = sze.left();
int y0 = sze.bottom();
int width = sze.width();
int height = sze.height();
// We now now the width and height. From this,
// we can compute the radial length
int radlength = (int) sqrt(width*width+height*height)*2;
// We need a bitmap surface that is 2X this size.
QImage img(radlength,radlength,QImage::Format_RGB32);
QPainter pnt(&img);
pnt.setRenderHint(QPainter::TextAntialiasing);
pnt.setRenderHint(QPainter::Antialiasing);
pnt.setBackground(QColor(255,255,255));
pnt.eraseRect(0,0,radlength,radlength);
pnt.setFont(fnt);
pnt.setPen(QColor(0,0,0));
// We translate to the center of the bitmap
pnt.translate(radlength/2,radlength/2);
pnt.rotate(-rotation);
// pnt.drawText(-width/2,height/2,txt.c_str());
pnt.drawText(0,0,txt.c_str());
pnt.end();
// The next step is to trim the bitmap from the bottom up
bool allempty = true;
int row_offset = 0;
while (allempty && (row_offset < (radlength/2-1))) {
QRgb* dbits = (QRgb*) img.scanLine(radlength-1-row_offset);
allempty = true;
for (int i=0;allempty && (i<radlength);i++)
allempty = (qRed(dbits[i]) == 255);
row_offset++;
}
row_offset--;
row_offset = qMax(row_offset,0);
// Now we trim from the left side
allempty = true;
int col_offset = 0;
while (allempty && (col_offset < (radlength/2-1))) {
allempty = true;
for (int i=0;allempty && (i<radlength);i++)
allempty = (qRed(((QRgb*)img.scanLine(i))[col_offset]) == 255);
col_offset++;
}
col_offset--;
col_offset = qMax(col_offset,0);
int newwidth = radlength-col_offset;
int newheight = radlength-row_offset;
// Copy the text into an openGL bitmap
QImage pic = QImage(newwidth,newheight,QImage::Format_ARGB32);
// Set the color bits to all be the same color as specified
// in the argument list, and use the grey scale to modulate
// the transparency
int cred, cgreen, cblue;
cred = (int)(color[0]*255);
cgreen = (int)(color[1]*255);
cblue = (int)(color[2]*255);
for (int i=0;i<newheight;i++) {
QRgb* ibits = (QRgb*) img.scanLine(i);
QRgb* obits = (QRgb*) pic.scanLine(i);
for (int j=0;j<newwidth;j++)
obits[j] = qRgba(cred,cgreen,cblue,255-qRed(ibits[j+col_offset]));
}
pic = QGLWidget::convertToGLFormat(pic);
// Adjust the raster position based on the alignment offsets
double xdelta, ydelta;
xdelta = 0;
ydelta = 0;
if (xflag == Mean)
xdelta = -width/2.0;
if (xflag == Max)
xdelta = -width;
if (yflag == Mean)
ydelta = -height/2.0;
if (yflag == Max)
ydelta = -height;
double costhet, sinthet;
costhet = cos(rotation*M_PI/180.0);
sinthet = sin(rotation*M_PI/180.0);
double xpos, ypos;
xpos = x-radlength/2.0+xdelta*costhet-ydelta*sinthet+col_offset;
ypos = y-radlength/2.0+xdelta*sinthet+ydelta*costhet+row_offset;
glRasterPos2d(xpos,ypos);
glDrawPixels(newwidth,newheight,GL_RGBA,GL_UNSIGNED_BYTE,pic.bits());
}
void GLRenderEngine::depth(bool flag) {
if (flag)
glEnable(GL_DEPTH_TEST);
else
glDisable(GL_DEPTH_TEST);
}
void GLRenderEngine::measureText(std::string txt, QFont fnt, AlignmentFlag xflag,
AlignmentFlag yflag,int &width, int &height,
int &xoffset, int &yoffset) {
QFontMetrics fm(fnt);
QRect sze(fm.boundingRect(txt.c_str()));
width = sze.width();
height = sze.height();
yoffset = -height;
xoffset = 0;
if (xflag == Mean)
xoffset -= width/2;
else if (xflag == Max)
xoffset -= width;
if (yflag == Mean)
yoffset += height/2;
else if (yflag == Min)
yoffset += height;
}
void GLRenderEngine::rect(double x1, double y1, double x2, double y2) {
glBegin(GL_LINE_LOOP);
glVertex2f(x1,y1);
glVertex2f(x1,y2);
glVertex2f(x2,y2);
glVertex2f(x2,y1);
glEnd();
}
void GLRenderEngine::rectFill(double x1, double y1, double x2, double y2) {
glRectf(x1,y1,x2,y2);
}
void GLRenderEngine::tri(double x1, double y1, double z1,
double x2, double y2, double z2,
double x3, double y3, double z3) {
glBegin(GL_TRIANGLES);
glVertex3f(x1,y1,z1);
glVertex3f(x2,y2,z2);
glVertex3f(x3,y3,z3);
glEnd();
}
void GLRenderEngine::triLine(double x1, double y1, double z1,
double x2, double y2, double z2,
double x3, double y3, double z3) {
glBegin(GL_LINE_LOOP);
glVertex3f(x1,y1,z1);
glVertex3f(x2,y2,z2);
glVertex3f(x3,y3,z3);
glEnd();
}
void GLRenderEngine::circle(double x, double y, double radius) {
}
void GLRenderEngine::circleFill(double x, double y, double radius) {
}
void GLRenderEngine::drawImage(double x1, double y1, double x2,
double y2, QImage pic) {
pic = QGLWidget::convertToGLFormat(pic);
glRasterPos2d(x1,y1);
glDrawPixels(pic.width(),pic.height(),GL_RGBA,GL_UNSIGNED_BYTE,pic.bits());
return;
int texid = m_widget->bindTexture(pic);
glColor3f(1,1,1);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glDisable(GL_LIGHTING);
glBegin(GL_QUADS);
glTexCoord2d(0,0); glVertex2f(x1,y1);
glTexCoord2d(1,0); glVertex2f(x2,y1);
glTexCoord2d(1,1); glVertex2f(x2,y2);
glTexCoord2d(0,1); glVertex2f(x1,y2);
glEnd();
// glEnable(GL_LIGHTING);
m_widget->deleteTexture(texid);
}
void GLRenderEngine::quadStrips(std::vector<std::vector<cpoint> > faces, bool flatfaces,
std::vector<std::vector<cpoint> > edges, bool flatedges) {
glDisable(GL_CULL_FACE);
glEnable(GL_POLYGON_OFFSET_FILL);
if (flatfaces)
glShadeModel(GL_FLAT);
else
glShadeModel(GL_SMOOTH);
glPolygonOffset(2,2);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
for (int i=0;i<faces.size();i++) {
std::vector<cpoint> qlist(faces[i]);
glBegin(GL_QUAD_STRIP);
for (int j=0;j<qlist.size();j++) {
glColor4f(qlist[j].r,qlist[j].g,qlist[j].b,qlist[j].a);
glVertex3f(qlist[j].x,qlist[j].y,qlist[j].z);
}
glEnd();
}
glDisable(GL_POLYGON_OFFSET_FILL);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
if (flatedges)
glShadeModel(GL_FLAT);
else
glShadeModel(GL_SMOOTH);
for (int i=0;i<edges.size();i++) {
std::vector<cpoint> qlist(edges[i]);
glBegin(GL_QUAD_STRIP);
for (int j=0;j<qlist.size();j++) {
glColor4f(qlist[j].r,qlist[j].g,qlist[j].b,qlist[j].a);
glVertex3f(qlist[j].x,qlist[j].y,qlist[j].z);
}
glEnd();
}
}
syntax highlighted by Code2HTML, v. 0.9.1