From 62e42408485e9e1b7e939925b650a4b2e90ecddb Mon Sep 17 00:00:00 2001 From: neoraider Date: Fri, 21 Sep 2007 21:47:05 +0000 Subject: zoomedit: Big transition Ciaro -> OpenGL, enormous speedup! --- Makefile.am | 8 +- Makefile.in | 46 ++++---- Polygon.cpp | 205 +++++++++++++++++++++++++++++++++++- Polygon.h | 22 ++++ Rectangle.h | 10 +- Triangle.cpp | 36 +++++++ Triangle.h | 39 +++++++ aclocal.m4 | 231 +++++++++++++++++++++++++++++++++++++++++ configure | 334 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- configure.in | 1 + draw.cpp | 234 +++++++++++++++++------------------------ draw.h | 4 +- edit.cpp | 19 +--- edit.h | 1 - geometry.cpp | 80 -------------- geometry.h | 11 -- window.cpp | 168 +++++++++++++++++++----------- window.h | 3 +- zoomedit.cpp | 12 ++- 19 files changed, 1114 insertions(+), 350 deletions(-) create mode 100644 Triangle.cpp create mode 100644 Triangle.h delete mode 100644 geometry.cpp delete mode 100644 geometry.h diff --git a/Makefile.am b/Makefile.am index 4ae72e8..94ded86 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,5 +1,5 @@ bin_PROGRAMS = zoomedit -zoomedit_SOURCES = zoomedit.cpp window.cpp ui.cpp draw.cpp edit.cpp geometry.cpp \ - Vertex.cpp Line.cpp Polygon.cpp Rectangle.cpp Room.cpp -zoomedit_CPPFLAGS = @GTK_CFLAGS@ -zoomedit_LDADD = @GTK_LIBS@ \ No newline at end of file +zoomedit_SOURCES = zoomedit.cpp window.cpp ui.cpp draw.cpp edit.cpp Vertex.cpp \ + Line.cpp Polygon.cpp Rectangle.cpp Room.cpp Triangle.cpp +zoomedit_CPPFLAGS = @GTK_CFLAGS@ @GTKGLEXT_CFLAGS@ +zoomedit_LDADD = @GTK_LIBS@ @GTKGLEXT_LIBS@ \ No newline at end of file diff --git a/Makefile.in b/Makefile.in index ef8432a..9762995 100644 --- a/Makefile.in +++ b/Makefile.in @@ -51,9 +51,9 @@ PROGRAMS = $(bin_PROGRAMS) am_zoomedit_OBJECTS = zoomedit-zoomedit.$(OBJEXT) \ zoomedit-window.$(OBJEXT) zoomedit-ui.$(OBJEXT) \ zoomedit-draw.$(OBJEXT) zoomedit-edit.$(OBJEXT) \ - zoomedit-geometry.$(OBJEXT) zoomedit-Vertex.$(OBJEXT) \ - zoomedit-Line.$(OBJEXT) zoomedit-Polygon.$(OBJEXT) \ - zoomedit-Rectangle.$(OBJEXT) zoomedit-Room.$(OBJEXT) + zoomedit-Vertex.$(OBJEXT) zoomedit-Line.$(OBJEXT) \ + zoomedit-Polygon.$(OBJEXT) zoomedit-Rectangle.$(OBJEXT) \ + zoomedit-Room.$(OBJEXT) zoomedit-Triangle.$(OBJEXT) zoomedit_OBJECTS = $(am_zoomedit_OBJECTS) zoomedit_DEPENDENCIES = DEFAULT_INCLUDES = -I.@am__isrc@ @@ -102,6 +102,8 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ GREP = @GREP@ +GTKGLEXT_CFLAGS = @GTKGLEXT_CFLAGS@ +GTKGLEXT_LIBS = @GTKGLEXT_LIBS@ GTK_CFLAGS = @GTK_CFLAGS@ GTK_LIBS = @GTK_LIBS@ INSTALL = @INSTALL@ @@ -171,11 +173,11 @@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ -zoomedit_SOURCES = zoomedit.cpp window.cpp ui.cpp draw.cpp edit.cpp geometry.cpp \ - Vertex.cpp Line.cpp Polygon.cpp Rectangle.cpp Room.cpp +zoomedit_SOURCES = zoomedit.cpp window.cpp ui.cpp draw.cpp edit.cpp Vertex.cpp \ + Line.cpp Polygon.cpp Rectangle.cpp Room.cpp Triangle.cpp -zoomedit_CPPFLAGS = @GTK_CFLAGS@ -zoomedit_LDADD = @GTK_LIBS@ +zoomedit_CPPFLAGS = @GTK_CFLAGS@ @GTKGLEXT_CFLAGS@ +zoomedit_LDADD = @GTK_LIBS@ @GTKGLEXT_LIBS@ all: config.h $(MAKE) $(AM_MAKEFLAGS) all-am @@ -268,10 +270,10 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zoomedit-Polygon.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zoomedit-Rectangle.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zoomedit-Room.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zoomedit-Triangle.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zoomedit-Vertex.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zoomedit-draw.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zoomedit-edit.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zoomedit-geometry.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zoomedit-ui.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zoomedit-window.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zoomedit-zoomedit.Po@am__quote@ @@ -360,20 +362,6 @@ zoomedit-edit.obj: edit.cpp @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(zoomedit_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o zoomedit-edit.obj `if test -f 'edit.cpp'; then $(CYGPATH_W) 'edit.cpp'; else $(CYGPATH_W) '$(srcdir)/edit.cpp'; fi` -zoomedit-geometry.o: geometry.cpp -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(zoomedit_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT zoomedit-geometry.o -MD -MP -MF $(DEPDIR)/zoomedit-geometry.Tpo -c -o zoomedit-geometry.o `test -f 'geometry.cpp' || echo '$(srcdir)/'`geometry.cpp -@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/zoomedit-geometry.Tpo $(DEPDIR)/zoomedit-geometry.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='geometry.cpp' object='zoomedit-geometry.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(zoomedit_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o zoomedit-geometry.o `test -f 'geometry.cpp' || echo '$(srcdir)/'`geometry.cpp - -zoomedit-geometry.obj: geometry.cpp -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(zoomedit_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT zoomedit-geometry.obj -MD -MP -MF $(DEPDIR)/zoomedit-geometry.Tpo -c -o zoomedit-geometry.obj `if test -f 'geometry.cpp'; then $(CYGPATH_W) 'geometry.cpp'; else $(CYGPATH_W) '$(srcdir)/geometry.cpp'; fi` -@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/zoomedit-geometry.Tpo $(DEPDIR)/zoomedit-geometry.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='geometry.cpp' object='zoomedit-geometry.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(zoomedit_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o zoomedit-geometry.obj `if test -f 'geometry.cpp'; then $(CYGPATH_W) 'geometry.cpp'; else $(CYGPATH_W) '$(srcdir)/geometry.cpp'; fi` - zoomedit-Vertex.o: Vertex.cpp @am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(zoomedit_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT zoomedit-Vertex.o -MD -MP -MF $(DEPDIR)/zoomedit-Vertex.Tpo -c -o zoomedit-Vertex.o `test -f 'Vertex.cpp' || echo '$(srcdir)/'`Vertex.cpp @am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/zoomedit-Vertex.Tpo $(DEPDIR)/zoomedit-Vertex.Po @@ -444,6 +432,20 @@ zoomedit-Room.obj: Room.cpp @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(zoomedit_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o zoomedit-Room.obj `if test -f 'Room.cpp'; then $(CYGPATH_W) 'Room.cpp'; else $(CYGPATH_W) '$(srcdir)/Room.cpp'; fi` +zoomedit-Triangle.o: Triangle.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(zoomedit_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT zoomedit-Triangle.o -MD -MP -MF $(DEPDIR)/zoomedit-Triangle.Tpo -c -o zoomedit-Triangle.o `test -f 'Triangle.cpp' || echo '$(srcdir)/'`Triangle.cpp +@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/zoomedit-Triangle.Tpo $(DEPDIR)/zoomedit-Triangle.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='Triangle.cpp' object='zoomedit-Triangle.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(zoomedit_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o zoomedit-Triangle.o `test -f 'Triangle.cpp' || echo '$(srcdir)/'`Triangle.cpp + +zoomedit-Triangle.obj: Triangle.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(zoomedit_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT zoomedit-Triangle.obj -MD -MP -MF $(DEPDIR)/zoomedit-Triangle.Tpo -c -o zoomedit-Triangle.obj `if test -f 'Triangle.cpp'; then $(CYGPATH_W) 'Triangle.cpp'; else $(CYGPATH_W) '$(srcdir)/Triangle.cpp'; fi` +@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/zoomedit-Triangle.Tpo $(DEPDIR)/zoomedit-Triangle.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='Triangle.cpp' object='zoomedit-Triangle.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(zoomedit_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o zoomedit-Triangle.obj `if test -f 'Triangle.cpp'; then $(CYGPATH_W) 'Triangle.cpp'; else $(CYGPATH_W) '$(srcdir)/Triangle.cpp'; fi` + ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ diff --git a/Polygon.cpp b/Polygon.cpp index 9340135..3425727 100644 --- a/Polygon.cpp +++ b/Polygon.cpp @@ -1,8 +1,9 @@ #include "Polygon.h" +#include #include -double Polygon::area() const { +double Polygon::signedArea() const { double d = 0.0; for(const_iterator it = begin(); it != end(); it++) { @@ -12,7 +13,17 @@ double Polygon::area() const { d += (it2->getX()+it->getX())*(it2->getY()-it->getY()); } - return fabs(d/2); + return d/2; +} + +Polygon::Direction Polygon::getDirection() const { + double area = signedArea(); + + return (area > 0) ? Triangle::CW : (area < 0) ? Triangle::CCW : Triangle::Unknown; +} + +double Polygon::area() const { + return fabs(signedArea()); } double Polygon::perimeter() const { @@ -103,8 +114,8 @@ bool Polygon::contains(const Vertex &v) const { bool Polygon::intersects(const Line &l) const { Line line; - for(Polygon::const_iterator it = begin(); it != end(); it++) { - Polygon::const_iterator it2 = it+1; + for(const_iterator it = begin(); it != end(); it++) { + const_iterator it2 = it+1; if(it2 == end()) it2 = begin(); line.setVertex1(*it); @@ -116,3 +127,189 @@ bool Polygon::intersects(const Line &l) const { return false; } + +bool Polygon::isConcave(const Direction &dir, const Vertex &v1, const Vertex &v2, const Vertex &v3) const { + switch(dir) { + case Triangle::CW: + return (v1.getX()-v2.getX())*(v3.getY()-v2.getY()) > (v3.getX()-v2.getX())*(v1.getY()-v2.getY()); + case Triangle::CCW: + return (v1.getX()-v2.getX())*(v3.getY()-v2.getY()) < (v3.getX()-v2.getX())*(v1.getY()-v2.getY()); + } + + return false; +} + +bool Polygon::intersections(std::vector *intersections) const { + bool ret = false; + size_t s = size(); + + for(size_t i = 0; i+2 < s; i++) { + Line l(at(i), at(i+1)); + + for(size_t j = i+2; j < s; j++) { + if(i == (j+1)%s) continue; + + Line l2(at(j), at((j+1)%s)); + + Vertex v; + if(l.intersects(l2, &v) == INTERSECTION_SEGMENT_SEGMENT) { + if(intersections) { + Intersection in = {i, i+1, j, ((j+1)%s), v}; + + intersections->push_back(in); + ret = true; + } + else { + return true; + } + } + } + } + + return ret; +} + +bool Polygon::isSimple() const { + return !intersections(); +} + +bool Polygon::simplify(Polygon &polygon) const { + std::vector ins; + + if(!intersections(&ins)) return false; + + int s = size(); + int start = 0; + + for(int i = 1; i < s; i++) { + if(at(i).getX() < at(start).getX()) + start = i; + else if(at(i).getX() == at(start).getX() && at(i).getY() < at(start).getY()) + start = i; + } + + int dir = Triangle(at((s+start-1)%s), at(start), at((start+1)%s)).getDirection(); + + int i2 = start; + const Vertex *v2 = &at(i2); + bool intersected; + + do { + intersected = false; + + int i = i2; + + if(dir == Triangle::CW) + i2 = (i2+1)%s; + else + i2 = (s+i2-1)%s; + + const Vertex *v1 = v2; + v2 = &at(i2); + + Vertex *v = NULL; + int v3, v4; + + for(std::vector::iterator in = ins.begin(); in != ins.end(); ++in) { + if(v2->distanceSq(in->v) >= v2->distanceSq(*v1) || v1 == &in->v) + continue; + + if(v) { + if(v1->distanceSq(in->v) >= v1->distanceSq(*v)) + continue; + } + + if((i == in->va1 && i2 == in->va2) || (i == in->va2 && i2 == in->va1)) { + v = &in->v; + v3 = in->vb1; + v4 = in->vb2; + } + else if((i == in->vb1 && i2 == in->vb2) || (i == in->vb2 && i2 == in->vb1)) { + v = &in->v; + v3 = in->va1; + v4 = in->va2; + } + } + + if(v) { + v2 = v; + intersected = true; + + if(isConcave(Triangle::CW, *v1, *v2, at(v4))) { + i2 = v3; + dir = Triangle::CW; + } + else { + i2 = v4; + dir = Triangle::CCW; + } + } + + polygon.push_back(*v2); + } while(i2 != start || intersected); + + return true; +} + +// FIXME: has still some problems... +void Polygon::doTriangulate(std::vector &triangles) const { + size_t s = size(); + + if(s < 3) return; + + std::vector p; + std::list concave; + Direction dir = getDirection(); + + for(size_t i = 0; i < s; i++) { + p.push_back((i+1)%s); + + if(isConcave(dir, at(i), at((i+1)%s), at((i+2)%s))) + concave.push_back((i+1)%s); + } + + for(size_t i = 0; i < p.size() && p.size() > 3; i++) { + size_t s2 = p.size(); + + const Vertex *v0 = &at(p[i]); + const Vertex *v1 = &at(p[(i+1)%s2]); + const Vertex *v2 = &at(p[(i+2)%s2]); + const Vertex *v3 = &at(p[(i+3)%s2]); + const Vertex *v4 = &at(p[(i+4)%s2]); + + if(isConcave(dir, *v1, *v2, *v3)) + continue; + + Triangle t(*v1, *v2, *v3); + + std::list::iterator it = concave.begin(); + for(; it != concave.end(); it++) { + if(*it != p[(i+1)%s2] && *it != p[(i+3)%s2] && t.contains(at(*it))) + break; + } + + if(it != concave.end()) + continue; + + triangles.push_back(t); + + if(isConcave(dir, *v2, *v3, *v4) && !isConcave(dir, *v1, *v3, *v4)) + concave.remove(p[(i+3)%s2]); + + if(isConcave(dir, *v0, *v1, *v2) && !isConcave(dir, *v0, *v1, *v3)) { + concave.remove(p[(i+1)%s2]); + } + + p.erase(p.begin()+(i+2)%s2); + i = 0; + } + + triangles.push_back(Triangle(at(p[0]), at(p[1]), at(p[2]))); +} + +void Polygon::triangulate(std::vector &triangles) const { + Polygon p; + + if(simplify(p)) p.doTriangulate(triangles); + else doTriangulate(triangles); +} diff --git a/Polygon.h b/Polygon.h index 093a160..6e36bee 100644 --- a/Polygon.h +++ b/Polygon.h @@ -3,17 +3,39 @@ #include "Vertex.h" #include "Line.h" +#include "Triangle.h" #include class Polygon : public std::vector { private: + struct Intersection { + size_t va1, va2, vb1, vb2; + Vertex v; + }; + + typedef Triangle::Direction Direction; + int quadrant(const Vertex &v) const; + + double signedArea() const; + + Triangle::Direction getDirection() const; + bool isConcave(const Triangle::Direction &dir, const Vertex &v1, const Vertex &v2, const Vertex &v3) const; + + bool intersections(std::vector *intersections = NULL) const; + + void doTriangulate(std::vector &triangles) const; public: double area() const; double perimeter() const; bool contains(const Vertex &v) const; bool intersects(const Line &l) const; + + bool isSimple() const; + bool simplify(Polygon &polygon) const; + + void triangulate(std::vector &triangles) const; }; #endif /*POLYGON_H_*/ diff --git a/Rectangle.h b/Rectangle.h index 8a61321..5e7bb94 100644 --- a/Rectangle.h +++ b/Rectangle.h @@ -18,13 +18,9 @@ class Rectangle { Vertex v1, v2; public: Rectangle() {} - Rectangle(const Vertex& v1, const Vertex& v2) { - this->v1 = v1; this->v2 = v2; - } - Rectangle(double x, double y, double width, double height) { - v1.setLocation(x, y); - v2.setLocation(x+width, y+height); - } + Rectangle(const Vertex& vertex1, const Vertex& vertex2) : v1(vertex1), v2(vertex2) {} + Rectangle(double x, double y, double width, double height) + : v1(x, y), v2(x+width, y+height) {} Vertex &getVertex1() {return v1;} const Vertex &getVertex1() const {return v1;} diff --git a/Triangle.cpp b/Triangle.cpp new file mode 100644 index 0000000..e367629 --- /dev/null +++ b/Triangle.cpp @@ -0,0 +1,36 @@ +#include "Triangle.h" +#include + + +Triangle::Direction Triangle::getDirection() const { + double c = (va.getX()-vb.getX())*(vc.getY()-vb.getY()) - (vc.getX()-vb.getX())*(va.getY()-vb.getY()); + + return (c < 0) ? CW : (c > 0) ? CCW : Unknown; +} + +double Triangle::area() const { + double a = vb.distanceSq(vc); + double b = vc.distanceSq(va); + double c = va.distanceSq(vb); + + return sqrt((a+b+c)*a+b+c - 2*(a*a+b*b+c*c))/4; +} + +double Triangle::perimeter() const { + return va.distance(vb) + vb.distance(vc) + vc.distance(va); +} + +bool Triangle::contains(const Vertex &v) const { + double a = (v.getX()-vb.getX())*(vc.getY()-vb.getY()) - (vc.getX()-vb.getX())*(v.getY()-vb.getY()); + double b = (v.getX()-vc.getX())*(va.getY()-vc.getY()) - (va.getX()-vc.getX())*(v.getY()-vc.getY()); + double c = (v.getX()-va.getX())*(vb.getY()-va.getY()) - (vb.getX()-va.getX())*(v.getY()-va.getY()); + + switch(getDirection()) { + case CW: + return ((a < 0) && (b < 0) && (c < 0)); + case CCW: + return ((a > 0) && (b > 0) && (c > 0)); + } + + return false; +} diff --git a/Triangle.h b/Triangle.h new file mode 100644 index 0000000..b0a7a2e --- /dev/null +++ b/Triangle.h @@ -0,0 +1,39 @@ +#ifndef TRIANGLE_H_ +#define TRIANGLE_H_ + + +#include "Vertex.h" + +class Triangle { + private: + Vertex va, vb, vc; + public: + enum Direction { + CW, CCW, Unknown + }; + + Triangle() {} + Triangle(const Vertex& vertexa, const Vertex& vertexb, const Vertex& vertexc) + : va(vertexa), vb(vertexb), vc(vertexc) {} + + Vertex &getVertexA() {return va;} + const Vertex &getVertexA() const {return va;} + void setVertexA(const Vertex &v) {va = v;} + + Vertex &getVertexB() {return vb;} + const Vertex &getVertexB() const {return vb;} + void setVertexB(const Vertex &v) {vb = v;} + + Vertex &getVertexC() {return vc;} + const Vertex &getVertexC() const {return vc;} + void setVertexC(const Vertex &v) {vc = v;} + + Direction getDirection() const; + + double area() const; + double perimeter() const; + + bool contains(const Vertex &v) const; +}; + +#endif /*TRIANGLE_H_*/ diff --git a/aclocal.m4 b/aclocal.m4 index 4353dd4..680d62e 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -213,6 +213,237 @@ main () rm -f conf.gtktest ]) +# Configure paths for GtkGLExt +# Naofumi Yasufuku +# +# Shamelessly stolen from gtk-2.0.m4 +# Configure paths for GTK+ +# Owen Taylor 1997-2001 + +dnl AM_PATH_GTKGLEXT_1_0([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]]) +dnl Test for GtkGLExt, and define GTKGLEXT_CFLAGS and GTKGLEXT_LIBS. +dnl +AC_DEFUN([AM_PATH_GTKGLEXT_1_0], +[ no_gtkglext="" + GTKGLEXT_CFLAGS="" + GTKGLEXT_LIBS="" + + # GtkGLExt pkg-config module + gtkglext_module=gtkglext-1.0 + + # minimum GtkGLExt version + gtkglext_min_version=ifelse([$1], ,1.0.0,$1) + + # minimum pkg-config version + pkgconfig_min_version=0.7 + +AC_ARG_ENABLE(gtkglext-test, +[ --disable-gtkglext-test do not try to compile and run a test GtkGLExt program], +, enable_gtkglext_test=yes) + +dnl +dnl Get the cflags and libraries from pkg-config +dnl + pkg_config_modules=$gtkglext_module + + AC_PATH_PROG(PKG_CONFIG, pkg-config, no) + + if test x$PKG_CONFIG != xno ; then + if pkg-config --atleast-pkgconfig-version $pkgconfig_min_version ; then + : + else + echo "" + echo "*** pkg-config too old; version $pkgconfig_min_version or better required." + no_gtkglext=yes + PKG_CONFIG=no + fi + else + no_gtkglext=yes + fi + + AC_MSG_CHECKING(for GtkGLExt - version >= $gtkglext_min_version) + + if test x$PKG_CONFIG != xno ; then + ## don't try to run the test against uninstalled libtool libs + if $PKG_CONFIG --uninstalled $pkg_config_modules; then + echo "" + echo "Will use uninstalled version of GtkGLExt found in PKG_CONFIG_PATH" + enable_gtkglext_test=no + fi + + if $PKG_CONFIG --atleast-version $gtkglext_min_version $pkg_config_modules; then + : + else + echo "" + echo "*** pkg-config cannot find $gtkglext_module >= $gtkglext_min_version" + echo "*** Set the environment variable PKG_CONFIG_PATH to point to the correct" + echo "*** configuration files." + no_gtkglext=yes + enable_gtkglext_test=no + fi + fi + + if test x"$no_gtkglext" = x ; then + GTKGLEXT_CFLAGS=`$PKG_CONFIG --cflags $pkg_config_modules` + GTKGLEXT_LIBS=`$PKG_CONFIG --libs $pkg_config_modules` + gtkglext_config_major_version=`$PKG_CONFIG --modversion $gtkglext_module | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` + gtkglext_config_minor_version=`$PKG_CONFIG --modversion $gtkglext_module | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` + gtkglext_config_micro_version=`$PKG_CONFIG --modversion $gtkglext_module | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` + if test "x$enable_gtkglext_test" = "xyes" ; then + ac_save_CFLAGS="$CFLAGS" + ac_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $GTKGLEXT_CFLAGS" + LIBS="$GTKGLEXT_LIBS $LIBS" +dnl +dnl Now check if the installed GtkGLExt is sufficiently new. (Also sanity +dnl checks the results of pkg-config to some extent) +dnl + rm -f conf.gtkgltest + AC_TRY_RUN([ +#include +#include +#include +#include + +int +main () +{ + int major, minor, micro; + char *tmp_version; + + system ("touch conf.gtkgltest"); + + /* HP/UX 9 (%@#!) writes to sscanf strings */ + tmp_version = g_strdup ("$gtkglext_min_version"); + if (sscanf (tmp_version, "%d.%d.%d", &major, &minor, µ) != 3) + { + printf ("%s, bad version string\n", "$gtkglext_min_version"); + exit (1); + } + + if ((gtkglext_major_version != $gtkglext_config_major_version) || + (gtkglext_minor_version != $gtkglext_config_minor_version) || + (gtkglext_micro_version != $gtkglext_config_micro_version)) + { + printf ("\n*** 'pkg-config --modversion $gtkglext_module' returned %d.%d.%d, but GtkGLExt\n", + $gtkglext_config_major_version, $gtkglext_config_minor_version, $gtkglext_config_micro_version); + printf ("*** library %d.%d.%d was found!\n", + gtkglext_major_version, gtkglext_minor_version, gtkglext_micro_version); + printf ("***\n"); + printf ("*** If pkg-config was correct, then it is best to remove the old version\n"); + printf ("*** of GtkGLExt. You may also be able to fix the error by modifying your\n"); + printf ("*** LD_LIBRARY_PATH enviroment variable, or by editing /etc/ld.so.conf.\n"); + printf ("*** Make sure you have run ldconfig if that is required on your system.\n"); + printf ("***\n"); + printf ("*** If pkg-config was wrong, set the environment variable PKG_CONFIG_PATH\n"); + printf ("*** to point to the correct configuration files.\n"); + } + else if ((gtkglext_major_version != GTKGLEXT_MAJOR_VERSION) || + (gtkglext_minor_version != GTKGLEXT_MINOR_VERSION) || + (gtkglext_micro_version != GTKGLEXT_MICRO_VERSION)) + { + printf ("\n*** GtkGLExt header files (version %d.%d.%d) do not match library (version %d.%d.%d).\n", + GTKGLEXT_MAJOR_VERSION, GTKGLEXT_MINOR_VERSION, GTKGLEXT_MICRO_VERSION, + gtkglext_major_version, gtkglext_minor_version, gtkglext_micro_version); + } + else + { + if ((gtkglext_major_version > major) || + ((gtkglext_major_version == major) && (gtkglext_minor_version > minor)) || + ((gtkglext_major_version == major) && (gtkglext_minor_version == minor) && (gtkglext_micro_version >= micro))) + { + return 0; + } + else + { + printf ("\n*** An old version of GtkGLExt library (%d.%d.%d) was found.\n", + gtkglext_major_version, gtkglext_minor_version, gtkglext_micro_version); + printf ("*** You need a version of GtkGLExt newer than %d.%d.%d. The latest version of\n", + major, minor, micro); + printf ("*** GtkGLExt is always available from http://gtkglext.sourceforge.net/.\n"); + printf ("***\n"); + printf ("*** If you have already installed a sufficiently new version, this error\n"); + printf ("*** probably means that the wrong copy of the pkg-config shell script is\n"); + printf ("*** being found. The easiest way to fix this is to remove the old version\n"); + printf ("*** of GtkGLExt, but you can also set the PKG_CONFIG environment to point\n"); + printf ("*** to the correct copy of pkg-config. (In this case, you will have to\n"); + printf ("*** modify your LD_LIBRARY_PATH enviroment variable, or edit /etc/ld.so.conf\n"); + printf ("*** so that the correct libraries are found at run-time)\n"); + } + } + return 1; +} +],, no_gtkglext=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"]) + CFLAGS="$ac_save_CFLAGS" + LIBS="$ac_save_LIBS" + fi + fi + if test "x$no_gtkglext" = x ; then + AC_MSG_RESULT(yes (version $gtkglext_config_major_version.$gtkglext_config_minor_version.$gtkglext_config_micro_version)) + ifelse([$2], , :, [$2]) + else + AC_MSG_RESULT(no) + if test "$PKG_CONFIG" = "no" ; then + echo "*** A new enough version of pkg-config was not found." + echo "*** See http://www.freedesktop.org/software/pkgconfig/." + elif test "x$enable_gtkglext_test" = "xyes" ; then + if test -f conf.gtkgltest ; then + : + else + echo "*** Could not run GtkGLExt test program, checking why..." + ac_save_CFLAGS="$CFLAGS" + ac_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $GTKGLEXT_CFLAGS" + LIBS="$LIBS $GTKGLEXT_LIBS" + AC_TRY_LINK([ +#include +#include +#include +], [ return ((gtkglext_major_version) || (gtkglext_minor_version) || (gtkglext_micro_version)); ], + [ echo "*** The test program compiled, but did not run. This usually means" + echo "*** that the run-time linker is not finding GtkGLExt or finding the wrong" + echo "*** version of GtkGLExt. If it is not finding GtkGLExt, you'll need to set your" + echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" + echo "*** to the installed location Also, make sure you have run ldconfig if that" + echo "*** is required on your system" + echo "***" + echo "*** If you have an old version installed, it is best to remove it, although" + echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH" ], + [ echo "*** The test program failed to compile or link. See the file config.log for the" + echo "*** exact error that occured. This usually means GtkGLExt is incorrectly installed."]) + CFLAGS="$ac_save_CFLAGS" + LIBS="$ac_save_LIBS" + fi + fi + GTKGLEXT_CFLAGS="" + GTKGLEXT_LIBS="" + ifelse([$3], , :, [$3]) + fi + AC_SUBST(GTKGLEXT_CFLAGS) + AC_SUBST(GTKGLEXT_LIBS) + rm -f conf.gtkgltest +]) + +dnl AC_GTKGLEXT_SUPPORTS_MULTIHEAD([ACTION-IF-SUPPORTED [, ACTION-IF-NOT-SUPPORTED]]) +dnl Checks whether GtkGLExt supports multihead. +dnl +AC_DEFUN([AC_GTKGLEXT_SUPPORTS_MULTIHEAD], +[ AC_CACHE_CHECK([whether GtkGLExt supports multihead], + [ac_cv_gtkglext_supports_multihead], + [AC_TRY_LINK([#include ], + [gdk_gl_query_extension_for_display(gdk_display_get_default());], + [ac_cv_gtkglext_supports_multihead=yes], + [ac_cv_gtkglext_supports_multihead=no])]) + if test "x$ac_cv_gtkglext_supports_multihead" = "xyes" ; then + ifelse([$1], , :, [$1]) + else + ifelse([$2], , :, [$2]) + fi +]) + # Copyright (C) 2002, 2003, 2005, 2006 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation diff --git a/configure b/configure index 53ed2f0..535b686 100755 --- a/configure +++ b/configure @@ -702,6 +702,8 @@ am__fastdepCC_FALSE PKG_CONFIG GTK_CFLAGS GTK_LIBS +GTKGLEXT_CFLAGS +GTKGLEXT_LIBS CPP GREP EGREP @@ -1300,6 +1302,7 @@ Optional Features: --disable-dependency-tracking speeds up one-time build --enable-dependency-tracking do not reject slow dependency extractors --disable-gtktest do not try to compile and run a test GTK+ program + --disable-gtkglext-test do not try to compile and run a test GtkGLExt program Some influential environment variables: CXX C++ compiler command @@ -4260,6 +4263,333 @@ echo "$as_me: error: zoomedit needs GTK+ 2.8.0" >&2;} rm -f conf.gtktest + no_gtkglext="" + GTKGLEXT_CFLAGS="" + GTKGLEXT_LIBS="" + + # GtkGLExt pkg-config module + gtkglext_module=gtkglext-1.0 + + # minimum GtkGLExt version + gtkglext_min_version=1.0.0 + + # minimum pkg-config version + pkgconfig_min_version=0.7 + +# Check whether --enable-gtkglext-test was given. +if test "${enable_gtkglext_test+set}" = set; then + enableval=$enable_gtkglext_test; +else + enable_gtkglext_test=yes +fi + + + pkg_config_modules=$gtkglext_module + + # Extract the first word of "pkg-config", so it can be a program name with args. +set dummy pkg-config; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_PKG_CONFIG+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + test -z "$ac_cv_path_PKG_CONFIG" && ac_cv_path_PKG_CONFIG="no" + ;; +esac +fi +PKG_CONFIG=$ac_cv_path_PKG_CONFIG +if test -n "$PKG_CONFIG"; then + { echo "$as_me:$LINENO: result: $PKG_CONFIG" >&5 +echo "${ECHO_T}$PKG_CONFIG" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + + if test x$PKG_CONFIG != xno ; then + if pkg-config --atleast-pkgconfig-version $pkgconfig_min_version ; then + : + else + echo "" + echo "*** pkg-config too old; version $pkgconfig_min_version or better required." + no_gtkglext=yes + PKG_CONFIG=no + fi + else + no_gtkglext=yes + fi + + { echo "$as_me:$LINENO: checking for GtkGLExt - version >= $gtkglext_min_version" >&5 +echo $ECHO_N "checking for GtkGLExt - version >= $gtkglext_min_version... $ECHO_C" >&6; } + + if test x$PKG_CONFIG != xno ; then + ## don't try to run the test against uninstalled libtool libs + if $PKG_CONFIG --uninstalled $pkg_config_modules; then + echo "" + echo "Will use uninstalled version of GtkGLExt found in PKG_CONFIG_PATH" + enable_gtkglext_test=no + fi + + if $PKG_CONFIG --atleast-version $gtkglext_min_version $pkg_config_modules; then + : + else + echo "" + echo "*** pkg-config cannot find $gtkglext_module >= $gtkglext_min_version" + echo "*** Set the environment variable PKG_CONFIG_PATH to point to the correct" + echo "*** configuration files." + no_gtkglext=yes + enable_gtkglext_test=no + fi + fi + + if test x"$no_gtkglext" = x ; then + GTKGLEXT_CFLAGS=`$PKG_CONFIG --cflags $pkg_config_modules` + GTKGLEXT_LIBS=`$PKG_CONFIG --libs $pkg_config_modules` + gtkglext_config_major_version=`$PKG_CONFIG --modversion $gtkglext_module | \ + sed 's/\([0-9]*\).\([0-9]*\).\([0-9]*\)/\1/'` + gtkglext_config_minor_version=`$PKG_CONFIG --modversion $gtkglext_module | \ + sed 's/\([0-9]*\).\([0-9]*\).\([0-9]*\)/\2/'` + gtkglext_config_micro_version=`$PKG_CONFIG --modversion $gtkglext_module | \ + sed 's/\([0-9]*\).\([0-9]*\).\([0-9]*\)/\3/'` + if test "x$enable_gtkglext_test" = "xyes" ; then + ac_save_CFLAGS="$CFLAGS" + ac_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $GTKGLEXT_CFLAGS" + LIBS="$GTKGLEXT_LIBS $LIBS" + rm -f conf.gtkgltest + if test "$cross_compiling" = yes; then + echo $ac_n "cross compiling; assumed OK... $ac_c" +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +#include +#include +#include +#include + +int +main () +{ + int major, minor, micro; + char *tmp_version; + + system ("touch conf.gtkgltest"); + + /* HP/UX 9 (%@#!) writes to sscanf strings */ + tmp_version = g_strdup ("$gtkglext_min_version"); + if (sscanf (tmp_version, "%d.%d.%d", &major, &minor, µ) != 3) + { + printf ("%s, bad version string\n", "$gtkglext_min_version"); + exit (1); + } + + if ((gtkglext_major_version != $gtkglext_config_major_version) || + (gtkglext_minor_version != $gtkglext_config_minor_version) || + (gtkglext_micro_version != $gtkglext_config_micro_version)) + { + printf ("\n*** 'pkg-config --modversion $gtkglext_module' returned %d.%d.%d, but GtkGLExt\n", + $gtkglext_config_major_version, $gtkglext_config_minor_version, $gtkglext_config_micro_version); + printf ("*** library %d.%d.%d was found!\n", + gtkglext_major_version, gtkglext_minor_version, gtkglext_micro_version); + printf ("***\n"); + printf ("*** If pkg-config was correct, then it is best to remove the old version\n"); + printf ("*** of GtkGLExt. You may also be able to fix the error by modifying your\n"); + printf ("*** LD_LIBRARY_PATH enviroment variable, or by editing /etc/ld.so.conf.\n"); + printf ("*** Make sure you have run ldconfig if that is required on your system.\n"); + printf ("***\n"); + printf ("*** If pkg-config was wrong, set the environment variable PKG_CONFIG_PATH\n"); + printf ("*** to point to the correct configuration files.\n"); + } + else if ((gtkglext_major_version != GTKGLEXT_MAJOR_VERSION) || + (gtkglext_minor_version != GTKGLEXT_MINOR_VERSION) || + (gtkglext_micro_version != GTKGLEXT_MICRO_VERSION)) + { + printf ("\n*** GtkGLExt header files (version %d.%d.%d) do not match library (version %d.%d.%d).\n", + GTKGLEXT_MAJOR_VERSION, GTKGLEXT_MINOR_VERSION, GTKGLEXT_MICRO_VERSION, + gtkglext_major_version, gtkglext_minor_version, gtkglext_micro_version); + } + else + { + if ((gtkglext_major_version > major) || + ((gtkglext_major_version == major) && (gtkglext_minor_version > minor)) || + ((gtkglext_major_version == major) && (gtkglext_minor_version == minor) && (gtkglext_micro_version >= micro))) + { + return 0; + } + else + { + printf ("\n*** An old version of GtkGLExt library (%d.%d.%d) was found.\n", + gtkglext_major_version, gtkglext_minor_version, gtkglext_micro_version); + printf ("*** You need a version of GtkGLExt newer than %d.%d.%d. The latest version of\n", + major, minor, micro); + printf ("*** GtkGLExt is always available from http://gtkglext.sourceforge.net/.\n"); + printf ("***\n"); + printf ("*** If you have already installed a sufficiently new version, this error\n"); + printf ("*** probably means that the wrong copy of the pkg-config shell script is\n"); + printf ("*** being found. The easiest way to fix this is to remove the old version\n"); + printf ("*** of GtkGLExt, but you can also set the PKG_CONFIG environment to point\n"); + printf ("*** to the correct copy of pkg-config. (In this case, you will have to\n"); + printf ("*** modify your LD_LIBRARY_PATH enviroment variable, or edit /etc/ld.so.conf\n"); + printf ("*** so that the correct libraries are found at run-time)\n"); + } + } + return 1; +} + +_ACEOF +rm -f conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +no_gtkglext=yes +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + + CFLAGS="$ac_save_CFLAGS" + LIBS="$ac_save_LIBS" + fi + fi + if test "x$no_gtkglext" = x ; then + { echo "$as_me:$LINENO: result: yes (version $gtkglext_config_major_version.$gtkglext_config_minor_version.$gtkglext_config_micro_version)" >&5 +echo "${ECHO_T}yes (version $gtkglext_config_major_version.$gtkglext_config_minor_version.$gtkglext_config_micro_version)" >&6; } + : + else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } + if test "$PKG_CONFIG" = "no" ; then + echo "*** A new enough version of pkg-config was not found." + echo "*** See http://www.freedesktop.org/software/pkgconfig/." + elif test "x$enable_gtkglext_test" = "xyes" ; then + if test -f conf.gtkgltest ; then + : + else + echo "*** Could not run GtkGLExt test program, checking why..." + ac_save_CFLAGS="$CFLAGS" + ac_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $GTKGLEXT_CFLAGS" + LIBS="$LIBS $GTKGLEXT_LIBS" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +#include +#include +#include + +int +main () +{ + return ((gtkglext_major_version) || (gtkglext_minor_version) || (gtkglext_micro_version)); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + echo "*** The test program compiled, but did not run. This usually means" + echo "*** that the run-time linker is not finding GtkGLExt or finding the wrong" + echo "*** version of GtkGLExt. If it is not finding GtkGLExt, you'll need to set your" + echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" + echo "*** to the installed location Also, make sure you have run ldconfig if that" + echo "*** is required on your system" + echo "***" + echo "*** If you have an old version installed, it is best to remove it, although" + echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + echo "*** The test program failed to compile or link. See the file config.log for the" + echo "*** exact error that occured. This usually means GtkGLExt is incorrectly installed." +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext + CFLAGS="$ac_save_CFLAGS" + LIBS="$ac_save_LIBS" + fi + fi + GTKGLEXT_CFLAGS="" + GTKGLEXT_LIBS="" + { { echo "$as_me:$LINENO: error: zoomedit needs GtkGLExt" >&5 +echo "$as_me: error: zoomedit needs GtkGLExt" >&2;} + { (exit 1); exit 1; }; } + fi + + + rm -f conf.gtkgltest + # Checks for header files. #AC_HEADER_STDC @@ -6123,6 +6453,8 @@ am__fastdepCC_FALSE!$am__fastdepCC_FALSE$ac_delim PKG_CONFIG!$PKG_CONFIG$ac_delim GTK_CFLAGS!$GTK_CFLAGS$ac_delim GTK_LIBS!$GTK_LIBS$ac_delim +GTKGLEXT_CFLAGS!$GTKGLEXT_CFLAGS$ac_delim +GTKGLEXT_LIBS!$GTKGLEXT_LIBS$ac_delim CPP!$CPP$ac_delim GREP!$GREP$ac_delim EGREP!$EGREP$ac_delim @@ -6130,7 +6462,7 @@ LIBOBJS!$LIBOBJS$ac_delim LTLIBOBJS!$LTLIBOBJS$ac_delim _ACEOF - if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 92; then + if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 94; then break elif $ac_last_try; then { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 diff --git a/configure.in b/configure.in index 1fd6e99..9b98a75 100644 --- a/configure.in +++ b/configure.in @@ -16,6 +16,7 @@ AM_PROG_CC_C_O # Checks for libraries. #AC_CHECK_LIB(m, [sqrt]) AM_PATH_GTK_2_0(2.8.0,,AC_MSG_ERROR(zoomedit needs GTK+ 2.8.0)) +AM_PATH_GTKGLEXT_1_0(1.0.0,,AC_MSG_ERROR(zoomedit needs GtkGLExt)) # Checks for header files. #AC_HEADER_STDC diff --git a/draw.cpp b/draw.cpp index ab21bd3..be67364 100644 --- a/draw.cpp +++ b/draw.cpp @@ -1,39 +1,39 @@ #include "draw.h" #include "edit.h" -#include "geometry.h" +#include "Rectangle.h" #include #include -#include -#include +#include +#include static double scale = 100.0; static double xTranslate = 0.0, yTranslate = 0.0; -static gboolean repaint = FALSE; -static void drawGrid(cairo_t *cr, const Rectangle *rect) { +static void drawGrid(const Rectangle &rect) { double depth = log10(scale)-0.75; double depth2 = floor(depth); double step = pow(0.1, depth2); double d; int i; - gchar *string; - double x1 = rect->getVertex1().getX(), y1 = rect->getVertex1().getY(); - double x2 = rect->getVertex2().getX(), y2 = rect->getVertex2().getY(); + //gchar *string; + double x1 = rect.getVertex1().getX(), y1 = rect.getVertex1().getY(); + double x2 = rect.getVertex2().getX(), y2 = rect.getVertex2().getY(); - cairo_set_font_size(cr, 10.0/scale); + glBegin(GL_LINES); + //cairo_set_font_size(cr, 10.0/scale); for(i = 0; 0.4*(depth-depth2+i-1) < 0.5; i++) { d = MIN(0.4*(depth-depth2+i), 0.5); - cairo_set_source_rgb(cr, d, d, d); + glColor3d(d, d, d); for(d = x1 - fmod(x1, step) - step; d <= x2; d+=step) { - cairo_move_to(cr, d, y1); - cairo_line_to(cr, d, y2); + glVertex2d(d, y1); + glVertex2d(d, y2); - if(step > 0.005) { + /*if(step > 0.005) { if(step > 0.5) string = g_strdup_printf("%i", (int)rint(d)); else @@ -43,14 +43,14 @@ static void drawGrid(cairo_t *cr, const Rectangle *rect) { cairo_show_text(cr, string); g_free(string); - } + }*/ } for(d = y1 - fmod(y1, step) - step; d <= y2; d+=step) { - cairo_move_to(cr, x1, d); - cairo_line_to(cr, x2, d); + glVertex2d(x1, d); + glVertex2d(x2, d); - if(step > 0.005) { + /*if(step > 0.005) { if(step > 0.5) string = g_strdup_printf("%i", (int)rint(d)); else @@ -60,48 +60,48 @@ static void drawGrid(cairo_t *cr, const Rectangle *rect) { cairo_show_text(cr, string); g_free(string); - } + }*/ } - cairo_stroke(cr); - step *= 10; } + + glEnd(); } -static void polygon2path(cairo_t *cr, const Polygon *polygon, const Rectangle *rect, gboolean close) { - Polygon polygon2; +static void fillPolygon(const Polygon &polygon) { + std::vector triangles; - // no vertices - if(polygon->empty()) return; + polygon.triangulate(triangles); - if(rect) - simplifyPolygon(polygon, rect, &polygon2); - else - polygon2 = *polygon; + glBegin(GL_TRIANGLES); - if(polygon2.empty()) return; + for(std::vector::iterator t = triangles.begin(); t != triangles.end(); t++) { + glVertex2d(t->getVertexA().getX(), t->getVertexA().getY()); + glVertex2d(t->getVertexB().getX(), t->getVertexB().getY()); + glVertex2d(t->getVertexC().getX(), t->getVertexC().getY()); + } - cairo_new_sub_path(cr); + glEnd(); +} + +static void drawPolygon(const Polygon &polygon, bool close) { + glBegin(GL_LINE_STRIP); - for(Polygon::iterator it = polygon2.begin(); it != polygon2.end(); it++) { - cairo_line_to(cr, it->getX(), it->getY()); - } + for(Polygon::const_iterator vertex = polygon.begin(); vertex != polygon.end(); vertex++) + glVertex2d(vertex->getX(), vertex->getY()); if(close) - cairo_close_path(cr); + glVertex2d(polygon.front().getX(), polygon.front().getY()); + + glEnd(); } gboolean drawTopView(GtkWidget *widget, GdkEventExpose *event, gpointer data) { - cairo_t *cr; - Vertex v1(-1, -1), v2(widget->allocation.width+1, widget->allocation.height+1); + GdkGLContext *context = gtk_widget_get_gl_context(widget); + GdkGLDrawable *drawable = gtk_widget_get_gl_drawable(widget); + Vertex v1(0, 0), v2(widget->allocation.width, widget->allocation.height); Rectangle rect; - gboolean vertexOk; - static GdkPixmap *pixmap = NULL; - static double lastImageWidth = 0.0, lastImageHeight = 0.0; - static gint lastWidth = 0, lastHeight = 0; - static int lastEditMode = 0; - int i; if(getLevel() == NULL) return FALSE; @@ -112,116 +112,79 @@ gboolean drawTopView(GtkWidget *widget, GdkEventExpose *event, gpointer data) { rect.setVertex1(v1); rect.setVertex2(v2); - if(pixmap == NULL || fabs(lastImageWidth - getImageWidth()) >= 0.000001 || fabs(lastImageHeight - getImageHeight()) >= 0.000001 || - lastWidth != widget->allocation.width || lastHeight != widget->allocation.height || lastEditMode != getEditMode() || repaint) - { - if(pixmap != NULL) - g_object_unref(G_OBJECT(pixmap)); - - pixmap = gdk_pixmap_new(widget->window, widget->allocation.width, widget->allocation.height, -1); - - lastImageWidth = getImageWidth(); - lastImageHeight = getImageHeight(); - lastWidth = widget->allocation.width; - lastHeight = widget->allocation.height; - lastEditMode = getEditMode(); - repaint = FALSE; - - - cr = gdk_cairo_create(GDK_DRAWABLE(pixmap)); - - cairo_translate(cr, getImageWidth()/2-xTranslate, getImageHeight()/2-yTranslate); - cairo_scale(cr, scale, scale); - - cairo_set_line_width(cr, 1.0/scale); - cairo_set_line_join(cr, CAIRO_LINE_JOIN_ROUND); + if(!gdk_gl_drawable_gl_begin(drawable, context)) + return FALSE; + + glClear(GL_COLOR_BUFFER_BIT); + + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + + glLineWidth(1.0); + + glTranslated(getImageWidth()/2-xTranslate, getImageHeight()/2-yTranslate, 0); + glScaled(scale, scale, 1); + + drawGrid(rect); + + for(Level::const_iterator room = getLevel()->begin(); room != getLevel()->end(); room++) { + if(&*room == getActiveRoom() && getEditMode() == EDIT_MODE_ADD) continue; - cairo_set_source_rgb(cr, 0, 0, 0); - cairo_paint(cr); + if(&*room == getActiveRoom()) + glColor4d(0.0, 0.7, 1.0, 0.2); + else + glColor4d(0.0, 0.7, 1.0, 0.3); - drawGrid(cr, &rect); + fillPolygon(*room); - for(Level::iterator room = getLevel()->begin(); room != getLevel()->end(); room++) { - if(&*room != getActiveRoom()) { - polygon2path(cr, &*room, &rect, TRUE); - } + if(&*room == getActiveRoom()) { + glColor4d(1.0, 1.0, 1.0, 0.9); + glLineWidth(2.0); } - - cairo_set_source_rgba(cr, 0.0, 0.7, 1.0, 0.3); - cairo_fill_preserve(cr); - - cairo_set_source_rgba(cr, 0.0, 0.7, 1.0, 0.7); - cairo_stroke(cr); - - if(getEditMode() == EDIT_MODE_SELECTED) { - polygon2path(cr, getActiveRoom(), &rect, TRUE); - - cairo_set_source_rgba(cr, 0.0, 0.7, 1.0, 0.2); - cairo_fill_preserve(cr); - - cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 0.9); - cairo_set_line_width(cr, 2.0/scale); - cairo_set_line_join(cr, CAIRO_LINE_JOIN_ROUND); - cairo_stroke(cr); + else if(&*room == getHoveredRoom() && getEditMode() != EDIT_MODE_ADD) { + glColor4d(0.0, 0.7, 1.0, 0.7); + glLineWidth(2.0); + } + else { + glColor4d(0.0, 0.7, 1.0, 0.7); + glLineWidth(1.0); } - cairo_destroy (cr); + drawPolygon(*room, true); } - gdk_draw_drawable(GDK_DRAWABLE(widget->window), widget->style->fg_gc[GTK_WIDGET_STATE(widget)], GDK_DRAWABLE(pixmap), 0, 0, 0, 0, -1, -1); - - cr = gdk_cairo_create(GDK_DRAWABLE(widget->window)); - - cairo_translate(cr, getImageWidth()/2-xTranslate, getImageHeight()/2-yTranslate); - cairo_scale(cr, scale, scale); - - cairo_set_line_width(cr, 2.0/scale); - cairo_set_line_join(cr, CAIRO_LINE_JOIN_MITER); - - if(getHoveredRoom() != NULL && getHoveredRoom() != getActiveRoom() && - (getEditMode() == EDIT_MODE_VIEW || getEditMode() == EDIT_MODE_SELECTED)) - { - polygon2path(cr, getHoveredRoom(), &rect, TRUE); - - cairo_set_source_rgba(cr, 0.0, 0.7, 1.0, 0.7); - cairo_stroke(cr); - } - else if(getEditMode() == EDIT_MODE_ADD) { - polygon2path(cr, getActiveRoom(), NULL, FALSE); - + if(getEditMode() == EDIT_MODE_ADD) { if(isPolygonOk(getActiveRoom())) - cairo_set_source_rgba(cr, 0.0, 0.7, 1.0, 0.2); + glColor4d(0.0, 0.7, 1.0, 0.2); else - cairo_set_source_rgba(cr, 1.0, 0.3, 0.3, 0.2); - cairo_fill_preserve(cr); + glColor4d(1.0, 0.3, 0.3, 0.2); + fillPolygon(*getActiveRoom()); + + glLineWidth(2.0); + glColor4d(0.0, 0.7, 1.0, 0.7); + drawPolygon(*getActiveRoom(), false); if(!getActiveRoom()->empty() && getHoveredVertex()) { - vertexOk = isVertexOk(getHoveredVertex()); + if(!isVertexOk(getHoveredVertex())) + glColor4d(1.0, 0.3, 0.3, 0.7); - if(vertexOk) - cairo_line_to(cr, getHoveredVertex()->getX(), getHoveredVertex()->getY()); - } - - cairo_set_line_width(cr, 2.0/scale); - cairo_set_line_join(cr, CAIRO_LINE_JOIN_ROUND); - cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND); - cairo_set_source_rgba(cr, 0.0, 0.7, 1.0, 0.7); - cairo_stroke(cr); - - if(!getActiveRoom()->empty() && getHoveredVertex() && !vertexOk) { - cairo_set_source_rgba(cr, 1.0, 0.3, 0.3, 0.7); + glBegin(GL_LINES); - cairo_move_to(cr, getActiveRoom()->back().getX(), getActiveRoom()->back().getY()); - cairo_line_to(cr, getHoveredVertex()->getX(), getHoveredVertex()->getY()); + glVertex2d(getActiveRoom()->back().getX(), getActiveRoom()->back().getY()); + glVertex2d(getHoveredVertex()->getX(), getHoveredVertex()->getY()); - cairo_stroke(cr); + glEnd(); } } - cairo_destroy (cr); + glPopMatrix(); + + gdk_gl_drawable_swap_buffers(drawable); + + gdk_gl_drawable_gl_end(drawable); - return FALSE; + return TRUE; } @@ -231,7 +194,6 @@ double getScale() { void setScale(double s) { scale = MAX(0.005, MIN(s, 10000)); - repaint = TRUE; } void imageToView(Vertex *v) { @@ -282,7 +244,6 @@ double getXTranslate() { void setXTranslate(double x) { xTranslate = x; - repaint = TRUE; } double getYTranslate() { @@ -291,9 +252,4 @@ double getYTranslate() { void setYTranslate(double y) { yTranslate = y; - repaint = TRUE; -} - -void redraw() { - repaint = TRUE; } diff --git a/draw.h b/draw.h index 0fcac61..3b6b974 100644 --- a/draw.h +++ b/draw.h @@ -2,7 +2,7 @@ #define DRAW_H_ #include -#include "geometry.h" +#include "Vertex.h" gboolean drawTopView(GtkWidget *widget, GdkEventExpose *event, gpointer data); @@ -21,6 +21,4 @@ void setXTranslate(double x); double getYTranslate(); void setYTranslate(double y); -void redraw(); - #endif /*DRAW_H_*/ diff --git a/edit.cpp b/edit.cpp index ab19969..3023dc5 100644 --- a/edit.cpp +++ b/edit.cpp @@ -1,6 +1,5 @@ #include "Level.h" #include "edit.h" -#include "geometry.h" static int editMode = EDIT_MODE_VIEW; @@ -145,6 +144,9 @@ bool isPolygonOk(Polygon *polygon) { if(polygon->size() == 1) return true; + if(!polygon->isSimple()) + return false; + for(Polygon::const_iterator it = polygon->begin(); it != polygon->end(); it++) { Polygon::const_iterator it2 = it+1; if(it2 == polygon->end()) it2 = polygon->begin(); @@ -156,21 +158,6 @@ bool isPolygonOk(Polygon *polygon) { if(room->intersects(l)) return false; } - - if(it2 != polygon->begin()) { - for(Polygon::const_iterator it3 = it2+1; it3 != polygon->end(); it3++) { - Polygon::const_iterator it4 = it3+1; - if(it4 == polygon->end()) it4 = polygon->begin(); - - if(it == polygon->begin() && it4 == polygon->begin()) continue; - - l2.setVertex1(*it3); - l2.setVertex2(*it4); - - if(l.intersects(l2, NULL) == INTERSECTION_SEGMENT_SEGMENT) - return false; - } - } } return true; diff --git a/edit.h b/edit.h index 460fb89..1216624 100644 --- a/edit.h +++ b/edit.h @@ -2,7 +2,6 @@ #define EDIT_H_ #include "Level.h" -#include "geometry.h" #define EDIT_MODE_VIEW 0 #define EDIT_MODE_SELECTED 1 diff --git a/geometry.cpp b/geometry.cpp deleted file mode 100644 index 0967119..0000000 --- a/geometry.cpp +++ /dev/null @@ -1,80 +0,0 @@ -#include "geometry.h" - - -static void edgeVertex(Vertex *v, int edge, const Rectangle *rect) { - if(edge == EDGE_NONE) - edge = rect->edges(*v); - - if(edge & EDGE_LEFT) v->setX(rect->getVertex1().getX()); - else if(edge & EDGE_RIGHT) v->setX(rect->getVertex2().getX()); - - if(edge & EDGE_TOP) v->setY(rect->getVertex1().getY()); - else if(edge & EDGE_BOTTOM) v->setY(rect->getVertex2().getY()); -} - -static int simplifyVertex(Vertex *v, const Vertex *to, const Rectangle *rect) { - Line l(*v, *to); - int edge, edge2; - - - edge = rect->edges(*v); - if(edge == EDGE_NONE) return EDGE_NONE; - - edge2 = rect->intersects(l, v, edge); - if(edge2 != EDGE_NONE) return edge2; - - edgeVertex(v, edge, rect); - return edge; -} - -static void addSimplifiedLine(const Vertex *v1, const Vertex *v2, const Rectangle *rect, int last, Polygon *out) { - const Line d1(rect->getVertex1(), rect->getVertex2()); - const Line d2(rect->getVertex1().getX(), rect->getVertex2().getY(), rect->getVertex2().getX(), rect->getVertex1().getY()); - - Line l(*v1, *v2); - Vertex v, vi; - int edge1, edge2; - - - v = *v1; - if((edge1 = simplifyVertex(&v, v2, rect)) != EDGE_NONE) - out->push_back(v); - - v = *v2; - edge2 = simplifyVertex(&v, v1, rect); - - if(edge1 != EDGE_NONE && edge2 != EDGE_NONE && !(edge1 & edge2)) { - if(l.intersects(d1, &vi) == INTERSECTION_SEGMENT_LINE) { - edgeVertex(&vi, 0, rect); - out->push_back(vi); - } - else if(l.intersects(d1, &vi) == INTERSECTION_SEGMENT_LINE) { - edgeVertex(&vi, 0, rect); - out->push_back(vi); - } - } - - if(!last) - out->push_back(v); -} - -void simplifyPolygon(const Polygon *in, const Rectangle *rect, Polygon *out) { - Vertex v; - - if(in->empty()) return; - else if(in->size() == 1) { - out->push_back(in->front()); - return; - } - - v = in->front(); - simplifyVertex(&v, &in->back(), rect); - out->push_back(v); - - for(Polygon::const_iterator v2 = in->begin(); v2 != in->end(); v2++) { - Polygon::const_iterator v3 = v2+1; - if(v3 == in->end()) v3 = in->begin(); - - addSimplifiedLine(&*v2, &*v3, rect, (v3 == in->begin()), out); - } -} diff --git a/geometry.h b/geometry.h deleted file mode 100644 index 633a5b4..0000000 --- a/geometry.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef GEOMETRY_H_ -#define GEOMETRY_H_ - - -#include "Polygon.h" -#include "Rectangle.h" - - -void simplifyPolygon(const Polygon *in, const Rectangle *rect, Polygon *out); - -#endif /*GEOMETRY_H_*/ diff --git a/window.cpp b/window.cpp index d347964..ff570ce 100644 --- a/window.cpp +++ b/window.cpp @@ -2,10 +2,9 @@ #include "ui.h" #include "edit.h" #include "draw.h" -#include "geometry.h" #include -#include -#include +#include +#include static GtkWidget *drawingArea = NULL, *sidebarView = NULL, *sidebarAdd = NULL; @@ -14,10 +13,111 @@ static GtkAdjustment *hAdjustment = NULL, *vAdjustment = NULL; static GtkWidget *entryName, *labelArea = NULL, *labelPerimeter = NULL, *buttonAdd = NULL, *buttonAddDo = NULL; +static void refreshScrolling() { + if(getImageWidth() < drawingArea->allocation.width) + setXTranslate((getImageWidth()-drawingArea->allocation.width)/2); + else + setXTranslate(gtk_adjustment_get_value(hAdjustment)); + + if(getImageHeight() < drawingArea->allocation.height) + setYTranslate((getImageHeight()-drawingArea->allocation.height)/2); + else + setYTranslate(gtk_adjustment_get_value(vAdjustment)); + + gtk_widget_queue_draw(drawingArea); +} + +static void updateScrollbars(double x, double y) { + const gdouble imageWidth = getImageWidth(), imageHeight = getImageHeight(); + const gdouble width = drawingArea->allocation.width, height = drawingArea->allocation.height; + gdouble upper, pageSize, value; + + gdk_window_freeze_updates(drawingArea->window); + + g_object_get(G_OBJECT(hAdjustment), "upper", &upper, "page_size", &pageSize, NULL); + g_object_set(G_OBJECT(hAdjustment), "upper", imageWidth, "page_size", width, NULL); + gtk_adjustment_changed(hAdjustment); + + if((pageSize > upper && width < imageWidth) || upper == 0) + value = (imageWidth-width)/2; + else + value = (gtk_adjustment_get_value(hAdjustment)+pageSize*x)/upper*imageWidth-width*x; + gtk_adjustment_set_value(hAdjustment, MAX(MIN(value, imageWidth-width), 0)); + + g_object_get(G_OBJECT(vAdjustment), "upper", &upper, "page_size", &pageSize, NULL); + g_object_set(G_OBJECT(vAdjustment), "upper", imageHeight, "page_size", height, NULL); + gtk_adjustment_changed(vAdjustment); + + if((pageSize > upper && height < imageHeight) || upper == 0) + value = (imageHeight-height)/2; + else + value = (gtk_adjustment_get_value(vAdjustment)+pageSize*y)/upper*imageHeight-height*y; + gtk_adjustment_set_value(vAdjustment, MAX(MIN(value, imageHeight-height), 0)); + + gdk_window_thaw_updates(drawingArea->window); + + refreshScrolling(); +} + static gboolean deleteEvent(GtkWidget *widget, GdkEvent *event, gpointer data) { return FALSE; } +static void realize(GtkWidget *widget, gpointer data) { + GdkGLContext *context = gtk_widget_get_gl_context(widget); + GdkGLDrawable *drawable = gtk_widget_get_gl_drawable(widget); + + if(!gdk_gl_drawable_gl_begin(drawable, context)) + return; + + glClearColor(0.0, 0.0, 0.0, 1.0); + + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + + glEnable(GL_LINE_SMOOTH); + + glViewport(0, 0, widget->allocation.width, widget->allocation.height); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + + if(widget->allocation.width != 0 && widget->allocation.height != 0) { + glTranslated(-1, 1, 0); + glScaled(2.0/widget->allocation.width, -2.0/widget->allocation.height, 1); + } + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + gdk_gl_drawable_gl_end(drawable); +} + +static gboolean configureEvent(GtkWidget *widget, GdkEventConfigure *event, gpointer data) { + GdkGLContext *context = gtk_widget_get_gl_context(widget); + GdkGLDrawable *drawable = gtk_widget_get_gl_drawable(widget); + + if(!gdk_gl_drawable_gl_begin(drawable, context)) + return FALSE; + + glViewport(0, 0, widget->allocation.width, widget->allocation.height); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + + if(widget->allocation.width != 0 && widget->allocation.height != 0) { + glTranslated(-1, 1, 0); + glScaled(2.0/widget->allocation.width, -2.0/widget->allocation.height, 1); + } + + gdk_gl_drawable_gl_end(drawable); + + updateScrollbars(0.5, 0.5); + + return TRUE; +} + + static gboolean scrollEvent(GtkWidget *widget, GdkEventScroll *event, gpointer user_data) { const gdouble x = event->x/widget->allocation.width, y = event->y/widget->allocation.height; @@ -44,8 +144,6 @@ static gboolean buttonEvent(GtkWidget *widget, GdkEventButton *event, gpointer u updateSidebar(); - redraw(); - break; case EDIT_MODE_ADD: viewToImage(&v); @@ -66,8 +164,6 @@ static gboolean buttonEvent(GtkWidget *widget, GdkEventButton *event, gpointer u gboolean crossingNotifyEvent(GtkWidget *widget, GdkEventCrossing *event, gpointer user_data) { Vertex v(event->x, event->y); - - switch(event->type) { case GDK_ENTER_NOTIFY: viewToImage(&v); @@ -99,56 +195,6 @@ static void destroy(GtkWidget *widget, gpointer data) { gtk_main_quit(); } -static void refreshScrolling() { - if(getImageWidth() < drawingArea->allocation.width) - setXTranslate((getImageWidth()-drawingArea->allocation.width)/2); - else - setXTranslate(gtk_adjustment_get_value(hAdjustment)); - - if(getImageHeight() < drawingArea->allocation.height) - setYTranslate((getImageHeight()-drawingArea->allocation.height)/2); - else - setYTranslate(gtk_adjustment_get_value(vAdjustment)); - - gtk_widget_queue_draw(drawingArea); -} - -static void updateScrollbars(double x, double y) { - const gdouble imageWidth = getImageWidth(), imageHeight = getImageHeight(); - const gdouble width = drawingArea->allocation.width, height = drawingArea->allocation.height; - gdouble upper, pageSize, value; - - gdk_window_freeze_updates(drawingArea->window); - - g_object_get(G_OBJECT(hAdjustment), "upper", &upper, "page_size", &pageSize, NULL); - g_object_set(G_OBJECT(hAdjustment), "upper", imageWidth, "page_size", width, NULL); - gtk_adjustment_changed(hAdjustment); - - if((pageSize > upper && width < imageWidth) || upper == 0) - value = (imageWidth-width)/2; - else - value = (gtk_adjustment_get_value(hAdjustment)+pageSize*x)/upper*imageWidth-width*x; - gtk_adjustment_set_value(hAdjustment, MAX(MIN(value, imageWidth-width), 0)); - - g_object_get(G_OBJECT(vAdjustment), "upper", &upper, "page_size", &pageSize, NULL); - g_object_set(G_OBJECT(vAdjustment), "upper", imageHeight, "page_size", height, NULL); - gtk_adjustment_changed(vAdjustment); - - if((pageSize > upper && height < imageHeight) || upper == 0) - value = (imageHeight-height)/2; - else - value = (gtk_adjustment_get_value(vAdjustment)+pageSize*y)/upper*imageHeight-height*y; - gtk_adjustment_set_value(vAdjustment, MAX(MIN(value, imageHeight-height), 0)); - - gdk_window_thaw_updates(drawingArea->window); - - refreshScrolling(); -} - -static void updateScrollbarsCentered() { - updateScrollbars(0.5, 0.5); -} - static void sidebarNameChanged(GtkEditable *editable, gpointer user_data) { if(getActiveRoom() == NULL) return; @@ -242,7 +288,7 @@ static GtkWidget* createSidebar() { return sidebar; } -GtkWidget* createMainWindow() { +GtkWidget* createMainWindow(GdkGLConfig *glconfig) { GtkWidget *window, *hPaned, *vbox, *table, *vScroll, *hScroll, *sidebar; GdkColor color = {0, 0, 0, 0}; @@ -267,8 +313,10 @@ GtkWidget* createMainWindow() { gtk_paned_pack1(GTK_PANED(hPaned), table, TRUE, TRUE); drawingArea = gtk_drawing_area_new(); - gtk_widget_modify_bg(drawingArea, (GtkStateType)GTK_WIDGET_STATE(drawingArea), &color); - g_signal_connect(G_OBJECT(drawingArea), "configure-event", G_CALLBACK(updateScrollbarsCentered), NULL); + gtk_widget_set_gl_capability(drawingArea, glconfig, NULL, TRUE, GDK_GL_RGBA_TYPE); + gtk_widget_set_double_buffered(drawingArea, FALSE); + g_signal_connect(G_OBJECT(drawingArea), "realize", G_CALLBACK(realize), NULL); + g_signal_connect(G_OBJECT(drawingArea), "configure-event", G_CALLBACK(configureEvent), NULL); g_signal_connect(G_OBJECT(drawingArea), "expose-event", G_CALLBACK(drawTopView), NULL); g_signal_connect(G_OBJECT(drawingArea), "button-press-event", G_CALLBACK(buttonEvent), NULL); g_signal_connect(G_OBJECT(drawingArea), "button-release-event", G_CALLBACK(buttonEvent), NULL); diff --git a/window.h b/window.h index 396c014..8e9265a 100644 --- a/window.h +++ b/window.h @@ -2,9 +2,10 @@ #define WINDOW_H_ #include +#include -GtkWidget* createMainWindow(); +GtkWidget* createMainWindow(GdkGLConfig *glconfig); void updateSidebar(); diff --git a/zoomedit.cpp b/zoomedit.cpp index 37b6159..580e224 100644 --- a/zoomedit.cpp +++ b/zoomedit.cpp @@ -1,4 +1,5 @@ #include +#include #include #include "Level.h" #include "window.h" @@ -6,13 +7,22 @@ int main(int argc, char *argv[]) { + GdkGLConfig *glconfig; GtkWidget *window; setLevel(new Level()); gtk_init(&argc, &argv); + gtk_gl_init(&argc, &argv); - window = createMainWindow(); + glconfig = gdk_gl_config_new_by_mode((GdkGLConfigMode)(GDK_GL_MODE_RGB | GDK_GL_MODE_DOUBLE)); + if(!glconfig) glconfig = gdk_gl_config_new_by_mode(GDK_GL_MODE_RGB); + if(!glconfig) { + g_print ("*** No appropriate OpenGL-capable visual found.\n"); + exit (1); + } + + window = createMainWindow(glconfig); gtk_widget_show(window); -- cgit v1.2.3