Logo Search packages:      
Sourcecode: earth3d version File versions  Download package

qGLWidgetDrawScene.cpp

#ifdef WIN32
#include "wingl.h"
#else
#define GL_GLEXT_PROTOTYPES
#endif

#include "qGLWidgetDrawScene.h"
#include "drawSceneObjectTexture.h"
#include <GL/glext.h>
#include <assert.h>
#include "quaternion.h"
#include "matrix.h"

#ifndef WIN32
#include <unistd.h>
#endif

/* white ambient light at full intensity (rgba) */
GLfloat qLightAmbient[] = { 1.0f, 1.0f, 1.0f, 1.0f };

/* super bright, full intensity diffuse light. */
GLfloat qLightDiffuse[] = { 1.0f, 1.0f, 1.0f, 1.0f };

/* position of light (x, y, z, (position of light)) */
GLfloat qLightPosition[] = { 1.f, 0.0f, 3.0f, 0.0f };
GLfloat qlight0_specular[] = {1,1,1,1};
GLfloat qmat_specular[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat qmat_shininess[] = { 50.0 };

QGLWidgetDrawScene::QGLWidgetDrawScene(DrawScene *scene)
  : QGLWidget() {
  depthbuffer = NULL;
  flcurrent = NULL;
  this->scene = scene;
  running = false;
}

QGLWidgetDrawScene::~QGLWidgetDrawScene() {
  if (depthbuffer) delete[](depthbuffer);
}

void QGLWidgetDrawScene::initializeGL() {
  /* set environment */
  glActiveTextureARB(GL_TEXTURE0_ARB);
  glClientActiveTextureARB(GL_TEXTURE0_ARB);
  glEnable(GL_TEXTURE_2D);
  glEnableClientState(GL_VERTEX_ARRAY);
  glEnableClientState(GL_TEXTURE_COORD_ARRAY);
  glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
  glDisable(GL_COLOR_MATERIAL);
  glDisable(GL_LIGHTING);
  glColor4f(1,1,1,1);
  
  cullface = glIsEnabled(GL_CULL_FACE);
  glDisable(GL_CULL_FACE);
  
  glEnable (GL_BLEND);
  glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  
  glEnable(GL_ALPHA_TEST);
  glAlphaFunc(GL_GREATER, 0.1);

  glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);

  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer
  glClearColor(backgroundcolor.x, backgroundcolor.y, backgroundcolor.z, 1.0f); 
  glLoadIdentity();                             // Reset The View

  glEnable(GL_LIGHTING);
  glEnable(GL_COLOR_MATERIAL);
  glEnable(GL_NORMALIZE);

  glShadeModel (GL_SMOOTH);
//   glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
//   glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
  
  glLightfv(GL_LIGHT1, GL_AMBIENT, qLightAmbient);  // add lighting. (ambient)
  glLightfv(GL_LIGHT1, GL_DIFFUSE, qLightDiffuse);  // add lighting. (diffuse).
  glLightfv(GL_LIGHT1, GL_POSITION,qLightPosition); // set light position.
  glLightfv(GL_LIGHT1, GL_SPECULAR, qlight0_specular);
  glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
  glEnable(GL_LIGHT1);                             // turn light 1 on.

  glEnable(GL_DEPTH_TEST);
}

void QGLWidgetDrawScene::resizeGL(int width, int height) {
  QGLWidget::resizeGL(width, height);

  glViewport(0, 0, width, height);
  glMatrixMode( GL_PROJECTION );
  glLoadIdentity();
  glOrtho(-1, 1, -1, 1, -1, 1);
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
}

void QGLWidgetDrawScene::paintGL() {
  if (flcurrent==NULL) return;

  printf("paint start\n");

  /* rotate bs_center */
  float matrix1[16];
  Quaternion quat;
  quat.createFromAxisAngle(1,0,0, pbrAnglesElevation);
  quat.createMatrix(matrix1);
  float matrix2[16];
  quat.createFromAxisAngle(0,1,0, currentangle*(360./pbrAnglesCount));
  quat.createMatrix(matrix2);

  Point3D bs_resultcenter = Matrix::multvector(matrix1, flcurrent->bs_center);
  bs_resultcenter = Matrix::multvector(matrix2, bs_resultcenter);

  /* set up projection */
  glMatrixMode( GL_PROJECTION );
  glLoadIdentity();
  glOrtho(-flcurrent->bs_radius, flcurrent->bs_radius, -flcurrent->bs_radius, flcurrent->bs_radius, -flcurrent->bs_radius, flcurrent->bs_radius);
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();

  drawMutex.lock();
  glClearColor(backgroundcolor.x, backgroundcolor.y, backgroundcolor.z, 1.0f); 
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer
  glLoadIdentity();                             // Reset The View
  glRotatef(currentangle*(360./pbrAnglesCount), 0, 1, 0); // Rotation
  glRotatef(pbrAnglesElevation, 1, 0, 0);                // Elevation
  glTranslatef(-flcurrent->bs_center.x, -flcurrent->bs_center.y, -flcurrent->bs_center.z);

  std::vector<openglarray *>::iterator i;
  for (i = flcurrent->openglarrayList.begin(); i != flcurrent->openglarrayList.end(); i++) {
    openglarray *current = *i;
    
    /* set texture */
    glBindTexture(GL_TEXTURE_2D, current->texture->getTextureID(true));   // choose the texture to use.
    
    /* draw arrays */
    glVertexPointer(3, GLDOUBLE, 0, current->vertexarray);
    glTexCoordPointer(2, GLDOUBLE, 0, current->texcoordarray);
    glDrawArrays(GL_TRIANGLES, 0, current->vertexcount);
  }
  
  /* read depth buffer */
  if (depthbuffer) delete[](depthbuffer);
  depthWidth = size().width();
  depthHeight = size().height();
  depthbuffer = new float[depthWidth*depthHeight];
  glReadPixels(0,0,depthWidth, depthHeight, GL_DEPTH_COMPONENT, GL_FLOAT, depthbuffer);

  /* read environment */
  glGetDoublev( GL_PROJECTION_MATRIX, proj );
  glGetDoublev( GL_MODELVIEW_MATRIX, modl );
  glGetIntegerv( GL_VIEWPORT, viewport );

  /* restore environment */
//   if (cullface) glEnable(GL_CULL_FACE);
//   glDisable(GL_ALPHA_TEST);

  drawn = true;
  lastimage = grabFrameBuffer();

  printf("paint end\n");
  drawMutex.unlock();
}

QImage QGLWidgetDrawScene::render(Point3D backgroundcolor, int angle) {
  currentangle = angle;

  drawMutex.lock();
  this->backgroundcolor = backgroundcolor;

  /* wait for drawing */
  drawn = false;
  drawMutex.unlock();

  show();
#ifdef LINUX
  update();
#else
  updateGL();
#endif
  while(!drawn) {
    usleep(1000);
    if (!drawn) {
#ifdef LINUX
      update();
#else
      updateGL();
#endif
    }
  }
  
  usleep(5000);
  //     QPixmap pixmap1 = renderPixmap(PBR_IMAGE_SIZE, PBR_IMAGE_SIZE);
  //     QImage image1 = pixmap1.convertToImage();
  drawMutex.lock();
  QImage image = lastimage.copy();//grabFrameBuffer();
  drawMutex.unlock();

  return(image);
}

void QGLWidgetDrawScene::readPoints(QImage &image1, QImage &image2, std::vector<ColoredPoint3D> &tmppoints) {
  for(int factor=2; factor<=PBR_IMAGE_SIZE; factor*=2) {
    for(int x=0; x<factor/2; x++) {
      for(int y=0; y<factor/2; y++) {
      /* get point (x*2+1) (y*2+1) */
      int sx = (PBR_IMAGE_SIZE/factor)*(x*2+1);
      int sy = (PBR_IMAGE_SIZE/factor)*(y*2+1);

      //      if (sx>=10 && sx<PBR_IMAGE_SIZE-10 && sy>=10 && sy<PBR_IMAGE_SIZE-1) {
      float sz = depthbuffer[sy*depthWidth+sx];
          
      QRgb pixel1 = image1.pixel(sx, PBR_IMAGE_SIZE-sy);
      QRgb pixel2 = image2.pixel(sx, PBR_IMAGE_SIZE-sy);

      //        printf("hasAlpha: %i alpha: %f\n", image1.hasAlphaBuffer(), qAlpha(pixel1));
      //        if (qAlpha(pixel1)<0.9) {
      if (pixel1==pixel2) { // hit the object, add the pixel
        GLdouble sdx, sdy, sdz;
        //      printf("sz: %f ", sz);
        if (sz>-0.1 && sz<0.99) {
          gluUnProject(sx, sy, sz, modl, proj, viewport, &sdx, &sdy, &sdz);

          tmppoints.push_back(ColoredPoint3D(Point3D(sdx, sdy, sdz), Point3D(qRed(pixel1)/256., qGreen(pixel1)/256., qBlue(pixel1)/256.)));
          //          printf("%i ", qBlue(image1.pixel((PBR_IMAGE_SIZE/factor)*(x*2+1), (PBR_IMAGE_SIZE/factor)*(y*2+1))));
        }
      }
      //      }
      }
    }
  }
}

void QGLWidgetDrawScene::renderPBRData(firstLevelOpenGLArray *flobject, int pbrAnglesCount, float pbrAnglesElevation, int pbrUseAnglesAround) {
  this->pbrAnglesCount = pbrAnglesCount;
  this->pbrAnglesElevation = pbrAnglesElevation;
  this->pbrUseAnglesAround = pbrUseAnglesAround;
  this->flcurrent = flobject;

  pbr_list *pbrlist = flobject->pbrlist;

  /* iterate through the view angles */
  for(int angle=0; angle<pbrAnglesCount+2; angle++) {
      usleep(1000);
    std::vector<ColoredPoint3D> tmppoints;

    QImage image1, image2;
    if (angle<pbrAnglesCount) { // render one side
      /* render with different background colors to see where the object is */
      image1 = render(Point3D(0,0,0), angle);
      image2 = render(Point3D(1,1,1), angle);
    }
    else {
      if (angle==pbrAnglesCount) { // top
      this->pbrAnglesElevation = 90;
      image1 = render(Point3D(0,0,0), 0);
      image2 = render(Point3D(1,1,1), 0);
      }
      else { // bottom
      this->pbrAnglesElevation = -90;
      image1 = render(Point3D(0,0,0), 0);
      image2 = render(Point3D(1,1,1), 0);
      }
    }

    /* DEBUG save image */
//     image1.save(QString("pixmap")+QString().setNum(angle)+QString(".png"), "PNG");

    /* read point based rendering pixels in a grid */
    readPoints(image1, image2, tmppoints);

    /* add new pbr data for this angle to pbrlist */
    pbrlist[angle].vertexcount = tmppoints.size();
    if (pbrlist[angle].vertexarray) delete[](pbrlist[angle].vertexarray);
    if (pbrlist[angle].colorarray) delete[](pbrlist[angle].colorarray);

    pbrlist[angle].vertexarray = new Point3D[pbrlist[angle].vertexcount];
    pbrlist[angle].colorarray = new Point3D[pbrlist[angle].vertexcount];

    /* copy data to destination */
    int c=0;
    std::vector<ColoredPoint3D>::iterator i;
    for (i = tmppoints.begin(); i != tmppoints.end(); i++) {
#ifdef WIN32
//       assert(((*i).p-flcurrent->bs_center).length()<flcurrent->bs_radius);
#endif
      pbrlist[angle].vertexarray[c] = (*i).p;
      pbrlist[angle].colorarray[c] = (*i).color;
      c++;
    }
    assert(c==tmppoints.size());
//     printf("angle: %i c: %i\n", angle, c);
  }
}

void QGLWidgetDrawScene::nextFrame() {
  if (fi != firstlevelcompilelist.end()) {
    firstLevelOpenGLArray *current = (firstLevelOpenGLArray *) (*fi);
    if (current->pbrlist[0].vertexcount==0) {
      renderPBRData(current, PBR_ANGLES_COUNT, PBR_ANGLES_ELEVATION, PBR_USE_ANGLES_AROUND);
    }

    fi++;
  }
  else {
    timer->stop();
    delete(timer);

    hide();

    usleep(10000);

    scene->setFinishedPBR();
  }
}

#ifdef WIN32
void QGLWidgetDrawScene::start ( Priority priority ) {
  printf("starttimer\n");
  fi = firstlevelcompilelist.begin();

  timer = new QTimer( this );
  connect(timer, SIGNAL(timeout()), SLOT(nextFrame()));

  running = true;
  timer->start(0, FALSE);
}
#endif

void QGLWidgetDrawScene::run() {
  running = true;
  usleep(1000000);

  std::vector<firstLevelOpenGLArray *>::iterator fi;
  for (fi = firstlevelcompilelist.begin(); fi != firstlevelcompilelist.end(); fi++) {
    firstLevelOpenGLArray *current = (firstLevelOpenGLArray *) (*fi);
    if (current->pbrlist[0].vertexcount==0) {
      renderPBRData(current, PBR_ANGLES_COUNT, PBR_ANGLES_ELEVATION, PBR_USE_ANGLES_AROUND);
    }
  }

  hide();

  usleep(1000000);

  scene->setFinishedPBR();
}

void QGLWidgetDrawScene::setPBRList(std::vector<firstLevelOpenGLArray *> firstlevelcompilelist) {
  this->firstlevelcompilelist = firstlevelcompilelist;
}


Generated by  Doxygen 1.6.0   Back to index