summaryrefslogtreecommitdiff
path: root/src/player/PolygonNode.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/player/PolygonNode.cpp')
-rw-r--r--src/player/PolygonNode.cpp219
1 files changed, 219 insertions, 0 deletions
diff --git a/src/player/PolygonNode.cpp b/src/player/PolygonNode.cpp
new file mode 100644
index 0000000..6e81b9b
--- /dev/null
+++ b/src/player/PolygonNode.cpp
@@ -0,0 +1,219 @@
+//
+// 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 "PolygonNode.h"
+
+#include "TypeDefinition.h"
+
+#include "../graphics/VertexArray.h"
+#include "../base/Exception.h"
+#include "../base/GeomHelper.h"
+#include "../base/triangulate/Triangulate.h"
+
+#include "../glm/gtx/norm.hpp"
+
+#include <iostream>
+#include <sstream>
+
+using namespace std;
+
+namespace avg {
+
+void PolygonNode::registerType()
+{
+ VectorVec2Vector cv;
+ vector<glm::vec2> v;
+ vector<float> vd;
+ TypeDefinition def = TypeDefinition("polygon", "filledvectornode",
+ ExportedObject::buildObject<PolygonNode>)
+ .addArg(Arg<string>("linejoin", "bevel"))
+ .addArg(Arg<vector<glm::vec2> >("pos", v, false, offsetof(PolygonNode, m_Pts)))
+ .addArg(Arg<vector<float> >("texcoords", vd, false,
+ offsetof(PolygonNode, m_TexCoords)))
+ .addArg(Arg<VectorVec2Vector>("holes", cv, false, offsetof(PolygonNode, m_Holes)))
+ ;
+ TypeRegistry::get()->registerType(def);
+}
+
+PolygonNode::PolygonNode(const ArgList& args)
+ : FilledVectorNode(args)
+{
+ args.setMembers(this);
+ if (m_TexCoords.size() > m_Pts.size()+1) {
+ throw(Exception(AVG_ERR_OUT_OF_RANGE,
+ "Too many texture coordinates in polygon"));
+ }
+ if (m_Pts.size() != 0 && m_Pts.size() < 3) {
+ throw(Exception(AVG_ERR_UNSUPPORTED,
+ "A polygon must have min. tree points."));
+ }
+ if (m_Holes.size() > 0) {
+ for (unsigned int i = 0; i < m_Holes.size(); i++) {
+ if (m_Holes[i].size() < 3) {
+ throw(Exception(AVG_ERR_UNSUPPORTED,
+ "A hole of a polygon must have min. tree points."));
+ }
+ }
+ }
+ setLineJoin(args.getArgVal<string>("linejoin"));
+ calcPolyLineCumulDist(m_CumulDist, m_Pts, true);
+}
+
+PolygonNode::~PolygonNode()
+{
+}
+
+const vector<glm::vec2>& PolygonNode::getPos() const
+{
+ return m_Pts;
+}
+
+void PolygonNode::setPos(const vector<glm::vec2>& pts)
+{
+ m_Pts.clear();
+ m_Pts = pts;
+ m_TexCoords.clear();
+ m_EffTexCoords.clear();
+ calcPolyLineCumulDist(m_CumulDist, m_Pts, true);
+ setDrawNeeded();
+}
+
+const vector<float>& PolygonNode::getTexCoords() const
+{
+ return m_TexCoords;
+}
+
+const VectorVec2Vector& PolygonNode::getHoles() const
+{
+ return m_Holes;
+}
+
+void PolygonNode::setHoles(const VectorVec2Vector& holes)
+{
+ m_Holes = holes;
+ m_TexCoords.clear();
+ m_EffTexCoords.clear();
+ setDrawNeeded();
+}
+
+void PolygonNode::setTexCoords(const vector<float>& coords)
+{
+ if (coords.size() > m_Pts.size()+1) {
+ throw(Exception(AVG_ERR_OUT_OF_RANGE,
+ "Too many texture coordinates in polygon"));
+ }
+ m_EffTexCoords.clear();
+ m_TexCoords = coords;
+ setDrawNeeded();
+}
+
+string PolygonNode::getLineJoin() const
+{
+ return lineJoin2String(m_LineJoin);
+}
+
+void PolygonNode::setLineJoin(const string& s)
+{
+ m_LineJoin = string2LineJoin(s);
+ setDrawNeeded();
+}
+
+void PolygonNode::getElementsByPos(const glm::vec2& pos, vector<NodePtr>& pElements)
+{
+ if (reactsToMouseEvents() && pointInPolygon(pos, m_Pts)) {
+ pElements.push_back(getSharedThis());
+ }
+}
+
+void PolygonNode::calcVertexes(const VertexDataPtr& pVertexData, Pixel32 color)
+{
+ if (getNumDifferentPts(m_Pts) < 3) {
+ return;
+ }
+ if (m_EffTexCoords.empty()) {
+ calcEffPolyLineTexCoords(m_EffTexCoords, m_TexCoords, m_CumulDist);
+ }
+ calcPolyLine(m_Pts, m_EffTexCoords, true, m_LineJoin, pVertexData, color);
+
+ for (unsigned i = 0; i < m_Holes.size(); i++) {
+ calcPolyLine(m_Holes[i], m_EffTexCoords, true, m_LineJoin, pVertexData, color);
+ }
+}
+
+void PolygonNode::calcFillVertexes(const VertexDataPtr& pVertexData, Pixel32 color)
+{
+ if (getNumDifferentPts(m_Pts) < 3) {
+ return;
+ }
+ // Remove duplicate points
+ vector<glm::vec2> pts;
+ vector<unsigned int> holeIndexes;
+ pts.reserve(m_Pts.size());
+
+ if (glm::distance2(m_Pts[0], m_Pts[m_Pts.size()-1]) > 0.1) {
+ pts.push_back(m_Pts[0]);
+ }
+ for (unsigned i = 1; i < m_Pts.size(); ++i) {
+ if (glm::distance2(m_Pts[i], m_Pts[i-1]) > 0.1) {
+ pts.push_back(m_Pts[i]);
+ }
+ }
+
+ if (m_Holes.size() > 0) {
+ for (unsigned int i = 0; i < m_Holes.size(); i++) { //loop over collection
+ holeIndexes.push_back(pts.size());
+ for (unsigned int j = 0; j < m_Holes[i].size(); j++) { //loop over vector
+ pts.push_back(m_Holes[i][j]);
+ }
+ }
+ }
+ if (color.getA() > 0) {
+ glm::vec2 minCoord = pts[0];
+ glm::vec2 maxCoord = pts[0];
+ for (unsigned i = 1; i < pts.size(); ++i) {
+ if (pts[i].x < minCoord.x) {
+ minCoord.x = pts[i].x;
+ }
+ if (pts[i].x > maxCoord.x) {
+ maxCoord.x = pts[i].x;
+ }
+ if (pts[i].y < minCoord.y) {
+ minCoord.y = pts[i].y;
+ }
+ if (pts[i].y > maxCoord.y) {
+ maxCoord.y = pts[i].y;
+ }
+ }
+ vector<unsigned int> triIndexes;
+ triangulatePolygon(triIndexes, pts, holeIndexes);
+
+ for (unsigned i = 0; i < pts.size(); ++i) {
+ glm::vec2 texCoord = calcFillTexCoord(pts[i], minCoord, maxCoord);
+ pVertexData->appendPos(pts[i], texCoord, color);
+ }
+ for (unsigned i = 0; i < triIndexes.size(); i+=3) {
+ pVertexData->appendTriIndexes(triIndexes[i], triIndexes[i+1],
+ triIndexes[i+2]);
+ }
+ }
+}
+
+}