/*===========================================================================*\
* *
* OpenFlipper *
* Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen *
* www.openflipper.org *
* *
*--------------------------------------------------------------------------- *
* This file is part of OpenFlipper. *
* *
* OpenFlipper 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 3 of *
* the License, or (at your option) any later version with the *
* following exceptions: *
* *
* If other files instantiate templates or use macros *
* or inline functions from this file, or you compile this file and *
* link it with other files to produce an executable, this file does *
* not by itself cause the resulting executable to be covered by the *
* GNU Lesser General Public License. This exception does not however *
* invalidate any other reasons why the executable file might be *
* covered by the GNU Lesser General Public License. *
* *
* OpenFlipper 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 LesserGeneral Public *
* License along with OpenFlipper. If not, *
* see . *
* *
\*===========================================================================*/
/*===========================================================================*\
* *
* $Revision: 10745 $ *
* $LastChangedBy: moebius $ *
* $Date: 2011-01-26 10:23:50 +0100 (Mi, 26 Jan 2011) $ *
* *
\*===========================================================================*/
#include "SkyDomeNode.hh"
#include
#include
#include
#include
#include
//== IMPLEMENTATION ==========================================================
SkyDomeNode::SkyDomeNode(SkyDome& _dome, BaseNode *_parent, std::string _name)
:BaseNode(_parent, _name),
dome_(_dome),
vbo_(0),
updateBuffers_(true)
{
vertexDecl_.addElement(GL_FLOAT, 3, ACG::VERTEX_USAGE_POSITION);
}
SkyDomeNode::~SkyDomeNode()
{
if ( vbo_)
glDeleteBuffers(1,&vbo_);
}
void SkyDomeNode::boundingBox(ACG::Vec3d& _bbMin, ACG::Vec3d& _bbMax)
{
// ACG::Vec3d pos = plane_.position - plane_.xDirection * 0.5 - plane_.yDirection * 0.5;
//
// //add a little offset in normal direction
// ACG::Vec3d pos0 = ACG::Vec3d( pos + plane_.normal * 0.1 );
// ACG::Vec3d pos1 = ACG::Vec3d( pos - plane_.normal * 0.1 );
//
// ACG::Vec3d xDird = ACG::Vec3d( plane_.xDirection );
// ACG::Vec3d yDird = ACG::Vec3d( plane_.yDirection );
//
// _bbMin.minimize( pos0 );
// _bbMin.minimize( pos0 + xDird);
// _bbMin.minimize( pos0 + yDird);
// _bbMin.minimize( pos0 + xDird + yDird);
// _bbMax.maximize( pos1 );
// _bbMax.maximize( pos1 + xDird);
// _bbMax.maximize( pos1 + yDird);
// _bbMax.maximize( pos1 + xDird + yDird);
}
//----------------------------------------------------------------------------
ACG::SceneGraph::DrawModes::DrawMode
SkyDomeNode::availableDrawModes() const
{
return ( ACG::SceneGraph::DrawModes::SOLID_FLAT_SHADED |
ACG::SceneGraph::DrawModes::SOLID_SMOOTH_SHADED );
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
void SkyDomeNode::drawSkyDome( ACG::GLState& _state) {
// const ACG::Vec3d xy = plane_.xDirection + plane_.yDirection;
//
// // Array of coordinates for the plane
// float vboData_[9 * 3 ] = { 0.0,0.0,0.0,
// (float)plane_.xDirection[0],(float)plane_.xDirection[1],(float)plane_.xDirection[2],
// (float)xy[0],(float)xy[1],(float)xy[2],
// (float)plane_.yDirection[0],(float)plane_.yDirection[1],(float)plane_.yDirection[2],
// 0.0,0.0,0.0,
// (float)plane_.yDirection[0],(float)plane_.yDirection[1],(float)plane_.yDirection[2],
// (float)xy[0],(float)xy[1],(float)xy[2],
// (float)plane_.xDirection[0],(float)plane_.xDirection[1],(float)plane_.xDirection[2],
// 0.0,0.0,0.0 };
//
// // Enable the arrays
// _state.enableClientState(GL_VERTEX_ARRAY);
// _state.vertexPointer(3,GL_FLOAT,0,&vboData_[0]);
//
// //first draw the lines
// _state.set_color(ACG::Vec4f(1.0, 1.0, 1.0 , 1.0) );
// glLineWidth(2.0);
//
// glDrawArrays(GL_LINE_STRIP,0,5);
//
// glLineWidth(1.0);
//
// // Remember blending state
// bool blending = _state.blending();
//
// //then the red front side
// ACG::GLState::enable (GL_BLEND);
// ACG::GLState::blendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
//
// _state.set_color(ACG::Vec4f( 0.6, 0.15, 0.2, 0.5));
// glDrawArrays(GL_QUADS,0,4);
//
//
// //finally the green back side
// _state.set_color(ACG::Vec4f(0.1, 0.8, 0.2, 0.5 ));
//
// glDrawArrays(GL_QUADS,4,4);
//
// if ( !blending )
// ACG::GLState::disable(GL_BLEND);
//
// // deactivate vertex arrays after drawing
// _state.disableClientState(GL_VERTEX_ARRAY);
}
//----------------------------------------------------------------
void SkyDomeNode::drawSkyDomePick( ACG::GLState& _state) {
// _state.pick_set_maximum(1);
// _state.pick_set_name(0);
//
// const ACG::Vec3d xy = plane_.xDirection + plane_.yDirection;
//
// // Array of coordinates for the plane
// float vboData_[4* 3 ] = { 0.0,0.0,0.0,
// (float)plane_.xDirection[0],(float)plane_.xDirection[1],(float)plane_.xDirection[2],
// (float)xy[0],(float)xy[1],(float)xy[2],
// (float)plane_.yDirection[0],(float)plane_.yDirection[1],(float)plane_.yDirection[2] };
//
// // Enable the arrays
// _state.enableClientState(GL_VERTEX_ARRAY);
// _state.vertexPointer(3,GL_FLOAT,0,&vboData_[0]);
//
// glDrawArrays(GL_QUADS,0,4);
//
// // deactivate vertex arrays after drawing
// _state.disableClientState(GL_VERTEX_ARRAY);
}
//----------------------------------------------------------------
void SkyDomeNode::draw(ACG::GLState& _state , const ACG::SceneGraph::DrawModes::DrawMode& /*_drawMode*/)
{
// _state.push_modelview_matrix();
// glPushAttrib(GL_COLOR_BUFFER_BIT);
// glPushAttrib(GL_LIGHTING_BIT);
//
// glColorMaterial ( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE ) ;
// ACG::GLState::enable(GL_COLOR_MATERIAL);
//
// // plane_.position represents the center of the plane.
// // Compute the corner position
// ACG::Vec3d pos = plane_.position - plane_.xDirection*0.5 - plane_.yDirection*0.5;
//
// // translate to corner position
// _state.translate(pos[0], pos[1], pos[2]);
//
// // draw the plane
// drawPlane(_state);
//
// glPopAttrib();
// glPopAttrib();
// _state.pop_modelview_matrix();
}
//----------------------------------------------------------------
void
SkyDomeNode::pick(ACG::GLState& _state, ACG::SceneGraph::PickTarget _target)
{
// if (_target == ACG::SceneGraph::PICK_ANYTHING) {
//
// _state.push_modelview_matrix();
//
// ACG::Vec3d pos = plane_.position - plane_.xDirection*0.5 - plane_.yDirection*0.5;
//
// _state.translate(pos[0], pos[1], pos[2]);
//
// drawPlanePick(_state);
//
// _state.pop_modelview_matrix();
// }
}
//----------------------------------------------------------------
void
SkyDomeNode::
getRenderObjects(ACG::IRenderer* _renderer, ACG::GLState& _state , const ACG::SceneGraph::DrawModes::DrawMode& _drawMode , const ACG::SceneGraph::Material* _mat) {
if ( updateBuffers_ ) {
QFileInfo info(dome_.textureFileName());
QString filename = dome_.textureFileName();
// Fallback image
if ( !info.exists() ) {
std::cerr << "Did not find image!" << filename.toStdString() << std::endl;
filename = OpenFlipper::Options::iconDirStr() + QDir::separator() + "EmptySkyDome.png";
}
// Test: Load texture image
QImage texture(filename);
GLuint textureId;
QImage GL_formatted_image;
GL_formatted_image = QGLWidget::convertToGLFormat(texture);
if( GL_formatted_image.isNull() )
{
std::cerr << "error GL_formatted_image" << std::endl ;
}
//generate the texture name
if ( !textureId_ )
glGenTextures(1, &textureId_);
//bind the texture ID
glBindTexture(GL_TEXTURE_2D, textureId_);
//generate the texture
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, GL_formatted_image.width(),
GL_formatted_image.height(),
0, GL_RGBA, GL_UNSIGNED_BYTE, GL_formatted_image.bits() );
//texture parameters
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D,0);
updateBuffers_ = false;
}
// init base render object
ACG::RenderObject ro;
// We simply take the data from the texture! -> No Lighting
_state.disable(GL_LIGHTING);
ro.initFromState(&_state);
ro.debugName = "SkyDome";
ro.priority = 100;
ACG::RenderObject::Texture tex;
tex.id = textureId_;
ro.addTexture(tex);
// Render with depth test enabled
ro.depthTest = true;
ro.blending = false;
// Compute a screen aligned quad ( Depth doesn't matter, as we compute depth in shader anyway, but we set it to the far plane)
ACG::Vec3d bottomLeft ( 0.0 , 0.0 , 0.99 );
ACG::Vec3d bottomRight( _state.viewport_width() , 0.0 , 0.99 );
ACG::Vec3d topLeft ( 0.0 , _state.viewport_height() , 0.99 );
ACG::Vec3d topRight ( _state.viewport_width() , _state.viewport_height() , 0.99 );
ACG::Vec3f unprojectedBottomLeft = ACG::Vec3f(_state.unproject(bottomLeft));
ACG::Vec3f unprojectedBottomRight = ACG::Vec3f(_state.unproject(bottomRight));
ACG::Vec3f unprojectedtopLeft = ACG::Vec3f(_state.unproject(topLeft));
ACG::Vec3f unprojectedtopRight = ACG::Vec3f(_state.unproject(topRight));
// Array of coordinates for the quad
float vboData_[4 * 3 * 4 ] = { unprojectedBottomLeft[0] , unprojectedBottomLeft[1] , unprojectedBottomLeft[2],
unprojectedBottomRight[0] , unprojectedBottomRight[1] , unprojectedBottomRight[2],
unprojectedtopRight[0] , unprojectedtopRight[1] , unprojectedtopRight[2],
unprojectedtopLeft[0] , unprojectedtopLeft[1] , unprojectedtopLeft[2]
};
if ( ! vbo_ ) {
glGenBuffersARB(1, &vbo_);
}
// Bind buffer
glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo_);
// Upload to buffer ( 4 vertices with 3 coordinates for point and normal of 4 byte sized floats)
glBufferDataARB(GL_ARRAY_BUFFER_ARB, 4 * 3 * 4, &vboData_[0], GL_STATIC_DRAW_ARB);
// Set the buffers for rendering
ro.shaderDesc.shadeMode = ACG::SG_SHADE_UNLIT;
ro.shaderDesc.vertexTemplateFile = OpenFlipper::Options::shaderDirStr() + QDir::separator() + "SkyDome" + QDir::separator() + "SkyDomeVertexShader.glsl";
ro.shaderDesc.fragmentTemplateFile = OpenFlipper::Options::shaderDirStr() + QDir::separator() + "SkyDome" + QDir::separator() + "SkyDomeFragmentShader.glsl";
ro.vertexBuffer = vbo_;
ro.vertexDecl = &vertexDecl_;
ACG::SceneGraph::Material localMaterial = *_mat;
localMaterial.baseColor(ACG::Vec4f(1.0,0.0,0.0,1.0) );
ro.setMaterial(&localMaterial);
ro.glDrawArrays(GL_QUADS, 0, 4);
ro.setUniform("uUpperCutOff" , dome_.topOffset() );
ro.setUniform("uHorizontalFOV" , dome_.horizontalFOV() );
ro.setUniform("uVerticalFOV" , dome_.verticalFOV() );
ro.setUniform("uVP_width" , float(_state.viewport_width()) );
ro.setUniform("uVP_height" , float(_state.viewport_height()) );
_renderer->addRenderObject(&ro);
}
//=============================================================================