/******************************************************************************* * CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * * version 0.1 * * Copyright (C) 2009-2011, IGG Team, LSIIT, University of Strasbourg * * * * This library 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 2.1 of the License, or (at your * * option) any later version. * * * * This library 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 Lesser General Public License * * along with this library; if not, write to the Free Software Foundation, * * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * * * Web site: http://cgogn.u-strasbg.fr/ * * Contact information: cgogn@unistra.fr * * * *******************************************************************************/ #include "Utils/pickables.h" #include "glm/gtc/matrix_transform.hpp" #include "Geometry/distances.h" #include "Geometry/intersection.h" #include #include namespace CGoGN { namespace Utils { LineDrawable::LineDrawable() { m_vboPos = new VBO(); m_vboPos->setDataSize(3); m_shader = new ShaderSimpleColor(); m_shader->setAttributePosition(m_vboPos); m_shader->setColor(Geom::Vec4f(1.,1.,0.,0.)); GLSLShader::registerShader(NULL, m_shader); glGenBuffers(1, &m_ind); } LineDrawable::~LineDrawable() { delete m_vboPos; GLSLShader::unregisterShader(NULL, m_shader); delete m_shader; glDeleteBuffers(1, &m_ind); } void LineDrawable::setColor(const Geom::Vec4f& col) { m_shader->setColor(col); } void LineDrawable::draw() { m_shader->enableVertexAttribs(); glDrawArrays(GL_LINES, 0, m_nb); m_shader->disableVertexAttribs(); } Pickable::Pickable(LineDrawable* ld, unsigned int id): m_drawable(ld),m_transfo(1.0f), m_id(id) { } void Pickable::invertPV(const Geom::Vec3f& P, const Geom::Vec3f& V, const glm::mat4& transfo, Geom::Vec3f& PP, Geom::Vec3f& VV) { glm::mat4 invtr = glm::inverse(transfo); glm::vec4 xP(P[0],P[1],P[2],1.0f); glm::vec4 xQ(P[0]+V[0],P[1]+V[1],P[2]+V[2],1.0f); glm::vec4 tP = invtr*xP; glm::vec4 tQ = invtr*xQ; PP = Geom::Vec3f(tP[0]/tP[3], tP[1]/tP[3], tP[2]/tP[3]); VV = Geom::Vec3f(tQ[0]/tQ[3] - PP[0], tQ[1]/tQ[3] - PP[1], tQ[2]/tQ[3]- PP[2]); } bool Pickable::pick(const Geom::Vec3f& P, const Geom::Vec3f& V, float epsilon) { Geom::Vec3f PP; Geom::Vec3f VV; invertPV(P,V,m_transfo,PP,VV); return m_drawable->pick(PP,VV,epsilon) != 0; } void Pickable::draw() { glm::mat4 store = Utils::GLSLShader::currentTransfo(); Utils::GLSLShader::currentTransfo() *= m_transfo; Utils::GLSLShader::updateCurrentMatrices(); m_drawable->draw(); Utils::GLSLShader::currentTransfo() = store; } glm::mat4& Pickable::transfo() { return m_transfo; } void Pickable::rotate(float angle, const Geom::Vec3f& Axis) { m_transfo = glm::rotate(m_transfo, angle, glm::vec3(Axis[0],Axis[1],Axis[2])); } //void Pickable::rotate(float angle, const Geom::Vec3f& Axis) //{ // glm::mat4 tr = glm::rotate(glm::mat4(1.0f), angle, glm::vec3(Axis[0],Axis[1],Axis[2])); // m_transfo = tr*m_transfo; //} void Pickable::translate(const Geom::Vec3f& P) { m_transfo = glm::translate(m_transfo, glm::vec3(P[0],P[1],P[2])); } //void Pickable::translate(const Geom::Vec3f& P) //{ // glm::mat4 tr = glm::translate(glm::mat4(1.0f), glm::vec3(P[0],P[1],P[2])); // m_transfo = tr*m_transfo; //} void Pickable::scale(const Geom::Vec3f& S) { m_transfo = glm::scale(m_transfo, glm::vec3(S[0],S[1],S[2])); } //void Pickable::scale(const Geom::Vec3f& S) //{ // glm::mat4 tr = glm::scale(glm::mat4(1.0f), glm::vec3(S[0],S[1],S[2])); // m_transfo = tr*m_transfo; //} // TODO check why BUG void Pickable::randomOrientation() { Geom::Vec3f V1(float(rand() - RAND_MAX/2), float(rand() - RAND_MAX/2), float(rand() - RAND_MAX/2)); V1.normalize(); float angle = float(rand()%360); rotate(angle,V1); } void Pickable::randomScale(float min, float max) { const unsigned int MAX_NB=10000; float amp = (max - min)/MAX_NB; float sx = float((rand()%MAX_NB))*amp + min; float sy = float((rand()%MAX_NB))*amp + min; float sz = float((rand()%MAX_NB))*amp + min; scale(Geom::Vec3f(sx,sy,sz)); } void Pickable::randomUniformScale(float min, float max) { const unsigned int MAX_NB=10000; float amp = (max - min)/MAX_NB; float sc = float((rand()%MAX_NB))*amp + min; scale(Geom::Vec3f(sc,sc,sc)); } float Pickable::distancefrom(const Geom::Vec3f& P) { Geom::Vec3f origin(m_transfo[3][0],m_transfo[3][1],m_transfo[3][2]); origin -= P; return float(origin.norm()); } Pickable* Pickable::pick(const std::vector& picks,const Geom::Vec3f& P, const Geom::Vec3f& V) { float mdist = std::numeric_limits::max(); Pickable* res=NULL; for (std::vector::const_iterator it=picks.begin(); it != picks.end(); ++it) { if ((*it)->pick(P,V)) { float dist = (*it)->distancefrom(P); if (dist < mdist) { res = *it; mdist = dist; } } } return res; } bool Pickable::distOrder(const std::pair& e1, const std::pair& e2) { return (e1.first < e2.first); } std::vector Pickable::sortedPick(std::vector& picks, const Geom::Vec3f& P, const Geom::Vec3f& V) { std::vector< std::pair > sorted; sorted.reserve(picks.size()); for (std::vector::const_iterator it=picks.begin(); it != picks.end(); ++it) { if ((*it)->pick(P,V)) { float dist = (*it)->distancefrom(P); sorted.push_back(std::pair(dist,*it)); } } std::sort(sorted.begin(), sorted.end(),distOrder); std::vector res; res.reserve(sorted.size()); for (unsigned int i=0; i points; points.resize((sub+1)*2*2); m_nb=0; for (unsigned int i=0; i<=sub; ++i) { float a = -1.0f + (2.0f/sub)*i; points[4*i] = Geom::Vec3f(a,-1.0f,0.0f); points[4*i+1] = Geom::Vec3f(a,1.0f,0.0f); points[4*i+2] = Geom::Vec3f(-1.0f,a,0.0f); points[4*i+3] = Geom::Vec3f(1.0f,a,0.0f); m_nb+=4; } m_vboPos->bind(); glBufferData(GL_ARRAY_BUFFER, m_nb * sizeof(Geom::Vec3f), &(points[0]), GL_STREAM_DRAW); } void Grid::updatePrecisionDrawing(unsigned int sub, unsigned int sub2) { changeTopo(sub); } unsigned int Grid::pick(const Geom::Vec3f& P, const Geom::Vec3f& V, float epsilon) { if (fabsf(V[2])>=0.0000001f) { float a = -1.0f*P[2]/V[2]; Geom::Vec3f Q = Geom::Vec3f(P+a*V); // intersection with plane z=0 if ( (fabsf(Q[0])<=1.0f) && (fabsf(Q[1])<=1.0f) ) return 1; } return 0; } Sphere::Sphere(unsigned int par, unsigned int mer) { changeTopo(par,mer); } void Sphere::changeTopo(unsigned int parp, unsigned int mer) { // to obtain right number of slice unsigned int par = parp-1; unsigned int merfactor=1; unsigned int parfactor=1; if (mer<8) merfactor = 8; else if (mer<16) merfactor = 4; else if (mer<32) merfactor = 2; if (par<8) parfactor = 8; else if (par<16) parfactor = 4; else if (par<32) parfactor = 2; unsigned int merAll = merfactor * mer; unsigned int parAll = parfactor* (par+1); // parAll += 1; std::vector points; points.reserve(parAll*merAll+2); std::cout << "PAR="<