diff options
Diffstat (limited to 'src/player/CircleNode.cpp')
-rw-r--r-- | src/player/CircleNode.cpp | 291 |
1 files changed, 291 insertions, 0 deletions
diff --git a/src/player/CircleNode.cpp b/src/player/CircleNode.cpp new file mode 100644 index 0000000..8d00a8e --- /dev/null +++ b/src/player/CircleNode.cpp @@ -0,0 +1,291 @@ +// +// libavg - Media Playback Engine. +// Copyright (C) 2003-2014 Ulrich von Zadow +// +// 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 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Current versions can be found at www.libavg.de +// + +#include "CircleNode.h" + +#include "TypeDefinition.h" + +#include "../base/Exception.h" +#include "../base/MathHelper.h" + +#include <iostream> +#include <sstream> + +using namespace std; + +namespace avg { + +void CircleNode::registerType() +{ + TypeDefinition def = TypeDefinition("circle", "filledvectornode", + ExportedObject::buildObject<CircleNode>) + .addArg(Arg<glm::vec2>("pos", glm::vec2(0,0), false, offsetof(CircleNode, m_Pos))) + .addArg(Arg<float>("r", 1, false, offsetof(CircleNode, m_Radius))) + .addArg(Arg<float>("texcoord1", 0, false, offsetof(CircleNode, m_TC1))) + .addArg(Arg<float>("texcoord2", 1, false, offsetof(CircleNode, m_TC2))) + ; + TypeRegistry::get()->registerType(def); +} + +CircleNode::CircleNode(const ArgList& args) + : FilledVectorNode(args) +{ + args.setMembers(this); +} + +CircleNode::~CircleNode() +{ +} + +const glm::vec2& CircleNode::getPos() const +{ + return m_Pos; +} + +void CircleNode::setPos(const glm::vec2& pt) +{ + m_Pos = pt; + setDrawNeeded(); +} + +float CircleNode::getR() const +{ + return m_Radius; +} + +void CircleNode::setR(float r) +{ + if (int(r) <= 0) { + throw Exception(AVG_ERR_OUT_OF_RANGE, "Circle radius must be a positive number."); + } + m_Radius = r; + setDrawNeeded(); +} + +float CircleNode::getTexCoord1() const +{ + return m_TC1; +} + +void CircleNode::setTexCoord1(float tc) +{ + m_TC1 = tc; + setDrawNeeded(); +} + +float CircleNode::getTexCoord2() const +{ + return m_TC2; +} + +void CircleNode::setTexCoord2(float tc) +{ + m_TC2 = tc; + setDrawNeeded(); +} + +void CircleNode::getElementsByPos(const glm::vec2& pos, vector<NodePtr>& pElements) +{ + if (glm::length(pos-m_Pos) <= m_Radius && reactsToMouseEvents()) { + pElements.push_back(getSharedThis()); + } +} + +void CircleNode::calcVertexes(const VertexDataPtr& pVertexData, Pixel32 color) +{ + // TODO: This gets called whenever the circle position changes and is quite + // expensive. Should be optimized away. + glm::vec2 firstPt1 = getCirclePt(0, m_Radius+getStrokeWidth()/2)+m_Pos; + glm::vec2 firstPt2 = getCirclePt(0, m_Radius-getStrokeWidth()/2)+m_Pos; + int curVertex = 0; + pVertexData->appendPos(firstPt1, glm::vec2(m_TC1, 0), color); + pVertexData->appendPos(firstPt2, glm::vec2(m_TC1, 1), color); + vector<glm::vec2> innerCircle; + getEigthCirclePoints(innerCircle, m_Radius-getStrokeWidth()/2); + vector<glm::vec2> outerCircle; + getEigthCirclePoints(outerCircle, m_Radius+getStrokeWidth()/2); + + typedef vector<glm::vec2>::iterator Vec2It; + typedef vector<glm::vec2>::reverse_iterator Vec2RIt; + int i = 0; + for (Vec2It iit = innerCircle.begin()+1, oit = outerCircle.begin()+1; + iit != innerCircle.end(); ++iit, ++oit) + { + appendCirclePoint(pVertexData, *iit, *oit, color, i, curVertex); + } + for (Vec2RIt iit = innerCircle.rbegin()+1, oit = outerCircle.rbegin()+1; + iit != innerCircle.rend(); ++iit, ++oit) + { + glm::vec2 iPt = glm::vec2(-iit->y, -iit->x); + glm::vec2 oPt = glm::vec2(-oit->y, -oit->x); + appendCirclePoint(pVertexData, iPt, oPt, color, i, curVertex); + } + for (Vec2It iit = innerCircle.begin()+1, oit = outerCircle.begin()+1; + iit != innerCircle.end(); ++iit, ++oit) + { + glm::vec2 iPt = glm::vec2(-iit->y, iit->x); + glm::vec2 oPt = glm::vec2(-oit->y, oit->x); + appendCirclePoint(pVertexData, iPt, oPt, color, i, curVertex); + } + for (Vec2RIt iit = innerCircle.rbegin()+1, oit = outerCircle.rbegin()+1; + iit !=innerCircle.rend(); ++iit, ++oit) + { + glm::vec2 iPt = glm::vec2(iit->x, -iit->y); + glm::vec2 oPt = glm::vec2(oit->x, -oit->y); + appendCirclePoint(pVertexData, iPt, oPt, color, i, curVertex); + } + for (Vec2It iit = innerCircle.begin()+1, oit = outerCircle.begin()+1; + iit != innerCircle.end(); ++iit, ++oit) + { + glm::vec2 iPt = glm::vec2(-iit->x, -iit->y); + glm::vec2 oPt = glm::vec2(-oit->x, -oit->y); + appendCirclePoint(pVertexData, iPt, oPt, color, i, curVertex); + } + for (Vec2RIt iit = innerCircle.rbegin()+1, oit = outerCircle.rbegin()+1; + iit != innerCircle.rend(); ++iit, ++oit) + { + glm::vec2 iPt = glm::vec2(iit->y, iit->x); + glm::vec2 oPt = glm::vec2(oit->y, oit->x); + appendCirclePoint(pVertexData, iPt, oPt, color, i, curVertex); + } + for (Vec2It iit = innerCircle.begin()+1, oit = outerCircle.begin()+1; + iit != innerCircle.end(); ++iit, ++oit) + { + glm::vec2 iPt = glm::vec2(iit->y, -iit->x); + glm::vec2 oPt = glm::vec2(oit->y, -oit->x); + appendCirclePoint(pVertexData, iPt, oPt, color, i, curVertex); + } + for (Vec2RIt iit = innerCircle.rbegin()+1, oit = outerCircle.rbegin()+1; + iit != innerCircle.rend(); ++iit, ++oit) + { + glm::vec2 iPt = glm::vec2(-iit->x, iit->y); + glm::vec2 oPt = glm::vec2(-oit->x, oit->y); + appendCirclePoint(pVertexData, iPt, oPt, color, i, curVertex); + } +} + +void CircleNode::calcFillVertexes(const VertexDataPtr& pVertexData, Pixel32 color) +{ + glm::vec2 minPt = m_Pos-glm::vec2(m_Radius, m_Radius); + glm::vec2 maxPt = m_Pos+glm::vec2(m_Radius, m_Radius); + glm::vec2 centerTexCoord = calcFillTexCoord(m_Pos, minPt, maxPt); + pVertexData->appendPos(m_Pos, centerTexCoord, color); + int curVertex = 1; + glm::vec2 firstPt = getCirclePt(0, m_Radius)+m_Pos; + glm::vec2 firstTexCoord = calcFillTexCoord(firstPt, minPt, maxPt); + pVertexData->appendPos(firstPt, firstTexCoord, color); + vector<glm::vec2> circlePoints; + getEigthCirclePoints(circlePoints, m_Radius); + + for (vector<glm::vec2>::iterator it = circlePoints.begin()+1; + it != circlePoints.end(); ++it) + { + glm::vec2 curPt = *it+m_Pos; + appendFillCirclePoint(pVertexData, curPt, minPt, maxPt, color, curVertex); + } + for (vector<glm::vec2>::reverse_iterator it = circlePoints.rbegin()+1; + it != circlePoints.rend(); ++it) + { + glm::vec2 curPt = glm::vec2(-it->y, -it->x)+m_Pos; + appendFillCirclePoint(pVertexData, curPt, minPt, maxPt, color, curVertex); + } + for (vector<glm::vec2>::iterator it = circlePoints.begin()+1; + it != circlePoints.end(); ++it) + { + glm::vec2 curPt = glm::vec2(-it->y, it->x)+m_Pos; + appendFillCirclePoint(pVertexData, curPt, minPt, maxPt, color, curVertex); + } + for (vector<glm::vec2>::reverse_iterator it = circlePoints.rbegin()+1; + it != circlePoints.rend(); ++it) + { + glm::vec2 curPt = glm::vec2(it->x, -it->y)+m_Pos; + appendFillCirclePoint(pVertexData, curPt, minPt, maxPt, color, curVertex); + } + for (vector<glm::vec2>::iterator it = circlePoints.begin()+1; + it != circlePoints.end(); ++it) + { + glm::vec2 curPt = glm::vec2(-it->x, -it->y)+m_Pos; + appendFillCirclePoint(pVertexData, curPt, minPt, maxPt, color, curVertex); + } + for (vector<glm::vec2>::reverse_iterator it = circlePoints.rbegin()+1; + it != circlePoints.rend(); ++it) + { + glm::vec2 curPt = glm::vec2(it->y, it->x)+m_Pos; + appendFillCirclePoint(pVertexData, curPt, minPt, maxPt, color, curVertex); + } + for (vector<glm::vec2>::iterator it = circlePoints.begin()+1; + it != circlePoints.end(); ++it) + { + glm::vec2 curPt = glm::vec2(it->y, -it->x)+m_Pos; + appendFillCirclePoint(pVertexData, curPt, minPt, maxPt, color, curVertex); + } + for (vector<glm::vec2>::reverse_iterator it = circlePoints.rbegin()+1; + it != circlePoints.rend(); ++it) + { + glm::vec2 curPt = glm::vec2(-it->x, it->y)+m_Pos; + appendFillCirclePoint(pVertexData, curPt, minPt, maxPt, color, curVertex); + } +} + +void CircleNode::appendCirclePoint(const VertexDataPtr& pVertexData, + const glm::vec2& iPt, const glm::vec2& oPt, Pixel32 color, int& i, + int& curVertex) +{ + i++; + float ratio = (float(i)/getNumCircumferencePoints()); + float curTC = (1-ratio)*m_TC1+ratio*m_TC2; + pVertexData->appendPos(oPt+m_Pos, glm::vec2(curTC, 0), color); + pVertexData->appendPos(iPt+m_Pos, glm::vec2(curTC, 1), color); + pVertexData->appendQuadIndexes(curVertex+1, curVertex, curVertex+3, curVertex+2); + curVertex += 2; +} + +void CircleNode::appendFillCirclePoint(const VertexDataPtr& pVertexData, + const glm::vec2& curPt, const glm::vec2& minPt, const glm::vec2& maxPt, + Pixel32 color, int& curVertex) +{ + glm::vec2 curTexCoord = calcFillTexCoord(curPt, minPt, maxPt); + pVertexData->appendPos(curPt, curTexCoord, color); + pVertexData->appendTriIndexes(0, curVertex, curVertex+1); + curVertex++; +} + +int CircleNode::getNumCircumferencePoints() +{ + return int(ceil((m_Radius*3)/8)*8); +} + +void CircleNode::getEigthCirclePoints(vector<glm::vec2>& pts, float radius) +{ + int numPts = getNumCircumferencePoints(); + for (int i = 0; i <= numPts/8; ++i) { + float ratio = (float(i)/numPts); + float angle = ratio*2*PI; + pts.push_back(getCirclePt(angle, radius)); + } +} + +glm::vec2 CircleNode::getCirclePt(float angle, float radius) +{ + return glm::vec2(sin(angle)*radius, -cos(angle)*radius); +} + +} |