/*
* Project: MoleCuilder
* Description: creates and alters molecular systems
* Copyright (C) 2010-2012 University of Bonn. All rights reserved.
* Copyright (C) 2013 Frederik Heber. All rights reserved.
*
*
* This file is part of MoleCuilder.
*
* MoleCuilder 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.
*
* MoleCuilder 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 MoleCuilder. If not, see .
*/
/*
* GLMoleculeObject_shape.cpp
*
* Created on: Aug 3, 2012
* Author: ankele
*/
// include config.h
#ifdef HAVE_CONFIG_H
#include
#endif
#include "GLMoleculeObject_shape.hpp"
#include
#include
#include
#include
#include
#include
#include "CodePatterns/MemDebug.hpp"
#include "CodePatterns/Assert.hpp"
#include "CodePatterns/Log.hpp"
#include "Shapes/ShapeFactory.hpp"
#include "LinearAlgebra/Vector.hpp"
#include "LinkedCell/PointCloudAdaptor.hpp"
#include "LinkedCell/linkedcell.hpp"
#include "Tesselation/tesselation.hpp"
#include "Tesselation/BoundaryLineSet.hpp"
#include "Tesselation/BoundaryTriangleSet.hpp"
#include "Tesselation/CandidateForTesselation.hpp"
#include "Atom/TesselPoint.hpp"
typedef QGLSceneNode *MeshList[GLMoleculeObject::DETAILTYPES_MAX];
static QGLSceneNode *createShapeMesh(Shape &shape, QObject *parent)
{
size_t NumPointsonSurface = 200;
// guess the surface area which divided by 200 determines rolling sphere's size
const double surfacearea = shape.getSurfaceArea();
const size_t EstimatedNumberTriangles = NumPointsonSurface*1;
const double MeanAreaPerTriangle = surfacearea/((double)EstimatedNumberTriangles);
// assume two triangles to form a square and take its diameter as the radius
double minradius = sqrt(2. * 2.*MeanAreaPerTriangle);
LOG(3, "DEBUG: Surface area is " << surfacearea << ", minradius is " << minradius << ".");
if (minradius < 1.)
minradius = 1.;
LOG(2, "DEBUG: Tesselating shape " << shape.getName() << " with sphere of radius " << minradius << ".");
// Create some points on our shape.
std::vector points = shape.getHomogeneousPointsOnSurface(NumPointsonSurface);
QGeometryData geo;
// we need at least three points for tesselation
if (points.size() >= 3) {
// Fill the points into a tesselate-able container.
TesselPointSTLList Corners;
for (size_t i=0;isetPosition(points[i]);
Walker->setName(toString(i));
Walker->setNr(i);
Corners.push_back(Walker);
}
// Tesselate the points.
Tesselation T;
PointCloudAdaptor cloud(&Corners, "TesselPointSTLList");
T(cloud, minradius);
// Fill the points into a Qt geometry.
LinkedCell_deprecated LinkedList(cloud, minradius);
std::vector normals;
normals.resize(points.size(), zeroVec);
for(size_t i=0;isecond->endpoints[i]->node->getNr();
// Sort the vertices so the triangle is clockwise (relative to the normal vector).
Vector cross = points[v[1]] - points[v[0]];
cross.VectorProduct(points[v[2]] - points[v[0]]);
if (cross.ScalarProduct(normals[v[0]] + normals[v[1]] + normals[v[2]]) > 0)
geo.appendIndices(v[0], v[1], v[2]);
else
geo.appendIndices(v[0], v[2], v[1]);
}
}
// Build a mesh from the geometry.
QGLBuilder builder;
builder.addTriangles(geo);
QGLSceneNode *mesh = builder.finalizedSceneNode();
return mesh;
}
GLMoleculeObject_shape::GLMoleculeObject_shape(Shape &shape, QObject *parent) :
GLMoleculeObject(createShapeMesh(shape, parent), parent),
m_shape(shape)
{
// Create the material.
QGLMaterial *material = new QGLMaterial(NULL);
material->setAmbientColor( QColor(50, 60, 100, 255) );
material->setDiffuseColor( QColor(150, 160, 200, 180) );
material->setSpecularColor( QColor(60, 60, 60) );
material->setShininess( 128 );
setMaterial(material);
m_enabled = false;
}
GLMoleculeObject_shape::~GLMoleculeObject_shape()
{
}
void GLMoleculeObject_shape::enable(bool enabled)
{
m_enabled = enabled;
}
void GLMoleculeObject_shape::draw(QGLPainter *painter, const QVector4D &cameraPlane)
{
if (!m_enabled)
return;
painter->modelViewMatrix().push();
painter->setColor(m_material->diffuseColor());
painter->setFaceMaterial(QGL::AllFaces, m_material);
// Draw the transparent cube.
painter->setStandardEffect(QGL::LitMaterial);
glCullFace(GL_BACK);
glEnable(GL_CULL_FACE);
glEnable(GL_BLEND);
glDepthMask(0);
glDisable(GL_DEPTH_TEST);
m_mesh[0]->draw(painter);
glEnable(GL_DEPTH_TEST);
glDepthMask(1);
glDisable(GL_BLEND);
glDisable(GL_CULL_FACE);
painter->modelViewMatrix().pop();
}