/* * 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(); }