├── doc ├── Astar寻路算法.doc ├── Astar寻路算法-中文.doc ├── 平面多边形域的快速约束Delaunay三角化.pdf └── doc.txt ├── img ├── 20230113115226.png ├── 20230113203022.png ├── 20230113203058.png ├── 20230113203242.png ├── 20230113205512.png ├── 20240131153911.png ├── 20240131165800.png ├── 20240131165840.png ├── 20240131165915.png ├── 20240131165954.png ├── 20240131170422.png └── 20240214150332.png ├── libs ├── freeglut_mingw │ ├── Readme.txt │ ├── bin │ │ ├── freeglut.dll │ │ └── x64 │ │ │ └── freeglut.dll │ ├── include │ │ └── GL │ │ │ ├── glut.h │ │ │ ├── freeglut.h │ │ │ ├── freeglut_ext.h │ │ │ └── freeglut_std.h │ └── Copying.txt └── freeglut_msvc │ ├── Readme.txt │ ├── bin │ ├── freeglut.dll │ └── x64 │ │ └── freeglut.dll │ ├── lib │ ├── freeglut.lib │ └── x64 │ │ └── freeglut.lib │ ├── include │ └── GL │ │ ├── glut.h │ │ ├── freeglut.h │ │ ├── freeglut_ext.h │ │ └── freeglut_std.h │ └── Copying.txt ├── src ├── Point.cpp ├── Circle.h ├── Edge.h ├── Edge.cpp ├── Triangle.h ├── Circle.cpp ├── Point.h ├── Polygon.h ├── Triangle.cpp ├── navmesh.cpp └── Polygon.cpp ├── tools └── gen_map_tools │ ├── requirements.txt │ ├── README.md │ ├── pytest1.py │ ├── main.py │ ├── draw_obj.py │ ├── .gitignore │ ├── navmesh_test.py │ ├── parse_obj.py │ └── navmesh.py ├── .gitignore ├── CMakeLists.txt ├── Makefile ├── README.md └── LICENSE /doc/Astar寻路算法.doc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunxvming/navmesh/HEAD/doc/Astar寻路算法.doc -------------------------------------------------------------------------------- /doc/Astar寻路算法-中文.doc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunxvming/navmesh/HEAD/doc/Astar寻路算法-中文.doc -------------------------------------------------------------------------------- /img/20230113115226.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunxvming/navmesh/HEAD/img/20230113115226.png -------------------------------------------------------------------------------- /img/20230113203022.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunxvming/navmesh/HEAD/img/20230113203022.png -------------------------------------------------------------------------------- /img/20230113203058.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunxvming/navmesh/HEAD/img/20230113203058.png -------------------------------------------------------------------------------- /img/20230113203242.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunxvming/navmesh/HEAD/img/20230113203242.png -------------------------------------------------------------------------------- /img/20230113205512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunxvming/navmesh/HEAD/img/20230113205512.png -------------------------------------------------------------------------------- /img/20240131153911.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunxvming/navmesh/HEAD/img/20240131153911.png -------------------------------------------------------------------------------- /img/20240131165800.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunxvming/navmesh/HEAD/img/20240131165800.png -------------------------------------------------------------------------------- /img/20240131165840.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunxvming/navmesh/HEAD/img/20240131165840.png -------------------------------------------------------------------------------- /img/20240131165915.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunxvming/navmesh/HEAD/img/20240131165915.png -------------------------------------------------------------------------------- /img/20240131165954.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunxvming/navmesh/HEAD/img/20240131165954.png -------------------------------------------------------------------------------- /img/20240131170422.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunxvming/navmesh/HEAD/img/20240131170422.png -------------------------------------------------------------------------------- /img/20240214150332.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunxvming/navmesh/HEAD/img/20240214150332.png -------------------------------------------------------------------------------- /doc/平面多边形域的快速约束Delaunay三角化.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunxvming/navmesh/HEAD/doc/平面多边形域的快速约束Delaunay三角化.pdf -------------------------------------------------------------------------------- /libs/freeglut_mingw/Readme.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunxvming/navmesh/HEAD/libs/freeglut_mingw/Readme.txt -------------------------------------------------------------------------------- /libs/freeglut_msvc/Readme.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunxvming/navmesh/HEAD/libs/freeglut_msvc/Readme.txt -------------------------------------------------------------------------------- /libs/freeglut_msvc/bin/freeglut.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunxvming/navmesh/HEAD/libs/freeglut_msvc/bin/freeglut.dll -------------------------------------------------------------------------------- /libs/freeglut_msvc/lib/freeglut.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunxvming/navmesh/HEAD/libs/freeglut_msvc/lib/freeglut.lib -------------------------------------------------------------------------------- /libs/freeglut_mingw/bin/freeglut.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunxvming/navmesh/HEAD/libs/freeglut_mingw/bin/freeglut.dll -------------------------------------------------------------------------------- /src/Point.cpp: -------------------------------------------------------------------------------- 1 | #include "Point.h" 2 | 3 | Point::Point(double x, double y) 4 | { 5 | this->x = x; 6 | this->y = y; 7 | } 8 | -------------------------------------------------------------------------------- /tools/gen_map_tools/requirements.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunxvming/navmesh/HEAD/tools/gen_map_tools/requirements.txt -------------------------------------------------------------------------------- /libs/freeglut_mingw/bin/x64/freeglut.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunxvming/navmesh/HEAD/libs/freeglut_mingw/bin/x64/freeglut.dll -------------------------------------------------------------------------------- /libs/freeglut_msvc/bin/x64/freeglut.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunxvming/navmesh/HEAD/libs/freeglut_msvc/bin/x64/freeglut.dll -------------------------------------------------------------------------------- /libs/freeglut_msvc/lib/x64/freeglut.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunxvming/navmesh/HEAD/libs/freeglut_msvc/lib/x64/freeglut.lib -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | 34 | /build 35 | /bin 36 | .vscode 37 | -------------------------------------------------------------------------------- /src/Circle.h: -------------------------------------------------------------------------------- 1 | //==================================== 2 | // brief: Circle类,表示圆 3 | // author:sunxvming@163.com 4 | // date: 2019-11-15 5 | //==================================== 6 | 7 | #ifndef NAVMESH_CIRCLE_H 8 | #define NAVMESH_CIRCLE_H 9 | 10 | #include "Point.h" 11 | #include 12 | class Circle 13 | { 14 | private: 15 | Point center; 16 | double r; 17 | public: 18 | Circle(Point p1, Point p2, Point p3); 19 | Point GetCenter(); 20 | double GetR(); 21 | virtual ~Circle(); 22 | }; 23 | 24 | #endif // NAVMESH_CIRCLE_H 25 | -------------------------------------------------------------------------------- /src/Edge.h: -------------------------------------------------------------------------------- 1 | //==================================== 2 | // brief: Edge类,表示经过剖分后的线段,一条线段可能包含一个或两个三角,包含两个点 3 | // author:sunxvming@163.com 4 | // date: 2019-11-15 5 | //==================================== 6 | 7 | #ifndef NAVMESH_EDGE_H 8 | #define NAVMESH_EDGE_H 9 | 10 | namespace navmesh{ 11 | class Polygon; 12 | } 13 | 14 | class Edge 15 | { 16 | public: 17 | int triangles[2]; 18 | int points[2]; 19 | Edge(int t1, int t2, int p1, int p2); 20 | bool IsRestrain(navmesh::Polygon* p); 21 | virtual ~Edge(); 22 | }; 23 | 24 | #endif // NAVMESH_EDGE_H 25 | -------------------------------------------------------------------------------- /doc/doc.txt: -------------------------------------------------------------------------------- 1 | Step1. 建立单元大小为 E * E 的均匀网格,并将多边形域的顶点和边放入其中 2 | Step2. 取任意一条外边界边 p1p2. 3 | Step3. 计算DT点p3,构成约束 Delaunay三角形Δp1p2p3. 4 | Step4. 如果新生成的边 p1p3 不是约束边,若已经在栈中,则将其从中删除;否则,将其放入栈;类似地,可处理p3p2. 5 | Step5. 若栈不空,则从中取出一条边,转 Step3 ;否则,算法停止 6 | 7 | 8 | 计算一条边的DT点,包含两步:1.寻找初始可见点 2.确定 DT 点 . 9 | 1.寻找初始可见点 10 | 以 p1p2 的中点所在的网格单元为中心,按照螺旋式扩散的顺序搜索网格单元, 11 | 对其顶点链表中各节点作相对 p1p2 的可见性判断,直至找到一个可见点p,即为:初始可见点 12 | 13 | 2.确定 DT 点 14 | Step1. 构造Δp1p2p3 的外接圆及其网格包围盒 15 | Step2. 依次访问网格包围盒内的每个网格单元, 16 | 若某个网格单元中存在可见点 p 并且 ∠p1pp2 > ∠p1p3p2 ,则令 p3 = p ,转 Step1 ;否则,转 Step3. 17 | Step3. 若当前网格包围盒内所有网格单元都已被标记为当前趟数,也即 C(p1,p2,p3)内无可见点,则p3 为p1p2的 DT 点 18 | 19 | -------------------------------------------------------------------------------- /tools/gen_map_tools/README.md: -------------------------------------------------------------------------------- 1 | ## 依赖安装 2 | 此python转换工具依赖了pygame,使用前请先用一下命令进行依赖安装 3 | ``` 4 | pip install -r requirements.txt 5 | ``` 6 | 7 | ## 使用说明 8 | 把`.obj`模型文件转换成自定义的地图文件 9 | ``` 10 | python .\main.py -i .\map\map1.obj -o .\map\map1.txt 11 | ``` 12 | 13 | 14 | 用pygame把`.obj`模型文件的外轮廓和内轮廓画出来 15 | ``` 16 | python .\draw_obj.py -f .\map\map1.obj 17 | ``` 18 | 19 | 20 | ## 算法主要逻辑 21 | 1. 读取顶点和面信息。解析obj文件,读取其中的顶点(v:x y z)和三角形面(f:v1 v2 v3)数据 22 | 2. 找边界边。遍历所有三角的边的索引,找到所有没有被两个三角形给引用的边,用于找多边形边界,边界分外边界和内边界 23 | 3. 根据边界边找回环。从任意边界边出发,因为一个点可以对应两条边,故可以从一点出发转一圈回到出发点,便形成一个回环。其中访问过的边会被标记为已访问,之后不会再次访问。直到把所有的边界边全部访问完,即可获取到所有的回环。 24 | 4. 区分内边界和外边界。根据多边形的包含关系确定内外边界,若一个多边形包含其他所有多边形,则它就是外边界 25 | 5. 根据多边形结构生成寻路算法所需的地图文件 26 | -------------------------------------------------------------------------------- /src/Edge.cpp: -------------------------------------------------------------------------------- 1 | //==================================== 2 | // brief: Edge类,表示经过剖分后的线段,一条线段可能包含一个或两个三角,包含两个点 3 | // author:sunxvming@163.com 4 | // date: 2019-11-15 5 | //==================================== 6 | 7 | #include "Edge.h" 8 | #include "Polygon.h" 9 | 10 | 11 | Edge::Edge(int t1, int t2, int p1, int p2) 12 | { 13 | triangles[0] = t1; 14 | triangles[1] = t2; 15 | points[0] = p1; 16 | points[1] = p2; 17 | } 18 | 19 | bool Edge::IsRestrain(navmesh::Polygon* p) 20 | { 21 | int p1 = points[0]; 22 | int p2 = points[1]; 23 | int dp = p2 - p1; 24 | if (dp == 1 || dp == -1) return 1; 25 | if (p1 && p2) return 0; 26 | return std::size_t(p1 + p2) == p->points.size() - 1; 27 | } 28 | 29 | Edge::~Edge() 30 | { 31 | } 32 | -------------------------------------------------------------------------------- /src/Triangle.h: -------------------------------------------------------------------------------- 1 | //==================================== 2 | // brief: Triangle类,三角形的表示类 3 | // author:sunxvming@163.com 4 | // date: 2019-11-15 5 | //==================================== 6 | 7 | #ifndef NAVMESH_TRIANGLE_H 8 | #define NAVMESH_TRIANGLE_H 9 | 10 | #include "Point.h" 11 | 12 | namespace navmesh 13 | { 14 | class Polygon; 15 | } 16 | 17 | class Triangle 18 | { 19 | public: 20 | int p1; 21 | int p2; 22 | int p3; 23 | int edges[3]; 24 | Point icenter; // 重心 25 | Point lt; 26 | Point rb; 27 | bool isPath; 28 | 29 | public: 30 | Triangle(int p1, int p2, int p3); 31 | void GenExtData(navmesh::Polygon *p); 32 | int Contain(navmesh::Polygon *p, Point pt); 33 | virtual ~Triangle(); 34 | }; 35 | 36 | #endif // NAVMESH_TRIANGLE_H -------------------------------------------------------------------------------- /libs/freeglut_mingw/include/GL/glut.h: -------------------------------------------------------------------------------- 1 | #ifndef __GLUT_H__ 2 | #define __GLUT_H__ 3 | 4 | /* 5 | * glut.h 6 | * 7 | * The freeglut library include file 8 | * 9 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 10 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 11 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 12 | * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 13 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 14 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 15 | */ 16 | 17 | #include "freeglut_std.h" 18 | 19 | /*** END OF FILE ***/ 20 | 21 | #endif /* __GLUT_H__ */ 22 | -------------------------------------------------------------------------------- /libs/freeglut_msvc/include/GL/glut.h: -------------------------------------------------------------------------------- 1 | #ifndef __GLUT_H__ 2 | #define __GLUT_H__ 3 | 4 | /* 5 | * glut.h 6 | * 7 | * The freeglut library include file 8 | * 9 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 10 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 11 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 12 | * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 13 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 14 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 15 | */ 16 | 17 | #include "freeglut_std.h" 18 | 19 | /*** END OF FILE ***/ 20 | 21 | #endif /* __GLUT_H__ */ 22 | -------------------------------------------------------------------------------- /libs/freeglut_mingw/include/GL/freeglut.h: -------------------------------------------------------------------------------- 1 | #ifndef __FREEGLUT_H__ 2 | #define __FREEGLUT_H__ 3 | 4 | /* 5 | * freeglut.h 6 | * 7 | * The freeglut library include file 8 | * 9 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 10 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 11 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 12 | * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 13 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 14 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 15 | */ 16 | 17 | #include "freeglut_std.h" 18 | #include "freeglut_ext.h" 19 | 20 | /*** END OF FILE ***/ 21 | 22 | #endif /* __FREEGLUT_H__ */ 23 | -------------------------------------------------------------------------------- /libs/freeglut_msvc/include/GL/freeglut.h: -------------------------------------------------------------------------------- 1 | #ifndef __FREEGLUT_H__ 2 | #define __FREEGLUT_H__ 3 | 4 | /* 5 | * freeglut.h 6 | * 7 | * The freeglut library include file 8 | * 9 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 10 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 11 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 12 | * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 13 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 14 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 15 | */ 16 | 17 | #include "freeglut_std.h" 18 | #include "freeglut_ext.h" 19 | 20 | /*** END OF FILE ***/ 21 | 22 | #endif /* __FREEGLUT_H__ */ 23 | -------------------------------------------------------------------------------- /src/Circle.cpp: -------------------------------------------------------------------------------- 1 | //==================================== 2 | // brief: Circle类,表示圆 3 | // author:sunxvming@163.com 4 | // date: 2019-11-15 5 | //==================================== 6 | 7 | #include "Circle.h" 8 | 9 | Circle::Circle( Point p1, Point p2, Point p3) 10 | { 11 | double x1 = p1.x, y1 = p1.y; 12 | double x2 = p2.x, y2 = p2.y; 13 | double x3 = p3.x, y3 = p3.y; 14 | //求外接圆圆心 15 | double t1 = x1*x1 + y1*y1; 16 | double t2 = x2*x2 + y2*y2; 17 | double t3 = x3*x3 + y3*y3; 18 | double temp = x1*y2 + x2*y3 + x3*y1 - x1*y3 - x2*y1 - x3*y2; 19 | double cx = (t2*y3 + t1*y2 + t3*y1 - t2*y1 - t3*y2 - t1*y3) / temp / 2; 20 | double cy = (t3*x2 + t2*x1 + t1*x3 - t1*x2 - t2*x3 - t3*x1) / temp / 2; 21 | center.x = cx, center.y = cy; 22 | r = sqrt((cx -x1)*(cx -x1)+ (cy - y1)*(cy - y1)); 23 | } 24 | 25 | Point Circle::GetCenter() 26 | { 27 | return center; 28 | } 29 | 30 | double Circle::GetR() 31 | { 32 | return r; 33 | } 34 | 35 | 36 | Circle::~Circle() 37 | { 38 | } 39 | -------------------------------------------------------------------------------- /src/Point.h: -------------------------------------------------------------------------------- 1 | //==================================== 2 | // brief: Point类,点的表示类 3 | // author:sunxvming@163.com 4 | // date: 2019-11-15 5 | //==================================== 6 | 7 | #ifndef NAVMESH_POINT_H 8 | #define NAVMESH_POINT_H 9 | 10 | #include 11 | 12 | class Point 13 | { 14 | public: 15 | double x; 16 | double y; 17 | 18 | public: 19 | Point(double x, double y); 20 | Point() 21 | { 22 | this->x = 0; 23 | this->y = 0; 24 | } 25 | Point(const Point &p) 26 | { 27 | this->x = p.x; 28 | this->y = p.y; 29 | } 30 | double Dot(Point p) { return this->x * p.x + this->y * p.y; }; 31 | bool operator==(const Point p) { return x == p.x && y == p.y; }; // 这个地方就是用==,因为没有精度丢失 32 | Point operator-(const Point p) { return Point(this->x - p.x, this->y - p.y); }; 33 | std::string toString() { return "(" + std::to_string(x) + "," + std::to_string(y) + ")"; } 34 | bool inLeft(Point p) 35 | { 36 | return x * p.y - p.x * y > 0; 37 | } 38 | bool inRight(Point p) 39 | { 40 | return x * p.y - p.x * y < 0; 41 | } 42 | bool inSame(Point p) 43 | { 44 | return x * p.y - p.x * y == 0; 45 | } 46 | ~Point() = default; 47 | }; 48 | 49 | #endif // NAVMESH_POINT_H 50 | -------------------------------------------------------------------------------- /tools/gen_map_tools/pytest1.py: -------------------------------------------------------------------------------- 1 | import imp 2 | import pygame 3 | from math import pi 4 | import navmesh 5 | 6 | #初始化 7 | pygame.init() 8 | # 设置主屏幕大小 9 | size = (500, 450) 10 | screen = pygame.display.set_mode(size) 11 | #设置标题 12 | pygame.display.set_caption("pytest") 13 | # 设置一个控制主循环的变量 14 | done = False 15 | #创建时钟对象 16 | clock = pygame.time.Clock() 17 | 18 | vertices = [ 19 | [0,0,0], 20 | [300,0,0], 21 | [300,0,300], 22 | [0,0,300], 23 | [100,0,100], 24 | [200,0,100], 25 | [200,0,200], 26 | [100,0,200], 27 | ] 28 | indices = [ 29 | 1,5,6, 30 | 1,2,6, 31 | 2,6,7, 32 | 2,3,7, 33 | 3,7,8, 34 | 3,4,8, 35 | 4,8,5, 36 | 4,1,5, 37 | ] 38 | 39 | mesh = navmesh.NavMash(vertices, indices) 40 | 41 | pols = mesh.gen_navmesh() 42 | 43 | 44 | while not done: 45 | # 设置游戏的fps,每秒60帧 46 | clock.tick(60) 47 | for event in pygame.event.get(): 48 | if event.type == pygame.QUIT: 49 | done = True # 若检测到关闭窗口,则将done置为True 50 | 51 | for p in pols: 52 | pygame.draw.polygon(screen, (255, 0, 0), p.get_coord_list(), 2) 53 | for subp in p.sub_polygons: 54 | pygame.draw.polygon(screen, (0, 255, 0), subp.get_coord_list(), 2) 55 | 56 | pygame.display.flip() 57 | # 点击关闭,退出pygame程序 58 | pygame.quit() -------------------------------------------------------------------------------- /libs/freeglut_mingw/Copying.txt: -------------------------------------------------------------------------------- 1 | 2 | Freeglut Copyright 3 | ------------------ 4 | 5 | Freeglut code without an explicit copyright is covered by the following 6 | copyright: 7 | 8 | Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. 9 | Permission is hereby granted, free of charge, to any person obtaining a copy 10 | of this software and associated documentation files (the "Software"), to deal 11 | in the Software without restriction, including without limitation the rights 12 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | copies or substantial portions of the Software. 14 | 15 | The above copyright notice and this permission notice shall be included in 16 | all copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21 | PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 22 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | 25 | Except as contained in this notice, the name of Pawel W. Olszta shall not be 26 | used in advertising or otherwise to promote the sale, use or other dealings 27 | in this Software without prior written authorization from Pawel W. Olszta. 28 | -------------------------------------------------------------------------------- /libs/freeglut_msvc/Copying.txt: -------------------------------------------------------------------------------- 1 | 2 | Freeglut Copyright 3 | ------------------ 4 | 5 | Freeglut code without an explicit copyright is covered by the following 6 | copyright: 7 | 8 | Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. 9 | Permission is hereby granted, free of charge, to any person obtaining a copy 10 | of this software and associated documentation files (the "Software"), to deal 11 | in the Software without restriction, including without limitation the rights 12 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | copies or substantial portions of the Software. 14 | 15 | The above copyright notice and this permission notice shall be included in 16 | all copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21 | PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 22 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | 25 | Except as contained in this notice, the name of Pawel W. Olszta shall not be 26 | used in advertising or otherwise to promote the sale, use or other dealings 27 | in this Software without prior written authorization from Pawel W. Olszta. 28 | -------------------------------------------------------------------------------- /tools/gen_map_tools/main.py: -------------------------------------------------------------------------------- 1 | 2 | import getopt 3 | import sys 4 | import os 5 | 6 | 7 | import parse_obj 8 | import navmesh 9 | 10 | # ############################################################################# 11 | # Helpers 12 | # ############################################################################# 13 | def usage(): 14 | print("Usage: {} -i filename.obj -o filename.js".format(os.path.basename(sys.argv[0]))) 15 | 16 | 17 | 18 | 19 | def get_obj_info(infile): 20 | if not parse_obj.file_exists(infile): 21 | print("Couldn't find [%s]" % infile) 22 | return 23 | 24 | vertices, triangles, _, _, _,_,_ = parse_obj.parse_obj(infile) 25 | 26 | return vertices, triangles 27 | 28 | 29 | 30 | 31 | # ##################################################### 32 | # Main 33 | # ##################################################### 34 | if __name__ == "__main__": 35 | 36 | # get parameters from the command line 37 | try: 38 | opts, args = getopt.getopt(sys.argv[1:], "hi:o:", ["help", "input=", "output="]) 39 | 40 | except getopt.GetoptError: 41 | usage() 42 | sys.exit(2) 43 | 44 | infile = outfile = "" 45 | 46 | for o, a in opts: 47 | if o in ("-h", "--help"): 48 | usage() 49 | sys.exit() 50 | 51 | elif o in ("-i", "--input"): 52 | infile = a 53 | 54 | elif o in ("-o", "--output"): 55 | outfile = a 56 | 57 | if infile == "" or outfile == "": 58 | usage() 59 | sys.exit(2) 60 | 61 | vertices, triangles = get_obj_info(infile) 62 | mesh = navmesh.NavMash(vertices, triangles) 63 | mesh.gen_navmesh_file(outfile) 64 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0) 2 | 3 | project(navmesh) 4 | 5 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m64") 6 | 7 | # 定义工程根目录; CMAKE_SOURCE_DIR为内建变量,表示工程根目录的CMakeLists.txt文件路径 8 | SET(ROOT_DIR ${CMAKE_SOURCE_DIR}) 9 | 10 | # 定义freeglut库目录 11 | # 判断编译系统是MSVC还是MinGW 12 | if(MSVC) 13 | message("Using MSVC compiler") 14 | SET(GLUT_DIR ${ROOT_DIR}/libs/freeglut_msvc) 15 | elseif(MINGW) 16 | message("Using MinGW compiler") 17 | SET(GLUT_DIR ${ROOT_DIR}/libs/freeglut_mingw) 18 | else() 19 | message(FATAL_ERROR "Using an unknown compiler.") 20 | endif() 21 | 22 | # 解决vs SAFESEH报错 23 | # set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SAFESEH:NO /NODEFAULTLIB:glut32.lib") 24 | 25 | # 编译那些源码 26 | file(GLOB SOURCES "src/*.cpp") 27 | 28 | # 编译目标 29 | add_executable(${PROJECT_NAME} ${SOURCES}) 30 | 31 | # 包含路径 32 | target_include_directories(${PROJECT_NAME} 33 | PUBLIC 34 | ${ROOT_DIR}/libs/freeglut_msvc/include 35 | ) 36 | 37 | # 添加外部静态 38 | add_library(freeglut STATIC IMPORTED) 39 | 40 | if(MSVC) 41 | set_property(TARGET freeglut PROPERTY IMPORTED_LOCATION ${GLUT_DIR}/lib/x64/freeglut.lib) 42 | elseif(MINGW) 43 | set_property(TARGET freeglut PROPERTY IMPORTED_LOCATION ${GLUT_DIR}/lib/x64/libfreeglut.a) 44 | endif() 45 | 46 | target_link_libraries(${PROJECT_NAME} freeglut opengl32 glu32) # 添加freeglut.lib 47 | 48 | # 复制动态库到执行目录 49 | set(EXECUTABLE_OUTPUT_PATH ${ROOT_DIR}/bin) 50 | 51 | if(MSVC) 52 | file(COPY ${GLUT_DIR}/bin/x64/freeglut.dll 53 | DESTINATION ${EXECUTABLE_OUTPUT_PATH}/Release) 54 | file(COPY ${GLUT_DIR}/bin/x64/freeglut.dll 55 | DESTINATION ${EXECUTABLE_OUTPUT_PATH}/Debug) 56 | elseif(MINGW) 57 | file(COPY ${GLUT_DIR}/bin/x64/freeglut.dll 58 | DESTINATION ${EXECUTABLE_OUTPUT_PATH}) 59 | endif() 60 | -------------------------------------------------------------------------------- /src/Polygon.h: -------------------------------------------------------------------------------- 1 | //==================================== 2 | // brief: Polygon类,代表寻路多边形的类,主要实现多边形的三角剖分和寻路 3 | // author:sunxvming@163.com 4 | // date: 2019-11-15 5 | //==================================== 6 | 7 | #ifndef NAVMESH_POLYGON_H 8 | #define NAVMESH_POLYGON_H 9 | 10 | #include 11 | #include 12 | #include "Point.h" 13 | #include "Triangle.h" 14 | #include "Edge.h" 15 | #include "Circle.h" 16 | 17 | using namespace std; 18 | 19 | typedef unordered_map Hash; 20 | #define MAXPOINT 100000 21 | #define PIndex(p1, p2) (p1 > p2 ? (p2 * MAXPOINT + p1) : (p1 * MAXPOINT + p2)) 22 | 23 | class Cell 24 | { 25 | public: 26 | vector points; 27 | vector edges; 28 | }; 29 | 30 | class Grid 31 | { 32 | public: 33 | vector cells; 34 | int gride_len; // grid length 35 | double minx; 36 | double miny; 37 | double maxx; 38 | double maxy; 39 | int xnum; 40 | int ynum; 41 | }; 42 | 43 | class Line 44 | { 45 | public: 46 | Point p1; 47 | Point p2; 48 | float color[3]; 49 | }; 50 | 51 | namespace navmesh 52 | { 53 | 54 | class Polygon 55 | { 56 | public: 57 | vector points; 58 | vector triangles; 59 | vector edges; // 三角剖分后的所有的三角形的边 60 | Grid grid; 61 | 62 | private: 63 | inline void CreateTriangle(Hash *eindex, int p1, int p2, int p3); 64 | inline int CreateEdge(Hash *eindexs, int triangle, int p1, int p2); 65 | inline int FindDT(Grid *grid, int p1, int p2); 66 | // Polygon的三角剖分 67 | void Delaunay(); 68 | // 生成额外的数据 69 | void GenExtData(); 70 | 71 | public: 72 | Point GetPoint(int p); 73 | bool IsIntersect(Grid *grid, int edgepos, int pa1, int p1); 74 | bool JudgeIsVisible(int pa1, int p1, Grid *grid); 75 | Polygon(double pos[], int size); 76 | vector GetLines(); 77 | vector GetGrideLines(); 78 | vector GetCenters(); 79 | int IsFrist(int p) { return p == 4; } 80 | int FindTriangle(Point p); 81 | vector FindPath(Point from, Point to); 82 | Polygon() = default; 83 | }; 84 | 85 | } 86 | #endif // NAVMESH_POLYGON_H -------------------------------------------------------------------------------- /tools/gen_map_tools/draw_obj.py: -------------------------------------------------------------------------------- 1 | 2 | import pygame 3 | import getopt 4 | import sys 5 | import os 6 | from math import pi 7 | import main 8 | import navmesh 9 | 10 | SCREEN_WIDTH = 1200 11 | SCREEN_HEIGHT = 800 12 | 13 | def usage(): 14 | print("Usage: {} -f filename.obj".format(os.path.basename(sys.argv[0]))) 15 | 16 | 17 | try: 18 | opts, args = getopt.getopt(sys.argv[1:], "hf:", ["help", "file="]) 19 | 20 | except getopt.GetoptError: 21 | usage() 22 | sys.exit(2) 23 | 24 | infile = "" 25 | 26 | for o, a in opts: 27 | if o in ("-h", "--help"): 28 | usage() 29 | sys.exit() 30 | 31 | elif o in ("-f", "--file"): 32 | infile = a 33 | 34 | #初始化 35 | pygame.init() 36 | # 设置主屏幕大小 37 | size = (SCREEN_WIDTH, SCREEN_HEIGHT) 38 | screen = pygame.display.set_mode(size) 39 | #设置标题 40 | pygame.display.set_caption("test") 41 | # 设置一个控制主循环的变量 42 | done = False 43 | #创建时钟对象 44 | clock = pygame.time.Clock() 45 | 46 | vertices, triangles = main.get_obj_info(infile) 47 | nav = navmesh.NavMash(vertices, triangles) 48 | pols = nav.gen_navmesh() 49 | 50 | while not done: 51 | # 设置游戏的fps,每秒60帧 52 | clock.tick(60) 53 | for event in pygame.event.get(): 54 | if event.type == pygame.QUIT: 55 | done = True # 若检测到关闭窗口,则将done置为True 56 | 57 | 58 | minx = pols[0].lt.x 59 | miny = pols[0].lt.y 60 | maxx = pols[0].rb.x 61 | maxy = pols[0].rb.y 62 | 63 | dx = maxx - minx 64 | dy = maxy - miny 65 | timex = SCREEN_WIDTH / dx / 1.1 66 | timey = SCREEN_HEIGHT / dy / 1.1 67 | 68 | 69 | for p in pols: 70 | tmp = p.get_coord_list() 71 | points = [[timex * (p[0] - minx), timey * (p[1] - miny)] for p in tmp] #实际坐标转换为屏幕坐标 72 | pygame.draw.polygon(screen, (255, 0, 0), points, 2) 73 | for subp in p.sub_polygons: 74 | tmp = subp.get_coord_list() 75 | points = [[timex * (p[0] - minx), timey * (p[1] - miny)] for p in tmp] 76 | pygame.draw.polygon(screen, (0, 255, 0), points, 2) 77 | 78 | pygame.display.flip() 79 | # 点击关闭,退出pygame程序 80 | pygame.quit() -------------------------------------------------------------------------------- /src/Triangle.cpp: -------------------------------------------------------------------------------- 1 | //==================================== 2 | // brief: Triangle类,三角形的表示类 3 | // author:sunxvming@163.com 4 | // date: 2019-11-15 5 | //==================================== 6 | 7 | #include "Triangle.h" 8 | #include "Polygon.h" 9 | 10 | Triangle::Triangle(int p1, int p2, int p3) : p1(p1), p2(p2), p3(p3), edges{-1, -1, -1}, isPath(false) 11 | { 12 | } 13 | 14 | #define max(a, b) ((a) > (b) ? (a) : (b)) 15 | #define min(a, b) ((a) > (b) ? (b) : (a)) 16 | void Triangle::GenExtData(navmesh::Polygon *p) 17 | { 18 | Point pt1 = p->GetPoint(p1); 19 | Point pt2 = p->GetPoint(p2); 20 | Point pt3 = p->GetPoint(p3); 21 | 22 | icenter.x = (pt1.x + pt2.x + pt3.x) / 3; 23 | icenter.y = (pt1.y + pt2.y + pt3.y) / 3; 24 | 25 | double maxx = max(pt1.x, pt2.x); 26 | double maxy = max(pt1.y, pt2.y); 27 | double minx = min(pt1.x, pt2.x); 28 | double miny = min(pt1.y, pt2.y); 29 | 30 | if (pt3.x > maxx) 31 | maxx = pt3.x; 32 | if (pt3.y > maxy) 33 | maxy = pt3.y; 34 | if (pt3.x < minx) 35 | minx = pt3.x; 36 | if (pt3.y < miny) 37 | miny = pt3.y; 38 | 39 | lt.x = minx, lt.y = miny; 40 | rb.x = maxx, rb.y = maxy; 41 | } 42 | 43 | int Triangle::Contain(navmesh::Polygon *p, Point pt) 44 | { 45 | double x = pt.x, y = pt.y; 46 | // 快速排查 47 | if (x < lt.x) 48 | return 0; 49 | if (x > rb.x) 50 | return 0; 51 | if (y < lt.y) 52 | return 0; 53 | if (y > rb.y) 54 | return 0; 55 | 56 | Point pt1 = p->GetPoint(p1); 57 | Point pt2 = p->GetPoint(p2); 58 | Point pt3 = p->GetPoint(p3); 59 | 60 | Point v0 = pt3 - pt1; 61 | Point v1 = pt2 - pt1; 62 | Point v2 = pt - pt1; 63 | 64 | // P = A + u * (C – A) + v * (B - A) 满足 u + v <=1 u >= 0 v >= 0 65 | double dot00 = v0.Dot(v0); 66 | double dot01 = v0.Dot(v1); 67 | double dot02 = v0.Dot(v2); 68 | double dot11 = v1.Dot(v1); 69 | double dot12 = v1.Dot(v2); 70 | double inverDeno = 1 / (dot00 * dot11 - dot01 * dot01); 71 | double u = (dot11 * dot02 - dot01 * dot12) * inverDeno; 72 | if (u < 0 || u > 1) // if u out of range, return directly 73 | { 74 | return 0; 75 | } 76 | 77 | double v = (dot00 * dot12 - dot01 * dot02) * inverDeno; 78 | if (v < 0 || v > 1) // if v out of range, return directly 79 | { 80 | return 0; 81 | } 82 | 83 | return u + v <= 1 ? 1 : 0; 84 | } 85 | 86 | Triangle::~Triangle() 87 | { 88 | } 89 | -------------------------------------------------------------------------------- /tools/gen_map_tools/.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | pip-wheel-metadata/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | *.py,cover 51 | .hypothesis/ 52 | .pytest_cache/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | target/ 76 | 77 | # Jupyter Notebook 78 | .ipynb_checkpoints 79 | 80 | # IPython 81 | profile_default/ 82 | ipython_config.py 83 | 84 | # pyenv 85 | .python-version 86 | 87 | # pipenv 88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 91 | # install all needed dependencies. 92 | #Pipfile.lock 93 | 94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 95 | __pypackages__/ 96 | 97 | # Celery stuff 98 | celerybeat-schedule 99 | celerybeat.pid 100 | 101 | # SageMath parsed files 102 | *.sage.py 103 | 104 | # Environments 105 | .env 106 | .venv 107 | env/ 108 | venv/ 109 | ENV/ 110 | env.bak/ 111 | venv.bak/ 112 | 113 | # Spyder project settings 114 | .spyderproject 115 | .spyproject 116 | 117 | # Rope project settings 118 | .ropeproject 119 | 120 | # mkdocs documentation 121 | /site 122 | 123 | # mypy 124 | .mypy_cache/ 125 | .dmypy.json 126 | dmypy.json 127 | 128 | # Pyre type checker 129 | .pyre/ 130 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | TARGET = navmesh 2 | OBJ_PATH = bin 3 | PREFIX_BIN = 4 | 5 | 6 | CC = gcc 7 | CPP = g++ -std=c++17 8 | INCLUDES += -I./ -I./libs/freeglut_mingw/include 9 | 10 | 11 | LIB_DIRS = -lfreeglut -lopengl32 -lglu32 -L".\libs\freeglut_mingw\lib\x64" 12 | 13 | G = -g 14 | CFLAGS :=-Wall -Wno-unknown-pragmas $(G) 15 | LINKFLAGS = 16 | 17 | 18 | SRCDIR =./src 19 | 20 | C_SRCDIR = $(SRCDIR) 21 | C_SOURCES = $(foreach d,$(C_SRCDIR),$(wildcard $(d)/*.c) ) 22 | C_OBJS = $(patsubst %.c, $(OBJ_PATH)/%.o, $(C_SOURCES)) 23 | C_DEPEND = $(patsubst %.c, $(OBJ_PATH)/%.d, $(C_SOURCES)) 24 | 25 | 26 | CC_SRCDIR = $(SRCDIR) 27 | CC_SOURCES = $(foreach d,$(CC_SRCDIR),$(wildcard $(d)/*.cc) ) 28 | CC_OBJS = $(patsubst %.cc, $(OBJ_PATH)/%.o, $(CC_SOURCES)) 29 | CC_DEPEND = $(patsubst %.cc, $(OBJ_PATH)/%.d, $(CC_SOURCES)) 30 | 31 | 32 | CPP_SRCDIR = $(SRCDIR) 33 | CPP_SOURCES = $(foreach d,$(CPP_SRCDIR),$(wildcard $(d)/*.cpp) ) 34 | CPP_OBJS = $(patsubst %.cpp, $(OBJ_PATH)/%.o, $(CPP_SOURCES)) 35 | CPP_DEPEND = $(patsubst %.cpp, $(OBJ_PATH)/%.d, $(CPP_SOURCES)) 36 | 37 | 38 | default: compile 39 | 40 | init: 41 | $(foreach d,$(SRCDIR), mkdir -p $(OBJ_PATH)/$(d);) 42 | 43 | 44 | 45 | $(C_OBJS):$(OBJ_PATH)/%.o:%.c 46 | $(CC) -c $(CFLAGS) $(INCLUDES) $< -o $@ 47 | 48 | $(CC_OBJS):$(OBJ_PATH)/%.o:%.cc 49 | $(CPP) -c $(CFLAGS) $(INCLUDES) $< -o $@ 50 | 51 | $(CPP_OBJS):$(OBJ_PATH)/%.o:%.cpp 52 | $(CPP) -c $(CFLAGS) $(INCLUDES) $< -o $@ 53 | 54 | 55 | test: 56 | @echo "C_SOURCES: $(C_SOURCES)" 57 | @echo "C_OBJS: $(C_OBJS)" 58 | @echo "CPP_SOURCES: $(CPP_SOURCES)" 59 | @echo "CPP_OBJS: $(CPP_OBJS)" 60 | @echo "CC_SOURCES: $(CC_SOURCES)" 61 | @echo "CC_OBJS: $(CC_OBJS)" 62 | 63 | compile:$(C_OBJS) $(CC_OBJS) $(CPP_OBJS) 64 | $(CPP) $^ -o bin/$(TARGET) $(LINKFLAGS) ${LIB_DIRS} 65 | cp .\libs\freeglut_mingw\bin\x64\freeglut.dll ./bin/freeglut.dll 66 | clean: 67 | rm -rf $(OBJ_PATH) 68 | cleand: 69 | find ./bin -name *.d | xargs rm -rf 70 | 71 | 72 | cleanall:subdirs_clean 73 | rm -rf $(OBJ_PATH) 74 | rm -f $(TARGET) 75 | 76 | install: $(TARGET) 77 | cp $(TARGET) $(PREFIX_BIN) 78 | 79 | uninstall: 80 | rm -f $(PREFIX_BIN)/$(TARGET) 81 | 82 | rebuild: clean init compile 83 | 84 | ifeq ($(MAKECMDGOALS),) 85 | include $(CPP_DEPEND) init 86 | endif 87 | 88 | # $* 不带后缀的target 89 | # $< target 90 | # $@ depend 91 | # $$xx 变量要用两个$$表示 92 | # $$$$ 进程号 93 | # sed中的变量用 '"包围, 's,\('"$$BASESRC"'\)\.o[ :]*,\bin\/$*.o $@ : ,g' 94 | $(CPP_DEPEND):$(OBJ_PATH)/%.d:%.cpp 95 | @BASESRC=`basename $*`;\ 96 | set -e; rm -f $@; \ 97 | $(CPP) $(INCLUDES) -MM $(CPPFLAGS) $< > $@.$$$$; \ 98 | sed 's,\('"$$BASESRC"'\)\.o[ :]*,\bin\/$*.o $@ : ,g' < $@.$$$$ > $@; \ 99 | rm -f $@.$$$$ 100 | 101 | -------------------------------------------------------------------------------- /src/navmesh.cpp: -------------------------------------------------------------------------------- 1 | //==================================== 2 | // brief: 程序的main入口文件,调用glut库来画经过三角剖分后的多边形网格和寻路的路径 3 | // author:sunxvming@163.com 4 | // date: 2019-11-16 5 | //==================================== 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "Polygon.h" 12 | 13 | int fromx = -1; 14 | int fromy = -1; 15 | int tox = -1; 16 | int toy = -1; 17 | int clicknum = 0; 18 | double pos[] = {50, 50, 275, 100, 425, 60, 450, 160, 350, 230, 600, 325, 750, 200, 750, 500, 525, 460, 575, 550, 425, 550, 480, 450, 325, 425, 300, 300, 30, 400, 85, 275}; 19 | // double pos[] = {0, 126, 119, 118, 158, 0, 200, 122, 317, 120, 224, 201, 260, 317, 163, 245, 65, 316, 99, 196}; 20 | // double pos[] = {150, 100, 300, 100, 350, 150, 400, 100, 550, 100, 600, 150, 450, 450, 200, 500, 200, 350, 50, 250}; 21 | // double pos[] = {50, 150,150,100,200,100,250,200, 300, 150,250,250,200,250,150,200,150,150,50,250}; 22 | std::shared_ptr polygon = make_shared(pos, sizeof(pos) / sizeof(double)); 23 | vector ways; 24 | 25 | static void DrawMap() 26 | { 27 | // (0,0)is in the upper left corner 28 | 29 | glLineWidth(2); 30 | glBegin(GL_LINES); 31 | 32 | // draw grid lines 33 | vector gridelines = polygon->GetGrideLines(); 34 | for (unsigned i = 0; i < gridelines.size(); i++) 35 | { 36 | Line grideline = gridelines[i]; 37 | glColor3fv(grideline.color); 38 | glVertex2f((GLfloat)grideline.p1.x, (GLfloat)grideline.p1.y); 39 | glVertex2f((GLfloat)grideline.p2.x, (GLfloat)grideline.p2.y); 40 | } 41 | glEnd(); 42 | 43 | // draw triangle that path has been found 44 | for (const auto &tri : polygon->triangles) 45 | { 46 | 47 | if (tri.isPath && ways.size() > 0) 48 | { 49 | glBegin(GL_TRIANGLES); 50 | glColor3f(0.5f, 0.5f, 0.5f); 51 | glVertex2f((GLfloat)polygon->points[tri.p1].x, (GLfloat)polygon->points[tri.p1].y); 52 | glVertex2f((GLfloat)polygon->points[tri.p2].x, (GLfloat)polygon->points[tri.p2].y); 53 | glVertex2f((GLfloat)polygon->points[tri.p3].x, (GLfloat)polygon->points[tri.p3].y); 54 | glEnd(); 55 | } 56 | } 57 | 58 | glBegin(GL_LINES); 59 | // draw polygon lines 60 | vector lines = polygon->GetLines(); 61 | for (unsigned i = 0; i < lines.size(); i++) 62 | { 63 | Line line = lines[i]; 64 | glColor3fv(line.color); 65 | glVertex2f((GLfloat)line.p1.x, (GLfloat)line.p1.y); 66 | glVertex2f((GLfloat)line.p2.x, (GLfloat)line.p2.y); 67 | } 68 | 69 | // draw path lines 70 | for (unsigned i = 1; i < ways.size(); i++) 71 | { 72 | glColor3f(0.0f, 0.0, 1.0); 73 | glVertex2f((GLfloat)ways[i - 1].x, (GLfloat)ways[i - 1].y); 74 | glVertex2f((GLfloat)ways[i].x, (GLfloat)ways[i].y); 75 | } 76 | glEnd(); 77 | 78 | // draw triangle centers 79 | glPointSize(3); 80 | glBegin(GL_POINTS); 81 | auto centers = polygon->GetCenters(); 82 | for (unsigned i = 0; i < centers.size(); i++) 83 | { 84 | glColor3f(0.5f, 0.5, 0.5); 85 | glVertex3f(centers[i].x, centers[i].y, 0.0); 86 | } 87 | glEnd(); 88 | 89 | // draw start and end point 90 | glPointSize(5); 91 | glBegin(GL_POINTS); 92 | glColor3f(1.0f, 0.0, 0.0); 93 | if (fromx != -1 && fromy != -1) 94 | { 95 | glVertex3f(fromx, fromy, 0.0); 96 | } 97 | if (tox != -1 && toy != -1) 98 | { 99 | glVertex3f(tox, toy, 0.0); 100 | } 101 | glEnd(); 102 | } 103 | 104 | void myDisplay(void) 105 | { 106 | glClearColor(0.2f, 0.3f, 0.3f, 1.0f); 107 | glClear(GL_COLOR_BUFFER_BIT); 108 | DrawMap(); 109 | glFlush(); 110 | } 111 | 112 | // 鼠标点击的回调函数,目的为获取用户的鼠标点输入,并作为寻路的起点和终点来进行寻路 113 | // param : 114 | // button: GLUT_LEFT_BUTTON或GLUT_RIGHT_BUTTON分别表示左右按键。 115 | // state: 按键的状态,若为按下则为GLUT_DOWN 116 | void myClick(int button, int state, int x, int y) 117 | { 118 | if (state == 1) // 抬起是1 119 | { 120 | ways.clear(); 121 | clicknum += 1; 122 | int t = clicknum % 3; 123 | if (t == 0) 124 | { 125 | fromx = fromy = tox = toy = -1; 126 | } 127 | else if (t == 1) 128 | { 129 | fromx = x; 130 | fromy = y; 131 | } 132 | else if (t == 2) 133 | { 134 | tox = x; 135 | toy = y; 136 | ways = polygon->FindPath(Point(fromx, fromy), Point(tox, toy)); 137 | } 138 | myDisplay(); 139 | } 140 | } 141 | 142 | int main(int argc, char *argv[]) 143 | { 144 | 145 | Point p1(0, 10); 146 | p1.inLeft(Point(1, 1)); 147 | 148 | glutInit(&argc, argv); 149 | 150 | glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE); 151 | glutInitWindowPosition(30, 30); // 定义窗口位置 152 | glutInitWindowSize(1000, 800); // 定义窗口大小 153 | glutCreateWindow("navmesh test"); 154 | // gluOrtho2D(x_mix, x_max, y_mix, y_max) 155 | // 用于截取世界坐标系相应区域。在世界坐标系中以从(x_mix, x_max)到(y_mix, y_max)的直线为对角线的 156 | // 矩形部分截取图像,该截图可以被用于显示。 157 | gluOrtho2D(0, 1000, 800, 0); 158 | glutDisplayFunc(myDisplay); 159 | glutMouseFunc(myClick); 160 | glutMainLoop(); 161 | return 0; 162 | } -------------------------------------------------------------------------------- /tools/gen_map_tools/navmesh_test.py: -------------------------------------------------------------------------------- 1 | 2 | import navmesh 3 | import unittest 4 | 5 | 6 | class TestPoint(unittest.TestCase): 7 | 8 | def test_sub(self): 9 | p1 = navmesh.Point(6,6) 10 | p2 = navmesh.Point(2,2) 11 | self.assertEqual(p1.sub(p2), navmesh.Point(4,4)) 12 | 13 | 14 | class TestEdge(unittest.TestCase): 15 | 16 | def test_other(self): 17 | e1 = navmesh.Edge(1, 2) 18 | self.assertEqual(e1.other(1), 2) 19 | self.assertEqual(e1.other(2), 1) 20 | 21 | def test_edge_index(self): 22 | self.assertEqual(navmesh.Edge.edge_index(1,2), 1*navmesh.MAX_POINT + 2) 23 | self.assertEqual(navmesh.Edge.edge_index(2,1), 1*navmesh.MAX_POINT + 2) 24 | 25 | def test_make_edge(self): 26 | # print(navmesh.Edge.make_edge(1*navmesh.MAX_POINT + 2)) 27 | # print(navmesh.Edge(1,2)) 28 | self.assertEqual(navmesh.Edge.make_edge(1*navmesh.MAX_POINT + 2), navmesh.Edge(1,2)) 29 | 30 | 31 | class TestPolygon(unittest.TestCase): 32 | def test_init(self): 33 | points = [ 34 | navmesh.Point(0,0), 35 | navmesh.Point(0,1), 36 | navmesh.Point(1,1), 37 | navmesh.Point(1,0), 38 | ] 39 | polygon = navmesh.Polygon(points) 40 | # print(polygon) 41 | self.assertEqual(polygon.points, points) 42 | self.assertEqual(polygon.clock, False) 43 | 44 | 45 | points = [ 46 | navmesh.Point(1,0), 47 | navmesh.Point(1,1), 48 | navmesh.Point(0,1), 49 | navmesh.Point(0,0), 50 | ] 51 | polygon = navmesh.Polygon(points) 52 | self.assertEqual(polygon.points, points) 53 | self.assertEqual(polygon.clock, True) 54 | 55 | def test_contain(self): 56 | p1 = navmesh.Polygon([ 57 | navmesh.Point(0,0), 58 | navmesh.Point(0,1), 59 | navmesh.Point(1,1), 60 | navmesh.Point(1,0), 61 | ]) 62 | p2 = navmesh.Polygon([ 63 | navmesh.Point(0.5,0.5), 64 | navmesh.Point(0.5,0.6), 65 | navmesh.Point(0.6,0.6), 66 | navmesh.Point(0.6,0.5), 67 | ]) 68 | self.assertTrue(p1.contain(p2)) 69 | 70 | p1 = navmesh.Polygon([ 71 | navmesh.Point(0,0), 72 | navmesh.Point(0,1), 73 | navmesh.Point(1,1), 74 | navmesh.Point(1,0), 75 | ]) 76 | p2 = navmesh.Polygon([ 77 | navmesh.Point(0.5,0.5), 78 | navmesh.Point(0.5,0.6), 79 | navmesh.Point(0.6,0.6), 80 | navmesh.Point(0.6,0.5), 81 | ]) 82 | self.assertFalse(p2.contain(p1)) 83 | 84 | def test_contained(self): 85 | p1 = navmesh.Polygon([ 86 | navmesh.Point(0,0), 87 | navmesh.Point(0,1), 88 | navmesh.Point(1,1), 89 | navmesh.Point(1,0), 90 | ]) 91 | p2 = navmesh.Polygon([ 92 | navmesh.Point(0.5,0.5), 93 | navmesh.Point(0.5,0.6), 94 | navmesh.Point(0.6,0.6), 95 | navmesh.Point(0.6,0.5), 96 | ]) 97 | p3 = navmesh.Polygon([ 98 | navmesh.Point(0.5,0.5), 99 | navmesh.Point(0.5,0.6), 100 | navmesh.Point(0.6,0.6), 101 | navmesh.Point(0.6,0.5), 102 | ]) 103 | polygons = [p1, p2, p3] 104 | self.assertEqual(p1.contained(polygons), None) 105 | self.assertEqual(p2.contained(polygons), p1) 106 | self.assertEqual(p3.contained(polygons), p1) 107 | 108 | 109 | def test_to_list(self): 110 | 111 | points = [ 112 | navmesh.Point(0,0), 113 | navmesh.Point(0,1), 114 | navmesh.Point(1,1), 115 | navmesh.Point(1,0), 116 | navmesh.Point(0,0), 117 | ] 118 | polygon = navmesh.Polygon(points) 119 | self.assertEqual(polygon.clock, False) 120 | 121 | list = [] 122 | polygon.to_list(True, list) 123 | self.assertEqual(list, [4, 1, 0, 1, 1, 0, 1, 0, 0]) 124 | 125 | list = [] 126 | polygon.to_list(False, list) 127 | self.assertEqual(list, [4, 0, 0, 0, 1, 1, 1, 1, 0]) 128 | 129 | 130 | 131 | class TestNavMesh(unittest.TestCase): 132 | def test_find_loopback(self): 133 | # 四边形套四边形的地图 134 | vertices = [ 135 | [0,0,0], 136 | [3,0,0], 137 | [3,0,3], 138 | [0,0,3], 139 | [1,0,1], 140 | [2,0,1], 141 | [2,0,2], 142 | [1,0,2], 143 | [1.0001,0,2.0001], 144 | ] 145 | indices = [ 146 | 1,5,6, 147 | 1,2,6, 148 | 2,6,7, 149 | 2,3,7, 150 | 3,7,8, 151 | 3,4,8, 152 | 4,8,5, 153 | 4,1,5, 154 | ] 155 | 156 | mesh = navmesh.NavMash(vertices, indices) 157 | # print(mesh) 158 | pols = mesh.find_loopback() 159 | # print(pols) 160 | pols = mesh.gen_navmesh() 161 | # print("pols:", pols) 162 | if __name__ == '__main__': 163 | unittest.main() -------------------------------------------------------------------------------- /tools/gen_map_tools/parse_obj.py: -------------------------------------------------------------------------------- 1 | """ 2 | ------------------------- 3 | How to use this converter 4 | ------------------------- 5 | python convert_obj_three.py -i infile.obj -o outfile.txt 6 | Notes: 7 | - flags 8 | -i infile.obj input OBJ file 9 | -o outfile.js output txt file 10 | 11 | """ 12 | 13 | import fileinput 14 | 15 | 16 | # ##################################################### 17 | # Utils 18 | # ##################################################### 19 | def file_exists(filename): 20 | """Return true if file exists and is accessible for reading. 21 | Should be safer than just testing for existence due to links and 22 | permissions magic on Unix filesystems. 23 | @rtype: boolean 24 | """ 25 | 26 | try: 27 | f = open(filename, 'r') 28 | f.close() 29 | return True 30 | except IOError: 31 | return False 32 | 33 | 34 | 35 | # ##################################################### 36 | # OBJ parser 37 | # ##################################################### 38 | def parse_vertex(text): 39 | """Parse text chunk specifying single vertex. 40 | Possible formats: 41 | vertex index 42 | vertex index / texture index 43 | vertex index / texture index / normal index 44 | vertex index / / normal index 45 | """ 46 | 47 | v = 0 48 | t = 0 49 | n = 0 50 | 51 | chunks = text.split("/") 52 | 53 | v = int(chunks[0]) 54 | if len(chunks) > 1: 55 | if chunks[1]: 56 | t = int(chunks[1]) 57 | if len(chunks) > 2: 58 | if chunks[2]: 59 | n = int(chunks[2]) 60 | 61 | return { 'v':v, 't':t, 'n':n } 62 | 63 | def parse_obj(fname): 64 | """Parse OBJ file. 65 | """ 66 | 67 | vertices = [] 68 | normals = [] 69 | uvs = [] 70 | 71 | faces = [] 72 | 73 | 74 | triangles = [] 75 | 76 | materials = {} 77 | material = "" 78 | mcounter = 0 79 | mcurrent = 0 80 | 81 | mtllib = "" 82 | 83 | # current face state 84 | group = 0 85 | object = 0 86 | smooth = 0 87 | 88 | for line in fileinput.input(fname): 89 | chunks = line.split() 90 | if len(chunks) > 0: 91 | 92 | # Vertices as (x,y,z) coordinates 93 | # v 0.123 0.234 0.345 94 | if chunks[0] == "v" and len(chunks) == 4: 95 | x = float(chunks[1]) 96 | y = float(chunks[2]) 97 | z = float(chunks[3]) 98 | vertices.append([x,y,z]) 99 | 100 | # Normals in (x,y,z) form; normals might not be unit 101 | # vn 0.707 0.000 0.707 102 | if chunks[0] == "vn" and len(chunks) == 4: 103 | x = float(chunks[1]) 104 | y = float(chunks[2]) 105 | z = float(chunks[3]) 106 | normals.append([x,y,z]) 107 | 108 | # Texture coordinates in (u,v[,w]) coordinates, w is optional 109 | # vt 0.500 -1.352 [0.234] 110 | if chunks[0] == "vt" and len(chunks) >= 3: 111 | u = float(chunks[1]) 112 | v = float(chunks[2]) 113 | w = 0 114 | if len(chunks)>3: 115 | w = float(chunks[3]) 116 | uvs.append([u,v,w]) 117 | 118 | # Face 119 | if chunks[0] == "f" and len(chunks) >= 4: 120 | vertex_index = [] 121 | uv_index = [] 122 | normal_index = [] 123 | 124 | triangles.append(chunks[1]) 125 | triangles.append(chunks[2]) 126 | triangles.append(chunks[3]) 127 | # Precompute vert / normal / uv lists 128 | # for negative index lookup 129 | vertlen = len(vertices) + 1 130 | normlen = len(normals) + 1 131 | uvlen = len(uvs) + 1 132 | 133 | for v in chunks[1:]: 134 | vertex = parse_vertex(v) 135 | if vertex['v']: 136 | if vertex['v'] < 0: 137 | vertex['v'] += vertlen 138 | vertex_index.append(vertex['v']) 139 | if vertex['t']: 140 | if vertex['t'] < 0: 141 | vertex['t'] += uvlen 142 | uv_index.append(vertex['t']) 143 | if vertex['n']: 144 | if vertex['n'] < 0: 145 | vertex['n'] += normlen 146 | normal_index.append(vertex['n']) 147 | faces.append({ 148 | 'vertex':vertex_index, 149 | 'uv':uv_index, 150 | 'normal':normal_index, 151 | 152 | 'material':mcurrent, 153 | 'group':group, 154 | 'object':object, 155 | 'smooth':smooth, 156 | }) 157 | 158 | # Group 159 | if chunks[0] == "g" and len(chunks) == 2: 160 | group = chunks[1] 161 | 162 | # Object 163 | if chunks[0] == "o" and len(chunks) == 2: 164 | object = chunks[1] 165 | 166 | # Materials definition 167 | if chunks[0] == "mtllib" and len(chunks) == 2: 168 | mtllib = chunks[1] 169 | 170 | # Material 171 | if chunks[0] == "usemtl": 172 | if len(chunks) > 1: 173 | material = chunks[1] 174 | else: 175 | material = "" 176 | if not material in materials: 177 | mcurrent = mcounter 178 | materials[material] = mcounter 179 | mcounter += 1 180 | else: 181 | mcurrent = materials[material] 182 | 183 | # Smooth shading 184 | if chunks[0] == "s" and len(chunks) == 2: 185 | smooth = chunks[1] 186 | 187 | return vertices, triangles, faces, uvs, normals, materials, mtllib 188 | 189 | 190 | 191 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | ## 导航网格寻路项目说明 3 | 每个mmorpg游戏中都会少不了有寻路模块,且还是开发中的一个难点,涉及到地形资源、客户端、服务器端,涉及到的算法还比较多,还得注意它的性能开销。相信不少游戏开发者都想弄清楚它是怎么实现的。网上讲解这方面的文章也有不少,github上的开源实现也有一些,不过有很大一部分是unity相关的,或者c#实现的。c++的实现也有,但是没几个像俺这样对初级中级程序员这么友好的。友好的原因如下: 4 | 5 | * 俺的这版是导航网格寻路的最简化版,仅是实现了平面多边形(没有相互嵌套的)的三角剖分和两点之间的寻路,代码量可谓相当少,实现的也比较通俗易懂。 6 | * 俺还会提供一些资料和一些线索来引导你去了解实现的过程。 7 | 8 | 了解学习一个东西如果一下子把你带到一个很难很深的level的话,恐怕还多人都是吃不消的。就应该循序渐进,按步登阶,从简入深。俺这个就是遵循这样的精神滴。这个是个入门版的,相信聪明的你很快就能看懂学会,说不定修改就直接用到你们的游戏里面!此项目为入门版,功能少且简单,进阶版的请看这里[导航网格寻路C++实现版(进阶版)](https://github.com/sunxvming/navmesh-advance)。 9 | 10 | 11 | ## 寻路功能的实现步骤 12 | ### 1.寻路地图文件的生成 13 | 对游戏中需要寻路的场景通常都需要对其进行相应的处理以生成专门针对寻路功能所使用的文件,文件里面包含了地图的信息,比如地图的顶点、边、三角形等。这个文件的生成通常是由专门的生成工具来完成的,比如在unity中,可以通过Unity的插件把场景文件导出为寻路地图文件。 14 | ### 2.对地图文件进行格栅化 15 | 对于寻路地图文件,我们需要对其进行进一步的格栅化处理,格栅化通常指的是将游戏地图划分为离散的网格的过程,网格又分为可行走区域和不可行走区域。格栅化后以便寻路算法能够更有效地进行路径搜索 。 16 | 常见的栅格化有正方形网格、三角形网格: 17 | 18 | - **正方形网格**:易于实现和理解,方法简单直观,但不适用于不规则地形。其中格子选择的大小对寻路算法影响很大。小格子供更高的地图精度,但算法效率低。大格子效率高但提供的精度低。 19 | - **三角形网格**:适用于复杂地形,节省空间,但实现稍复杂些。 20 | 21 | 如何你对正方形网格格栅化感兴趣的话,可以看一下[俺的github](https://github.com/sunxvming)上的另一个[路径规划的工程](https://github.com/sunxvming/pathplan),其中的`pathplan-gird`目录下的程序用的便是正方形网格,程序运行的截图如下: 22 | ![image.png](https://github.com/sunxvming/navmesh/blob/master/img/20240214150332.png) 23 | 24 | ### 3.网格寻路 25 | 网格寻路是一种基于网格的寻路算法,它的基本思想是:首先将地图划分为一个个的网格,然后在网格中寻找一条从起点到终点的路径。网格寻路的算法有很多种,比如`A*`、`Dijkstra`、`BFS`、`DFS`等等,通常可以选择`A*`算法来实现。 26 | 27 | 28 | 29 | ### 4.根据寻路的网格生成最终的路径 30 | 在网格寻路的过程中,我们只是找到了一条从起点到终点的网格路径,但是这条路径并不是我们想要的最终路径,因为这条路径是由网格组成的,而我们需要的是由顶点组成的路径。所以我们需要根据网格路径生成最终的路径。这种算法通常称为路径的二次优化算法。本工程使用拐点算法来实现。 31 | 32 | ## 编译方式说明 33 | 此工程的编译运行环境为windows,需要你的电脑的开发环境有cmake、Visual Studio或make、MinGW 34 | ### 一、cmake+visual studio编译 35 | 1.在cmake中设置源码目录和build目录 36 | ![image.png](https://github.com/sunxvming/navmesh/blob/master/img/20230113115226.png) 37 | 38 | 2.点击`configure`设置visual studio的版本,和64位应用程序 39 | ![image.png](https://github.com/sunxvming/navmesh/blob/master/img/20240131153911.png) 40 | 41 | 3.点击`Generrate`生成vs工程,生成的目录为`build`目录,用vs打开生成的工程并运行,可执行程序会生成到当前项目根目录的`bin`目录下 42 | 43 | 44 | ### 二、mingw+make+gcc编译 45 | 在项目根目录执行`make`命令即可,可执行程序同样会生成到`bin`目录下 46 | 47 | ### 三、VScode+cmake插件编译 48 | 1.选择编译套件 49 | ![image.png](https://github.com/sunxvming/navmesh/blob/master/img/20240131165800.png) 50 | 51 | ![image.png](https://github.com/sunxvming/navmesh/blob/master/img/20240131165840.png) 52 | 53 | 2.编译 54 | ![image.png](https://github.com/sunxvming/navmesh/blob/master/img/20240131165915.png) 55 | 56 | 3.运行 57 | ![image.png](https://github.com/sunxvming/navmesh/blob/master/img/20240131165954.png) 58 | 59 | 60 | ## 程序运行说明 61 | 62 | 编译成功后再运行你会看到如下的程序运行界面: 63 | ![image.png](https://github.com/sunxvming/navmesh/blob/master/img/20240131170422.png) 64 | 65 | 66 | 界面说明: 67 | * 红色的线是平面多边形,你可以把它看成游戏中的地型。 68 | * 绿色的线表示经三角剖分后构成的线 69 | * 蓝色的线代表寻路的路径 70 | * 灰色的格子代表路径规划所跨越的格子 71 | 72 | 操作说明: 73 | - 程序运行时在窗口点击第一下为寻路的起点,再点击第二下为寻路的终点。点击第三下会把之前的路径清空。 74 | 75 | 76 | ## 地图文件的生成 77 | 地图文件是一个自定义格式的文件,可以通过工具由obj模型文件导出生成,而obj模型文件可以通过Unity的插件把场景文件导出,例如这个[monitor1394/ExportSceneToObj](https://github.com/monitor1394/ExportSceneToObj)github项目。 78 | 79 | 在本项目的`tools`目录下有一个gen_map_tools的工具,此工具可以将obj模型文件导出成适合本项目的地图文件格式。 80 | 81 | 这个工具的主要逻辑就是把obj模型的地图文件的外轮廓和内轮廓的多边形识别出来,并按照如下格式生成一个文本文件 82 | > childsize,parentlength, parentpoints,[0,child1 length,child1 points, [0,child2 length, child2 points]] 83 | 84 | > 内嵌多边形数量,外多边形点的数量,外多边形的点,[0,子多边形1点的数量,子多边形1的点,[0, 子多边形2点的数量,子多边形2的点]] 85 | 86 | 下面的截图是`gen_map_tools/map`目录下的两个地图的例子 87 | 其中红色的线为外轮廓,绿色的线为内轮廓。 88 | ![image.png](https://github.com/sunxvming/navmesh/blob/master/img/20230113205512.png) 89 | ![image.png](https://github.com/sunxvming/navmesh/blob/master/img/20230113203242.png) 90 | 91 | ![image.png](https://github.com/sunxvming/navmesh/blob/master/img/20230113203022.png) 92 | 93 | ![image.png](https://github.com/sunxvming/navmesh/blob/master/img/20230113203058.png) 94 | 95 | 具体的说明和使用方法请参考`gen_map_tools`目录下的说明文档。 96 | 97 | ## 寻路涉及的主要算法 98 | 99 | 这些都可以在网上查的到,在俺的小demo中应该也很容易找的到的 100 | - 平面多边形三角剖分算法(Delaunay剖分) 101 | - 多边形用什么数据结构来表示 102 | - 各种几何图形用什么数据结构来表示 103 | - 如何生成网格以及附带数据 104 | - 如何确定一个DT点 105 | - 如何遍历整个多边形来完成三角剖分 106 | - 寻路算法 107 | - 寻路拐点算法 108 | - 判断两条线段是否相交 109 | - 判断点是否在三角形中 110 | - 判断点在向量的那一侧 111 | - 已知三点求三点的夹角 112 | 113 | 114 | ## Delaunay剖分是啥? 115 | 116 | Delaunay三角剖分其实并不是一种算法,而是一种三角剖分的标准,实现它有多种算法。它只是给出了一个“好的”三角网格的定义,它的优秀特性是空圆特性和最大化最小角特性,这两个特性避免了狭长三角形的产生,也使得Delaunay三角剖分应用广泛。 117 | 118 | **空圆特性**其实就是对于两个共边的三角形,任意一个三角形的外接圆中都不能包含有另一个三角形的顶点,这种形式的剖分产生的最小角最大(比不满足空圆特性的最小角大) 119 | 120 | 121 | ## 项目主要类说明 122 | 123 | ``` 124 | // Polygon类,代表寻路多边形的类,主要实现多边形的三角剖分和寻路 125 | Polygon 126 | vector points; 127 | vector triangles; 128 | vector edges; 129 | Grid grid; 130 | // 三角化 131 | Delaunay() 132 | eindexs // k->v (Pindex->edges的index),存放着已经处理过的所有三角形的边 133 | restrains // 存放着所有的约束边,在处理开始就已经知道 134 | // 寻路 135 | FindPath() 136 | // 多边形对应的网格结构类,由纵横的线分割的Cell(格子)组成 137 | Grid 138 | vector cells; 139 | int gride; 140 | double minx; 141 | double miny; 142 | double maxx; 143 | double maxy; 144 | int xnum; 145 | int ynum; 146 | //格子类,其中包含构成多边形的顶点链表和边链表 147 | Cell 148 | vector points; 149 | vector edges; 150 | // Triangle类,三角形的表示类 151 | Triangle 152 | int p1; 153 | int p2; 154 | int p3; 155 | int edges[3]; 156 | Point icenter;//重心 157 | Point lt; 158 | Point rb; 159 | // Edge类,表示经过剖分后的线段,一条线段可能包含一个或两个三角,包含两个点 160 | Edge 161 | int triangles[2]; 162 | int points[2]; 163 | // Line类,画网格线的时候用到 164 | Line 165 | Point p1; 166 | Point p2; 167 | // Point类,点的表示类 168 | Point 169 | double x; 170 | double y; 171 | // Circle类,表示圆 172 | Circle 173 | Point center; 174 | double r; 175 | ``` 176 | 177 | ## MMO游戏的常见的寻路逻辑 178 | ``` 179 | FindCross:向指定的方向寻路 180 | FindPath:向指定的点寻路 181 | 182 | 客户端寻路 183 | 角色寻路 184 | 摇杆移动 185 | 向摇杆方向FindCross 186 | 主要点:摇杆移动每桢渲染,但是FindCross寻路的调用要增加个冷却时间,比如100毫秒, 187 | 要不然调用寻路的接口会太频繁 188 | 屏幕点击某个位置点 189 | FindPath,寻路到指定位置 190 | 释放技能(FindCross) 191 | 寻路到目标点后释放技能 192 | 自动任务(自动打怪、自动采集、自动跟随等) 193 | FindPath,点击需要执行的任务自动寻路到目标点 194 | 195 | 服务器端寻路 196 | 怪物寻路 197 | 不存在攻击目标 198 | 巡逻 199 | 间隔固定时间在营地半径内进行一次巡逻 200 | 巡逻时会进行一次寻路(FindCross) 201 | Idle 202 | 非巡逻时间idle 203 | 204 | 存在攻击目标 205 | 若在攻击范围内,则进行对攻击目标的一次寻路(FindPath),随后释放相应的技能 206 | 207 | 宠物寻路 208 | 按照规则跟随着主人 209 | ``` 210 | 211 | ## 参考链接 212 | 213 | * [平面多边形域的快速约束Delaunay三角化](https://github.com/sunxvming/navmesh/blob/master/doc/%E5%B9%B3%E9%9D%A2%E5%A4%9A%E8%BE%B9%E5%BD%A2%E5%9F%9F%E7%9A%84%E5%BF%AB%E9%80%9F%E7%BA%A6%E6%9D%9FDelaunay%E4%B8%89%E8%A7%92%E5%8C%96.pdf) 214 | * [Nav导航网格寻路](https://blog.csdn.net/ynnmnm/article/details/44833007) 215 | * [深入理解游戏中寻路算法](https://my.oschina.net/u/1859679/blog/1486636) 216 | * [Astar寻路算法-中文](https://github.com/sunxvming/navmesh/blob/master/doc/Astar%E5%AF%BB%E8%B7%AF%E7%AE%97%E6%B3%95-%E4%B8%AD%E6%96%87.doc) 217 | * [NevMesh.Js你可以在Laya引擎中直接使用的AI寻路](http://ask.layabox.com/question/47899) 218 | * [recastnavigation: Navigation-mesh Toolset for Games](https://github.com/recastnavigation/recastnavigation) -------------------------------------------------------------------------------- /libs/freeglut_msvc/include/GL/freeglut_ext.h: -------------------------------------------------------------------------------- 1 | #ifndef __FREEGLUT_EXT_H__ 2 | #define __FREEGLUT_EXT_H__ 3 | 4 | /* 5 | * freeglut_ext.h 6 | * 7 | * The non-GLUT-compatible extensions to the freeglut library include file 8 | * 9 | * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. 10 | * Written by Pawel W. Olszta, 11 | * Creation date: Thu Dec 2 1999 12 | * 13 | * Permission is hereby granted, free of charge, to any person obtaining a 14 | * copy of this software and associated documentation files (the "Software"), 15 | * to deal in the Software without restriction, including without limitation 16 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 17 | * and/or sell copies of the Software, and to permit persons to whom the 18 | * Software is furnished to do so, subject to the following conditions: 19 | * 20 | * The above copyright notice and this permission notice shall be included 21 | * in all copies or substantial portions of the Software. 22 | * 23 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 24 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 26 | * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 27 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 28 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 29 | */ 30 | 31 | #ifdef __cplusplus 32 | extern "C" { 33 | #endif 34 | 35 | /* 36 | * Additional GLUT Key definitions for the Special key function 37 | */ 38 | #define GLUT_KEY_NUM_LOCK 0x006D 39 | #define GLUT_KEY_BEGIN 0x006E 40 | #define GLUT_KEY_DELETE 0x006F 41 | #define GLUT_KEY_SHIFT_L 0x0070 42 | #define GLUT_KEY_SHIFT_R 0x0071 43 | #define GLUT_KEY_CTRL_L 0x0072 44 | #define GLUT_KEY_CTRL_R 0x0073 45 | #define GLUT_KEY_ALT_L 0x0074 46 | #define GLUT_KEY_ALT_R 0x0075 47 | 48 | /* 49 | * GLUT API Extension macro definitions -- behaviour when the user clicks on an "x" to close a window 50 | */ 51 | #define GLUT_ACTION_EXIT 0 52 | #define GLUT_ACTION_GLUTMAINLOOP_RETURNS 1 53 | #define GLUT_ACTION_CONTINUE_EXECUTION 2 54 | 55 | /* 56 | * Create a new rendering context when the user opens a new window? 57 | */ 58 | #define GLUT_CREATE_NEW_CONTEXT 0 59 | #define GLUT_USE_CURRENT_CONTEXT 1 60 | 61 | /* 62 | * Direct/Indirect rendering context options (has meaning only in Unix/X11) 63 | */ 64 | #define GLUT_FORCE_INDIRECT_CONTEXT 0 65 | #define GLUT_ALLOW_DIRECT_CONTEXT 1 66 | #define GLUT_TRY_DIRECT_CONTEXT 2 67 | #define GLUT_FORCE_DIRECT_CONTEXT 3 68 | 69 | /* 70 | * GLUT API Extension macro definitions -- the glutGet parameters 71 | */ 72 | #define GLUT_INIT_STATE 0x007C 73 | 74 | #define GLUT_ACTION_ON_WINDOW_CLOSE 0x01F9 75 | 76 | #define GLUT_WINDOW_BORDER_WIDTH 0x01FA 77 | #define GLUT_WINDOW_BORDER_HEIGHT 0x01FB 78 | #define GLUT_WINDOW_HEADER_HEIGHT 0x01FB /* Docs say it should always have been GLUT_WINDOW_BORDER_HEIGHT, keep this for backward compatibility */ 79 | 80 | #define GLUT_VERSION 0x01FC 81 | 82 | #define GLUT_RENDERING_CONTEXT 0x01FD 83 | #define GLUT_DIRECT_RENDERING 0x01FE 84 | 85 | #define GLUT_FULL_SCREEN 0x01FF 86 | 87 | #define GLUT_SKIP_STALE_MOTION_EVENTS 0x0204 88 | 89 | #define GLUT_GEOMETRY_VISUALIZE_NORMALS 0x0205 90 | 91 | #define GLUT_STROKE_FONT_DRAW_JOIN_DOTS 0x0206 /* Draw dots between line segments of stroke fonts? */ 92 | 93 | /* 94 | * New tokens for glutInitDisplayMode. 95 | * Only one GLUT_AUXn bit may be used at a time. 96 | * Value 0x0400 is defined in OpenGLUT. 97 | */ 98 | #define GLUT_AUX 0x1000 99 | 100 | #define GLUT_AUX1 0x1000 101 | #define GLUT_AUX2 0x2000 102 | #define GLUT_AUX3 0x4000 103 | #define GLUT_AUX4 0x8000 104 | 105 | /* 106 | * Context-related flags, see fg_state.c 107 | * Set the requested OpenGL version 108 | */ 109 | #define GLUT_INIT_MAJOR_VERSION 0x0200 110 | #define GLUT_INIT_MINOR_VERSION 0x0201 111 | #define GLUT_INIT_FLAGS 0x0202 112 | #define GLUT_INIT_PROFILE 0x0203 113 | 114 | /* 115 | * Flags for glutInitContextFlags, see fg_init.c 116 | */ 117 | #define GLUT_DEBUG 0x0001 118 | #define GLUT_FORWARD_COMPATIBLE 0x0002 119 | 120 | 121 | /* 122 | * Flags for glutInitContextProfile, see fg_init.c 123 | */ 124 | #define GLUT_CORE_PROFILE 0x0001 125 | #define GLUT_COMPATIBILITY_PROFILE 0x0002 126 | 127 | /* 128 | * Process loop function, see fg_main.c 129 | */ 130 | FGAPI void FGAPIENTRY glutMainLoopEvent( void ); 131 | FGAPI void FGAPIENTRY glutLeaveMainLoop( void ); 132 | FGAPI void FGAPIENTRY glutExit ( void ); 133 | 134 | /* 135 | * Window management functions, see fg_window.c 136 | */ 137 | FGAPI void FGAPIENTRY glutFullScreenToggle( void ); 138 | FGAPI void FGAPIENTRY glutLeaveFullScreen( void ); 139 | 140 | /* 141 | * Menu functions 142 | */ 143 | FGAPI void FGAPIENTRY glutSetMenuFont( int menuID, void* font ); 144 | 145 | /* 146 | * Window-specific callback functions, see fg_callbacks.c 147 | */ 148 | FGAPI void FGAPIENTRY glutMouseWheelFunc( void (* callback)( int, int, int, int ) ); 149 | FGAPI void FGAPIENTRY glutPositionFunc( void (* callback)( int, int ) ); 150 | FGAPI void FGAPIENTRY glutCloseFunc( void (* callback)( void ) ); 151 | FGAPI void FGAPIENTRY glutWMCloseFunc( void (* callback)( void ) ); 152 | /* And also a destruction callback for menus */ 153 | FGAPI void FGAPIENTRY glutMenuDestroyFunc( void (* callback)( void ) ); 154 | 155 | /* 156 | * State setting and retrieval functions, see fg_state.c 157 | */ 158 | FGAPI void FGAPIENTRY glutSetOption ( GLenum option_flag, int value ); 159 | FGAPI int * FGAPIENTRY glutGetModeValues(GLenum mode, int * size); 160 | /* A.Donev: User-data manipulation */ 161 | FGAPI void* FGAPIENTRY glutGetWindowData( void ); 162 | FGAPI void FGAPIENTRY glutSetWindowData(void* data); 163 | FGAPI void* FGAPIENTRY glutGetMenuData( void ); 164 | FGAPI void FGAPIENTRY glutSetMenuData(void* data); 165 | 166 | /* 167 | * Font stuff, see fg_font.c 168 | */ 169 | FGAPI int FGAPIENTRY glutBitmapHeight( void* font ); 170 | FGAPI GLfloat FGAPIENTRY glutStrokeHeight( void* font ); 171 | FGAPI void FGAPIENTRY glutBitmapString( void* font, const unsigned char *string ); 172 | FGAPI void FGAPIENTRY glutStrokeString( void* font, const unsigned char *string ); 173 | 174 | /* 175 | * Geometry functions, see fg_geometry.c 176 | */ 177 | FGAPI void FGAPIENTRY glutWireRhombicDodecahedron( void ); 178 | FGAPI void FGAPIENTRY glutSolidRhombicDodecahedron( void ); 179 | FGAPI void FGAPIENTRY glutWireSierpinskiSponge ( int num_levels, double offset[3], double scale ); 180 | FGAPI void FGAPIENTRY glutSolidSierpinskiSponge ( int num_levels, double offset[3], double scale ); 181 | FGAPI void FGAPIENTRY glutWireCylinder( double radius, double height, GLint slices, GLint stacks); 182 | FGAPI void FGAPIENTRY glutSolidCylinder( double radius, double height, GLint slices, GLint stacks); 183 | 184 | /* 185 | * Rest of functions for rendering Newell's teaset, found in fg_teapot.c 186 | * NB: front facing polygons have clockwise winding, not counter clockwise 187 | */ 188 | FGAPI void FGAPIENTRY glutWireTeacup( double size ); 189 | FGAPI void FGAPIENTRY glutSolidTeacup( double size ); 190 | FGAPI void FGAPIENTRY glutWireTeaspoon( double size ); 191 | FGAPI void FGAPIENTRY glutSolidTeaspoon( double size ); 192 | 193 | /* 194 | * Extension functions, see fg_ext.c 195 | */ 196 | typedef void (*GLUTproc)(); 197 | FGAPI GLUTproc FGAPIENTRY glutGetProcAddress( const char *procName ); 198 | 199 | /* 200 | * Multi-touch/multi-pointer extensions 201 | */ 202 | 203 | #define GLUT_HAS_MULTI 1 204 | 205 | /* TODO: add device_id parameter, 206 | cf. http://sourceforge.net/mailarchive/forum.php?thread_name=20120518071314.GA28061%40perso.beuc.net&forum_name=freeglut-developer */ 207 | FGAPI void FGAPIENTRY glutMultiEntryFunc( void (* callback)( int, int ) ); 208 | FGAPI void FGAPIENTRY glutMultiButtonFunc( void (* callback)( int, int, int, int, int ) ); 209 | FGAPI void FGAPIENTRY glutMultiMotionFunc( void (* callback)( int, int, int ) ); 210 | FGAPI void FGAPIENTRY glutMultiPassiveFunc( void (* callback)( int, int, int ) ); 211 | 212 | /* 213 | * Joystick functions, see fg_joystick.c 214 | */ 215 | /* USE OF THESE FUNCTIONS IS DEPRECATED !!!!! */ 216 | /* If you have a serious need for these functions in your application, please either 217 | * contact the "freeglut" developer community at freeglut-developer@lists.sourceforge.net, 218 | * switch to the OpenGLUT library, or else port your joystick functionality over to PLIB's 219 | * "js" library. 220 | */ 221 | int glutJoystickGetNumAxes( int ident ); 222 | int glutJoystickGetNumButtons( int ident ); 223 | int glutJoystickNotWorking( int ident ); 224 | float glutJoystickGetDeadBand( int ident, int axis ); 225 | void glutJoystickSetDeadBand( int ident, int axis, float db ); 226 | float glutJoystickGetSaturation( int ident, int axis ); 227 | void glutJoystickSetSaturation( int ident, int axis, float st ); 228 | void glutJoystickSetMinRange( int ident, float *axes ); 229 | void glutJoystickSetMaxRange( int ident, float *axes ); 230 | void glutJoystickSetCenter( int ident, float *axes ); 231 | void glutJoystickGetMinRange( int ident, float *axes ); 232 | void glutJoystickGetMaxRange( int ident, float *axes ); 233 | void glutJoystickGetCenter( int ident, float *axes ); 234 | 235 | /* 236 | * Initialization functions, see fg_init.c 237 | */ 238 | /* to get the typedef for va_list */ 239 | #include 240 | FGAPI void FGAPIENTRY glutInitContextVersion( int majorVersion, int minorVersion ); 241 | FGAPI void FGAPIENTRY glutInitContextFlags( int flags ); 242 | FGAPI void FGAPIENTRY glutInitContextProfile( int profile ); 243 | FGAPI void FGAPIENTRY glutInitErrorFunc( void (* callback)( const char *fmt, va_list ap ) ); 244 | FGAPI void FGAPIENTRY glutInitWarningFunc( void (* callback)( const char *fmt, va_list ap ) ); 245 | 246 | /* OpenGL >= 2.0 support */ 247 | FGAPI void FGAPIENTRY glutSetVertexAttribCoord3(GLint attrib); 248 | FGAPI void FGAPIENTRY glutSetVertexAttribNormal(GLint attrib); 249 | FGAPI void FGAPIENTRY glutSetVertexAttribTexCoord2(GLint attrib); 250 | 251 | /* Mobile platforms lifecycle */ 252 | FGAPI void FGAPIENTRY glutInitContextFunc(void (* callback)()); 253 | FGAPI void FGAPIENTRY glutAppStatusFunc(void (* callback)(int)); 254 | /* state flags that can be passed to callback set by glutAppStatusFunc */ 255 | #define GLUT_APPSTATUS_PAUSE 0x0001 256 | #define GLUT_APPSTATUS_RESUME 0x0002 257 | 258 | /* 259 | * GLUT API macro definitions -- the display mode definitions 260 | */ 261 | #define GLUT_CAPTIONLESS 0x0400 262 | #define GLUT_BORDERLESS 0x0800 263 | #define GLUT_SRGB 0x1000 264 | 265 | #ifdef __cplusplus 266 | } 267 | #endif 268 | 269 | /*** END OF FILE ***/ 270 | 271 | #endif /* __FREEGLUT_EXT_H__ */ 272 | -------------------------------------------------------------------------------- /libs/freeglut_mingw/include/GL/freeglut_ext.h: -------------------------------------------------------------------------------- 1 | #ifndef __FREEGLUT_EXT_H__ 2 | #define __FREEGLUT_EXT_H__ 3 | 4 | /* 5 | * freeglut_ext.h 6 | * 7 | * The non-GLUT-compatible extensions to the freeglut library include file 8 | * 9 | * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. 10 | * Written by Pawel W. Olszta, 11 | * Creation date: Thu Dec 2 1999 12 | * 13 | * Permission is hereby granted, free of charge, to any person obtaining a 14 | * copy of this software and associated documentation files (the "Software"), 15 | * to deal in the Software without restriction, including without limitation 16 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 17 | * and/or sell copies of the Software, and to permit persons to whom the 18 | * Software is furnished to do so, subject to the following conditions: 19 | * 20 | * The above copyright notice and this permission notice shall be included 21 | * in all copies or substantial portions of the Software. 22 | * 23 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 24 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 26 | * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 27 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 28 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 29 | */ 30 | 31 | #ifdef __cplusplus 32 | extern "C" { 33 | #endif 34 | 35 | /* 36 | * Additional GLUT Key definitions for the Special key function 37 | */ 38 | #define GLUT_KEY_NUM_LOCK 0x006D 39 | #define GLUT_KEY_BEGIN 0x006E 40 | #define GLUT_KEY_DELETE 0x006F 41 | #define GLUT_KEY_SHIFT_L 0x0070 42 | #define GLUT_KEY_SHIFT_R 0x0071 43 | #define GLUT_KEY_CTRL_L 0x0072 44 | #define GLUT_KEY_CTRL_R 0x0073 45 | #define GLUT_KEY_ALT_L 0x0074 46 | #define GLUT_KEY_ALT_R 0x0075 47 | 48 | /* 49 | * GLUT API Extension macro definitions -- behaviour when the user clicks on an "x" to close a window 50 | */ 51 | #define GLUT_ACTION_EXIT 0 52 | #define GLUT_ACTION_GLUTMAINLOOP_RETURNS 1 53 | #define GLUT_ACTION_CONTINUE_EXECUTION 2 54 | 55 | /* 56 | * Create a new rendering context when the user opens a new window? 57 | */ 58 | #define GLUT_CREATE_NEW_CONTEXT 0 59 | #define GLUT_USE_CURRENT_CONTEXT 1 60 | 61 | /* 62 | * Direct/Indirect rendering context options (has meaning only in Unix/X11) 63 | */ 64 | #define GLUT_FORCE_INDIRECT_CONTEXT 0 65 | #define GLUT_ALLOW_DIRECT_CONTEXT 1 66 | #define GLUT_TRY_DIRECT_CONTEXT 2 67 | #define GLUT_FORCE_DIRECT_CONTEXT 3 68 | 69 | /* 70 | * GLUT API Extension macro definitions -- the glutGet parameters 71 | */ 72 | #define GLUT_INIT_STATE 0x007C 73 | 74 | #define GLUT_ACTION_ON_WINDOW_CLOSE 0x01F9 75 | 76 | #define GLUT_WINDOW_BORDER_WIDTH 0x01FA 77 | #define GLUT_WINDOW_BORDER_HEIGHT 0x01FB 78 | #define GLUT_WINDOW_HEADER_HEIGHT 0x01FB /* Docs say it should always have been GLUT_WINDOW_BORDER_HEIGHT, keep this for backward compatibility */ 79 | 80 | #define GLUT_VERSION 0x01FC 81 | 82 | #define GLUT_RENDERING_CONTEXT 0x01FD 83 | #define GLUT_DIRECT_RENDERING 0x01FE 84 | 85 | #define GLUT_FULL_SCREEN 0x01FF 86 | 87 | #define GLUT_SKIP_STALE_MOTION_EVENTS 0x0204 88 | 89 | #define GLUT_GEOMETRY_VISUALIZE_NORMALS 0x0205 90 | 91 | #define GLUT_STROKE_FONT_DRAW_JOIN_DOTS 0x0206 /* Draw dots between line segments of stroke fonts? */ 92 | 93 | /* 94 | * New tokens for glutInitDisplayMode. 95 | * Only one GLUT_AUXn bit may be used at a time. 96 | * Value 0x0400 is defined in OpenGLUT. 97 | */ 98 | #define GLUT_AUX 0x1000 99 | 100 | #define GLUT_AUX1 0x1000 101 | #define GLUT_AUX2 0x2000 102 | #define GLUT_AUX3 0x4000 103 | #define GLUT_AUX4 0x8000 104 | 105 | /* 106 | * Context-related flags, see fg_state.c 107 | * Set the requested OpenGL version 108 | */ 109 | #define GLUT_INIT_MAJOR_VERSION 0x0200 110 | #define GLUT_INIT_MINOR_VERSION 0x0201 111 | #define GLUT_INIT_FLAGS 0x0202 112 | #define GLUT_INIT_PROFILE 0x0203 113 | 114 | /* 115 | * Flags for glutInitContextFlags, see fg_init.c 116 | */ 117 | #define GLUT_DEBUG 0x0001 118 | #define GLUT_FORWARD_COMPATIBLE 0x0002 119 | 120 | 121 | /* 122 | * Flags for glutInitContextProfile, see fg_init.c 123 | */ 124 | #define GLUT_CORE_PROFILE 0x0001 125 | #define GLUT_COMPATIBILITY_PROFILE 0x0002 126 | 127 | /* 128 | * Process loop function, see fg_main.c 129 | */ 130 | FGAPI void FGAPIENTRY glutMainLoopEvent( void ); 131 | FGAPI void FGAPIENTRY glutLeaveMainLoop( void ); 132 | FGAPI void FGAPIENTRY glutExit ( void ); 133 | 134 | /* 135 | * Window management functions, see fg_window.c 136 | */ 137 | FGAPI void FGAPIENTRY glutFullScreenToggle( void ); 138 | FGAPI void FGAPIENTRY glutLeaveFullScreen( void ); 139 | 140 | /* 141 | * Menu functions 142 | */ 143 | FGAPI void FGAPIENTRY glutSetMenuFont( int menuID, void* font ); 144 | 145 | /* 146 | * Window-specific callback functions, see fg_callbacks.c 147 | */ 148 | FGAPI void FGAPIENTRY glutMouseWheelFunc( void (* callback)( int, int, int, int ) ); 149 | FGAPI void FGAPIENTRY glutPositionFunc( void (* callback)( int, int ) ); 150 | FGAPI void FGAPIENTRY glutCloseFunc( void (* callback)( void ) ); 151 | FGAPI void FGAPIENTRY glutWMCloseFunc( void (* callback)( void ) ); 152 | /* And also a destruction callback for menus */ 153 | FGAPI void FGAPIENTRY glutMenuDestroyFunc( void (* callback)( void ) ); 154 | 155 | /* 156 | * State setting and retrieval functions, see fg_state.c 157 | */ 158 | FGAPI void FGAPIENTRY glutSetOption ( GLenum option_flag, int value ); 159 | FGAPI int * FGAPIENTRY glutGetModeValues(GLenum mode, int * size); 160 | /* A.Donev: User-data manipulation */ 161 | FGAPI void* FGAPIENTRY glutGetWindowData( void ); 162 | FGAPI void FGAPIENTRY glutSetWindowData(void* data); 163 | FGAPI void* FGAPIENTRY glutGetMenuData( void ); 164 | FGAPI void FGAPIENTRY glutSetMenuData(void* data); 165 | 166 | /* 167 | * Font stuff, see fg_font.c 168 | */ 169 | FGAPI int FGAPIENTRY glutBitmapHeight( void* font ); 170 | FGAPI GLfloat FGAPIENTRY glutStrokeHeight( void* font ); 171 | FGAPI void FGAPIENTRY glutBitmapString( void* font, const unsigned char *string ); 172 | FGAPI void FGAPIENTRY glutStrokeString( void* font, const unsigned char *string ); 173 | 174 | /* 175 | * Geometry functions, see fg_geometry.c 176 | */ 177 | FGAPI void FGAPIENTRY glutWireRhombicDodecahedron( void ); 178 | FGAPI void FGAPIENTRY glutSolidRhombicDodecahedron( void ); 179 | FGAPI void FGAPIENTRY glutWireSierpinskiSponge ( int num_levels, double offset[3], double scale ); 180 | FGAPI void FGAPIENTRY glutSolidSierpinskiSponge ( int num_levels, double offset[3], double scale ); 181 | FGAPI void FGAPIENTRY glutWireCylinder( double radius, double height, GLint slices, GLint stacks); 182 | FGAPI void FGAPIENTRY glutSolidCylinder( double radius, double height, GLint slices, GLint stacks); 183 | 184 | /* 185 | * Rest of functions for rendering Newell's teaset, found in fg_teapot.c 186 | * NB: front facing polygons have clockwise winding, not counter clockwise 187 | */ 188 | FGAPI void FGAPIENTRY glutWireTeacup( double size ); 189 | FGAPI void FGAPIENTRY glutSolidTeacup( double size ); 190 | FGAPI void FGAPIENTRY glutWireTeaspoon( double size ); 191 | FGAPI void FGAPIENTRY glutSolidTeaspoon( double size ); 192 | 193 | /* 194 | * Extension functions, see fg_ext.c 195 | */ 196 | typedef void (*GLUTproc)(); 197 | FGAPI GLUTproc FGAPIENTRY glutGetProcAddress( const char *procName ); 198 | 199 | /* 200 | * Multi-touch/multi-pointer extensions 201 | */ 202 | 203 | #define GLUT_HAS_MULTI 1 204 | 205 | /* TODO: add device_id parameter, 206 | cf. http://sourceforge.net/mailarchive/forum.php?thread_name=20120518071314.GA28061%40perso.beuc.net&forum_name=freeglut-developer */ 207 | FGAPI void FGAPIENTRY glutMultiEntryFunc( void (* callback)( int, int ) ); 208 | FGAPI void FGAPIENTRY glutMultiButtonFunc( void (* callback)( int, int, int, int, int ) ); 209 | FGAPI void FGAPIENTRY glutMultiMotionFunc( void (* callback)( int, int, int ) ); 210 | FGAPI void FGAPIENTRY glutMultiPassiveFunc( void (* callback)( int, int, int ) ); 211 | 212 | /* 213 | * Joystick functions, see fg_joystick.c 214 | */ 215 | /* USE OF THESE FUNCTIONS IS DEPRECATED !!!!! */ 216 | /* If you have a serious need for these functions in your application, please either 217 | * contact the "freeglut" developer community at freeglut-developer@lists.sourceforge.net, 218 | * switch to the OpenGLUT library, or else port your joystick functionality over to PLIB's 219 | * "js" library. 220 | */ 221 | int glutJoystickGetNumAxes( int ident ); 222 | int glutJoystickGetNumButtons( int ident ); 223 | int glutJoystickNotWorking( int ident ); 224 | float glutJoystickGetDeadBand( int ident, int axis ); 225 | void glutJoystickSetDeadBand( int ident, int axis, float db ); 226 | float glutJoystickGetSaturation( int ident, int axis ); 227 | void glutJoystickSetSaturation( int ident, int axis, float st ); 228 | void glutJoystickSetMinRange( int ident, float *axes ); 229 | void glutJoystickSetMaxRange( int ident, float *axes ); 230 | void glutJoystickSetCenter( int ident, float *axes ); 231 | void glutJoystickGetMinRange( int ident, float *axes ); 232 | void glutJoystickGetMaxRange( int ident, float *axes ); 233 | void glutJoystickGetCenter( int ident, float *axes ); 234 | 235 | /* 236 | * Initialization functions, see fg_init.c 237 | */ 238 | /* to get the typedef for va_list */ 239 | #include 240 | FGAPI void FGAPIENTRY glutInitContextVersion( int majorVersion, int minorVersion ); 241 | FGAPI void FGAPIENTRY glutInitContextFlags( int flags ); 242 | FGAPI void FGAPIENTRY glutInitContextProfile( int profile ); 243 | FGAPI void FGAPIENTRY glutInitErrorFunc( void (* callback)( const char *fmt, va_list ap ) ); 244 | FGAPI void FGAPIENTRY glutInitWarningFunc( void (* callback)( const char *fmt, va_list ap ) ); 245 | 246 | /* OpenGL >= 2.0 support */ 247 | FGAPI void FGAPIENTRY glutSetVertexAttribCoord3(GLint attrib); 248 | FGAPI void FGAPIENTRY glutSetVertexAttribNormal(GLint attrib); 249 | FGAPI void FGAPIENTRY glutSetVertexAttribTexCoord2(GLint attrib); 250 | 251 | /* Mobile platforms lifecycle */ 252 | FGAPI void FGAPIENTRY glutInitContextFunc(void (* callback)()); 253 | FGAPI void FGAPIENTRY glutAppStatusFunc(void (* callback)(int)); 254 | /* state flags that can be passed to callback set by glutAppStatusFunc */ 255 | #define GLUT_APPSTATUS_PAUSE 0x0001 256 | #define GLUT_APPSTATUS_RESUME 0x0002 257 | 258 | /* 259 | * GLUT API macro definitions -- the display mode definitions 260 | */ 261 | #define GLUT_CAPTIONLESS 0x0400 262 | #define GLUT_BORDERLESS 0x0800 263 | #define GLUT_SRGB 0x1000 264 | 265 | #ifdef __cplusplus 266 | } 267 | #endif 268 | 269 | /*** END OF FILE ***/ 270 | 271 | #endif /* __FREEGLUT_EXT_H__ */ 272 | -------------------------------------------------------------------------------- /tools/gen_map_tools/navmesh.py: -------------------------------------------------------------------------------- 1 | 2 | import math 3 | 4 | def index_of_first(lst, pred): 5 | for i,v in enumerate(lst): 6 | if pred(v): 7 | return i 8 | return -1 9 | 10 | 11 | MAX_POINT = 100000; 12 | 13 | DIS_PRECISION = 1000 14 | 15 | class Point: 16 | def __init__(self, x, y): 17 | self.x = x 18 | self.y = y 19 | 20 | def sub(self, point): 21 | return Point(self.x - point.x, self.y - point.y) 22 | 23 | def __str__(self) -> str: 24 | return "[{},{}]".format(self.x, self.y) 25 | 26 | def __repr__(self) -> str: 27 | return self.__str__() 28 | 29 | def __eq__(self, o: object) -> bool: 30 | return self.x == o.x and self.y == o.y 31 | 32 | class Edge: 33 | # p1, p2是点的索引 34 | def __init__(self, p1, p2): 35 | self.p1 = p1 36 | self.p2 = p2 37 | 38 | def __str__(self) -> str: 39 | return "[{},{}]".format(self.p1, self.p2) 40 | 41 | def __repr__(self) -> str: 42 | return self.__str__() 43 | 44 | def __eq__(self, o: object) -> bool: 45 | return self.p1 == o.p1 and self.p2 == o.p2 46 | 47 | # 输入点的索引,返回另一个点的索引 48 | def other(self, p): 49 | return self.p1 if self.p2 == p else self.p2 50 | 51 | # 生成edge的索引 52 | @staticmethod 53 | def edge_index(p1, p2): 54 | if p1 < p2: 55 | return p1 * MAX_POINT + p2 56 | return p2 * MAX_POINT + p1 57 | 58 | 59 | # 根据edgeindex生成Edge对象 60 | @staticmethod 61 | def make_edge(edgeindex): 62 | p1 = edgeindex // MAX_POINT; 63 | p2 = edgeindex % MAX_POINT; 64 | return Edge(p1, p2) 65 | 66 | 67 | 68 | 69 | class Polygon: 70 | 71 | def __init__(self, points:list): 72 | self.points = self.merge( points ) 73 | 74 | p0 = points[0]; 75 | minx = p0.x; 76 | miny = p0.y; 77 | maxx = p0.x; 78 | maxy = p0.y; 79 | maxxn = 0; # maxx的索引 80 | cnt = len(points) - 1 81 | 82 | for i in range(1,cnt): 83 | x = points[i].x 84 | y = points[i].y 85 | if (x < minx): 86 | minx = x 87 | if (x > maxx): 88 | maxx = x 89 | maxxn = i 90 | if (y < miny): 91 | miny = y 92 | if (y> maxy): 93 | maxy = y 94 | 95 | # 左上角为坐标原点,向下向右坐标为坐标轴的正方向 96 | self.lt = Point(minx, miny) # left top 97 | self.rb = Point(maxx, maxy) # right bottom 98 | 99 | 100 | # 判断点的集合是否是顺时针 101 | for i in range(cnt + 2): # 最大到 cnt + 1 102 | if (i == cnt + 1): 103 | print("points:",self.points) 104 | raise Exception("Clock Detect Fail") 105 | 106 | n = maxxn + i; 107 | if (n > cnt): 108 | n -= (cnt+1); 109 | p = points[n]; 110 | pre = points[cnt if n - 1 < 0 else n - 1]; 111 | nxt = points[0 if n + 1 > cnt else n + 1]; 112 | v1 = p.sub(pre); 113 | v2 = nxt.sub(p); 114 | dxy = v1.x* v2.y - v2.x * v1.y; # 二维向量叉乘判断是否顺时针 115 | if (dxy != 0): 116 | self.clock = dxy > 0; 117 | break; 118 | 119 | self.sub_polygons = []; 120 | 121 | 122 | def __str__(self) -> str: 123 | str=""" 124 | Polygon: 125 | lt:{self.lt} 126 | rb:{self.rb} 127 | clock:{self.clock} 128 | points:{self.points} 129 | sub polygons:{self.sub_polygons} 130 | """ 131 | 132 | return str.format(self=self) 133 | 134 | def __repr__(self) -> str: 135 | return self.__str__() 136 | 137 | def get_coord_list(self): 138 | return [[p.x, p.y] for p in self.points] 139 | 140 | # 把特别靠近的顶点合并 141 | def merge(self, points): 142 | # todo 之后实现 143 | return points 144 | 145 | 146 | # 多边形是否包含另一个多边形p 147 | def contain(self, p:'Polygon'): 148 | plt = p.lt; 149 | prb = p.rb; 150 | if (self.lt.x > plt.x or self.lt.y > plt.y): 151 | return False; 152 | if (self.rb.x < prb.x or self.rb.y < prb.y): 153 | return False; 154 | return True; 155 | 156 | # 返回包围自己的多边形 157 | def contained(self, polygons:list['Polygon'] ): 158 | for i in range(len(polygons)): 159 | polygon = polygons[i] 160 | if (polygon is not self and polygon.contain(self)): 161 | return polygon; 162 | 163 | return None 164 | 165 | 166 | def add_sub_polygon(self, p:'Polygon'): 167 | self.sub_polygons.append(p); 168 | 169 | 170 | def to_list(self, clock, list ): 171 | change = self.clock != clock; 172 | 173 | list.append(len(self.points)-1); 174 | if (change): 175 | for i in range(len(self.points) -2, -1, -1): 176 | x = self.points[i].x 177 | y = self.points[i].y 178 | list.append(x); 179 | list.append(y) 180 | else: 181 | for i in range(len(self.points) - 1): 182 | x = self.points[i].x 183 | y = self.points[i].y 184 | list.append(x); 185 | list.append(y); 186 | return True; 187 | 188 | 189 | class NavMash: 190 | def __init__(self, vertices:list, indices:list): 191 | if len(vertices) > MAX_POINT: 192 | raise Exception("point count is too much") 193 | 194 | self.polygons = [] 195 | self.indices = indices 196 | 197 | #===处理顶点和边的索引 198 | indices = [int(i) - 1 for i in indices] # 索引从1开始,转换为从0开始 199 | vertices_tmp = [] 200 | for i in range(len(vertices)): 201 | vertices_tmp.append(Point(vertices[i][0], vertices[i][2])) 202 | 203 | 204 | # 去除相同的点 205 | points = [] 206 | adpts = {} 207 | 208 | for i in range(len(vertices_tmp)): 209 | pt = vertices_tmp[i] 210 | index = index_of_first(points,lambda p:math.floor(pt.x*DIS_PRECISION)/DIS_PRECISION == math.floor(p.x*DIS_PRECISION)/DIS_PRECISION 211 | and math.floor(pt.y*DIS_PRECISION)/DIS_PRECISION == math.floor(p.y*DIS_PRECISION)/DIS_PRECISION) 212 | 213 | if index > -1: 214 | adpts[i] = index 215 | else: 216 | adpts[i] = len(points) 217 | points.append(pt) 218 | indexs = [] 219 | 220 | for i in range(len(indices)): 221 | n = indices[i] 222 | if n in adpts: 223 | n = adpts[n] 224 | indexs.append(n) 225 | 226 | self.vertices = points 227 | self.indices = indexs 228 | 229 | def __str__(self) -> str: 230 | str=""" 231 | NavMash: 232 | vertices:{self.vertices} 233 | indices:{self.indices} 234 | polygons:{self.polygons} 235 | """ 236 | 237 | return str.format(self=self) 238 | 239 | 240 | def find_loopback(self)->list[Polygon]: 241 | # 遍历所有三角的edge,找到所有没有被两个三角形给引用的边,用于找回环,分外回环和内回环 242 | edge2triangle_num = {}; # key是边的index,value是以该边为三角形的数量 243 | for i in range(0, len(self.indices), 3): 244 | p1 = self.indices[i]; 245 | p2 = self.indices[i+1]; 246 | p3 = self.indices[i+2]; 247 | 248 | edge1 = Edge.edge_index(p1, p2); 249 | edge2 = Edge.edge_index(p2, p3); 250 | edge3 = Edge.edge_index(p3, p1); 251 | 252 | 253 | if (edge1 in edge2triangle_num): 254 | edge2triangle_num[edge1] = edge2triangle_num[edge1] + 1; 255 | else: 256 | edge2triangle_num[edge1] = 1; 257 | 258 | if (edge2 in edge2triangle_num): 259 | edge2triangle_num[edge2] = edge2triangle_num[edge2] + 1; 260 | else: 261 | edge2triangle_num[edge2] = 1; 262 | 263 | if (edge3 in edge2triangle_num): 264 | edge2triangle_num[edge3] = edge2triangle_num[edge3] + 1; 265 | else: 266 | edge2triangle_num[edge3] = 1; 267 | 268 | # print("edge2triangle_num:",edge2triangle_num) 269 | 270 | # 点所在边集合 271 | border = [] # 多边形边界,每个边界边只有一个三角形 272 | point2edges = {} # {point_index:[border中边的index]} 点到边的映射,一个点可以映射到两个边 273 | for edge in edge2triangle_num: 274 | if (edge2triangle_num[edge] == 1): 275 | i = len(border) 276 | edge = Edge.make_edge(edge) # 通过边的索引获得边的对象,边的对象包含两个点 277 | border.append(edge); 278 | 279 | p1 = edge.p1; 280 | p2 = edge.p2; 281 | 282 | if p1 not in point2edges: 283 | point2edges[p1] = [] 284 | point2edges[p1].append(i) 285 | if len(point2edges[p1]) > 2: 286 | pass 287 | # print("point2edges[p1] > 2, len is {}, p is {}, edge is {}".format(len(point2edges[p1]), p1, edge)) 288 | 289 | 290 | if p2 not in point2edges: 291 | point2edges[p2] = [] 292 | point2edges[p2].append(i) 293 | if len(point2edges[p2]) > 2: 294 | # print("point2edges[p2] > 2, len is {}, p is {}, edge is {}".format(len(point2edges[p2]), p2, edge)) 295 | pass 296 | 297 | 298 | 299 | elif edge2triangle_num[edge] >= 3: 300 | print("error: edge2triangle_num[edge] != 1") 301 | 302 | # print("border:", border) 303 | # print("point2edges:", point2edges) 304 | 305 | # 从任意边出发,找到回环,会有多个回环,有最外层的回环和内部包含的回环 306 | polygons = [] # 多边形集合 307 | visited = {} 308 | for i in range(0, len(border)): 309 | if(i not in visited): 310 | edge = border[i] 311 | p = edge.p2 312 | polygon = [] # 一个回环,内含所有回环的点,而非点的索引 313 | polygon.append(self.vertices[edge.p1]) 314 | polygon.append(self.vertices[edge.p2]) 315 | visited[i] = True 316 | 317 | while True: 318 | edges = point2edges[p] 319 | # 异常点判断 320 | if len(edges) != 2: 321 | print("error: len(edges) is {}, p is {}, edges is {}".format(len(edges), p, edges)) 322 | # break 323 | e0 = edges[0] 324 | e1 = edges[1] 325 | 326 | if len(edges) > 2: 327 | e0 = edges[2] 328 | e1 = edges[3] 329 | e = None 330 | if e0 not in visited: 331 | e = border[e0] 332 | visited[e0] = True 333 | elif e1 not in visited: 334 | e = border[e1] 335 | visited[e1] = True 336 | 337 | # 转了一圈,回到起点 338 | if e is None: 339 | break 340 | 341 | nxtp = e.other(p) 342 | polygon.append(self.vertices[nxtp]) 343 | p = nxtp 344 | if len(polygon) >= 3: 345 | pol = Polygon(polygon) 346 | polygons.append(pol) 347 | 348 | 349 | return polygons 350 | 351 | def add_polygon(self,p:Polygon): 352 | self.polygons.append(p) 353 | 354 | 355 | 356 | def gen_navmesh(self): 357 | self.polygons = [] 358 | polygons = self.find_loopback() 359 | for i in range(len(polygons)): 360 | polygon = polygons[i]; 361 | container = polygon.contained(polygons) 362 | if (container == None): # 外回环 363 | self.add_polygon(polygon) 364 | else: # 内回环,添加到外回环中 365 | container.add_sub_polygon(polygon) 366 | return self.polygons 367 | 368 | def get_coordinate(self)->list[float]: 369 | self.gen_navmesh() 370 | 371 | coords = [] 372 | for i in range(len(self.polygons)): 373 | polygon = self.polygons[i] 374 | if len(polygon.sub_polygons) > 0: 375 | coords.append(len(polygon.sub_polygons)) 376 | polygon.to_list(True,coords) 377 | 378 | for j in range(len(polygon.sub_polygons)): 379 | sub_polygon = polygon.sub_polygons[j] 380 | coords.append(0) 381 | sub_polygon.to_list(False,coords) 382 | 383 | else: 384 | coords.append(0) 385 | polygon.to_list(True,coords) 386 | return coords 387 | 388 | def gen_navmesh_file(self,filepath): 389 | coords = self.get_coordinate() 390 | with open(filepath, 'w') as f: 391 | for i in range(len(coords)): 392 | f.write(str(coords[i]) + '\n') 393 | 394 | 395 | -------------------------------------------------------------------------------- /src/Polygon.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include "Polygon.h" 6 | #include 7 | 8 | using navmesh::Polygon; 9 | 10 | Polygon::Polygon(double pos[], int size) 11 | { 12 | assert(size > 10); 13 | assert(size < MAXPOINT * 2); 14 | for (int i = 0; i < size; i += 2) 15 | { 16 | points.push_back(Point(pos[i], pos[i + 1])); 17 | } 18 | Delaunay(); 19 | GenExtData(); 20 | } 21 | 22 | void Polygon::CreateTriangle(Hash *eindexs, int p1, int p2, int p3) 23 | { 24 | triangles.push_back(Triangle(p1, p2, p3)); 25 | int triangle = triangles.size() - 1; 26 | triangles[triangle].edges[0] = CreateEdge(eindexs, triangle, p1, p2); // 点的顺序要保持方向,外层逆时针,内层顺时针 27 | triangles[triangle].edges[1] = CreateEdge(eindexs, triangle, p3, p2); 28 | triangles[triangle].edges[2] = CreateEdge(eindexs, triangle, p1, p3); 29 | } 30 | 31 | int Polygon::CreateEdge(Hash *eindexs, int triangle, int p1, int p2) 32 | { 33 | int k = PIndex(p1, p2); 34 | if (eindexs->find(k) == eindexs->end()) 35 | { 36 | int v = edges.size(); 37 | edges.push_back(Edge(triangle, -1, p1, p2)); 38 | eindexs->insert(make_pair(k, v)); 39 | return v; 40 | } 41 | int v = (*eindexs)[k]; 42 | int t2 = edges[v].triangles[1]; 43 | assert(t2 < 0); 44 | edges[v].triangles[1] = triangle; 45 | return v; 46 | } 47 | 48 | // 叉积 ac×bc, a在bc那一侧 49 | double mult(Point a, Point b, Point c) 50 | { 51 | return (a.x - c.x) * (b.y - c.y) - (b.x - c.x) * (a.y - c.y); 52 | } 53 | 54 | #define max(a, b) ((a) > (b) ? (a) : (b)) 55 | #define min(a, b) ((a) > (b) ? (b) : (a)) 56 | // aa, bb为一条线段两端点 cc, dd为另一条线段的两端点 相交返回true, 不相交返回false 57 | bool intersect(Point aa, Point bb, Point cc, Point dd) 58 | { 59 | if (max(aa.x, bb.x) < min(cc.x, dd.x)) 60 | { 61 | return false; 62 | } 63 | if (max(aa.y, bb.y) < min(cc.y, dd.y)) 64 | { 65 | return false; 66 | } 67 | if (max(cc.x, dd.x) < min(aa.x, bb.x)) 68 | { 69 | return false; 70 | } 71 | if (max(cc.y, dd.y) < min(aa.y, bb.y)) 72 | { 73 | return false; 74 | } 75 | // cd在ab同侧 76 | if (mult(cc, bb, aa) * mult(dd, bb, aa) > 0) 77 | { 78 | return false; 79 | } 80 | // ab在cd同侧 81 | if (mult(aa, dd, cc) * mult(bb, dd, cc) > 0) 82 | { 83 | return false; 84 | } 85 | return true; 86 | } 87 | 88 | // 根据点乘公式计算first-center-second的角度(弧度制) 89 | static inline double Angle(Point cen, Point first, Point second) 90 | { 91 | double dx1, dx2, dy1, dy2; 92 | 93 | dx1 = first.x - cen.x; 94 | dy1 = first.y - cen.y; 95 | dx2 = second.x - cen.x; 96 | dy2 = second.y - cen.y; 97 | // 求(cen 到 first 的距离)*(cen 到 second 的距离) 98 | double c = (double)sqrt(dx1 * dx1 + dy1 * dy1) * (double)sqrt(dx2 * dx2 + dy2 * dy2); 99 | // 避免 cen与 first 或者 second 重叠的现象 100 | if (c == 0) 101 | return 0; 102 | 103 | return (double)acos((dx1 * dx2 + dy1 * dy2) / c); 104 | } 105 | 106 | static inline int lerp(int v, int min, int max) 107 | { 108 | if (v < min) 109 | v = min; 110 | if (v > max) 111 | v = max; 112 | return v; 113 | } 114 | 115 | int Polygon::FindDT(Grid *grid, int p1, int p2) 116 | { 117 | double x1 = points[p1].x, y1 = points[p1].y; 118 | double x2 = points[p2].x, y2 = points[p2].y; 119 | double x = (x1 + x2) / 2, y = (y1 + y2) / 2; 120 | 121 | double minx = grid->minx, miny = grid->miny; 122 | double gride_len = grid->gride_len; 123 | int gx = (int)((x - minx) / gride_len); 124 | int gy = (int)((y - miny) / gride_len); 125 | int xnum = grid->xnum, ynum = grid->ynum; 126 | int d = 0; 127 | int p3 = -1; 128 | double angle3 = -1; 129 | Point point1 = GetPoint(p1), point2 = GetPoint(p2); 130 | while (1) 131 | { 132 | for (int i = -d; i <= d; i++) 133 | { 134 | for (int j = -d; j <= d; j++) 135 | { 136 | int pos = lerp(gx + i, 0, xnum - 1) + lerp(gy + j, 0, ynum - 1) * xnum; 137 | if (pos >= 0 && pos < (int)grid->cells.size()) 138 | { 139 | Cell c = grid->cells[pos]; 140 | for (unsigned k = 0; k < c.points.size(); k++) 141 | { 142 | int p = c.points[k]; 143 | Point point = GetPoint(p); 144 | if (p1 != p && p2 != p && (point2 - point1).inLeft(point - point1)) // p 要在p1p2的左侧 145 | { 146 | bool flag = JudgeIsVisible(p1, p, grid) && JudgeIsVisible(p2, p, grid); 147 | 148 | if (flag) 149 | { 150 | double angle = Angle(point, point1, point2); 151 | if (p3 == -1 || angle > angle3) 152 | { 153 | angle3 = angle; 154 | p3 = p; 155 | } 156 | } 157 | } 158 | } 159 | } 160 | } 161 | } 162 | // 判断是否应该结束当前趟 163 | if (p3 != -1) 164 | { 165 | Circle c(point1, point2, GetPoint(p3)); 166 | Point cc = c.GetCenter(); // 外接圆圆心 167 | double radius = c.GetR(); 168 | double l = cc.x - radius, r = cc.x + radius, t = cc.y - radius, b = cc.y + radius; 169 | int lx = lerp((int)((l - minx) / gride_len), 0, xnum - 1); 170 | int rx = lerp((int)((r - minx) / gride_len), 0, xnum - 1); 171 | int ty = lerp((int)((t - miny) / gride_len), 0, ynum - 1); 172 | int by = lerp((int)((b - miny) / gride_len), 0, ynum - 1); 173 | if ((gx - d) <= lx && (gx + d) >= rx && (gy - d) <= ty && (gy + d) >= by) 174 | break; 175 | } 176 | d++; 177 | } 178 | assert(p3 != -1); 179 | return p3; 180 | } 181 | 182 | Point Polygon::GetPoint(int p) 183 | { 184 | return points[p]; 185 | } 186 | 187 | bool Polygon::IsIntersect(Grid *grid, int edgepos, int pa1, int p1) 188 | { 189 | Point pa = GetPoint(pa1); 190 | Point p = GetPoint(p1); 191 | 192 | Cell c = grid->cells[edgepos]; 193 | for (unsigned m = 0; m < c.edges.size(); m++) 194 | { 195 | int eposId = c.edges[m]; 196 | int next_eposId = (eposId + 1) % points.size(); 197 | 198 | bool flag = intersect(GetPoint(next_eposId), GetPoint(eposId), pa, p); 199 | if ((eposId == pa1) || (eposId == p1) || (next_eposId == pa1) || (next_eposId == p1)) 200 | { 201 | flag = false; 202 | } 203 | if (flag) 204 | return true; 205 | } 206 | return false; 207 | } 208 | 209 | // false代表pa 与p不可见,true代表可见 210 | bool Polygon::JudgeIsVisible(int pindex1, int pindex2, Grid *grid) 211 | { 212 | Point p1 = GetPoint(pindex1); 213 | Point p2 = GetPoint(pindex2); 214 | 215 | // 检查最大最小值合法性 216 | Point p0 = points[0]; 217 | double minx = grid->minx; 218 | double miny = grid->miny; 219 | 220 | int gride = grid->gride_len; 221 | int xnum = grid->xnum; 222 | int ynum = grid->ynum; 223 | 224 | if (p1.x > p2.x) 225 | { 226 | Point demo = p2; 227 | p2 = p1; 228 | p1 = demo; 229 | } 230 | int xn1 = (int)((p1.x - minx) / gride); 231 | int yn1 = (int)((p1.y - miny) / gride); 232 | int xn2 = (int)((p2.x - minx) / gride); 233 | int yn2 = (int)((p2.y - miny) / gride); 234 | 235 | if (xn1 == xn2) 236 | { 237 | if (yn1 > yn2) 238 | { 239 | yn1 = yn1 ^ yn2; 240 | yn2 = yn1 ^ yn2; 241 | yn1 = yn1 ^ yn2; 242 | } 243 | for (int j = yn1; j <= yn2; j++) 244 | { 245 | if (j > ynum) 246 | break; 247 | int edgepos = (xn1 >= xnum ? xnum - 1 : xn1) + (j >= ynum ? ynum - 1 : j) * xnum; 248 | if (IsIntersect(grid, edgepos, pindex1, pindex2)) 249 | return false; 250 | } 251 | } 252 | else 253 | { 254 | double x = p1.x; 255 | double y = p1.y; 256 | for (int i = xn1; i <= xn2; i++) 257 | { 258 | double x3 = (i + 1) * gride + minx; 259 | if (x3 > p2.x) 260 | x3 = p2.x; 261 | // 两点求得方程 (y-y2)/(y1-y2)=(x-x2)/(x1-x2),把x3代入计算y3 262 | double y3 = (p2.x - x3) * (p2.y - p1.y) / (p1.x - p2.x) + p2.y; 263 | 264 | int cur_x = (int)((x - minx) / gride); 265 | int cur_y = (int)((y - miny) / gride); 266 | int next_y = (int)((y3 - miny) / gride); 267 | if (cur_y > next_y) 268 | { 269 | cur_y = cur_y ^ next_y; 270 | next_y = cur_y ^ next_y; 271 | cur_y = cur_y ^ next_y; 272 | } 273 | for (int j = cur_y; j <= next_y; j++) 274 | { 275 | if (j > ynum) 276 | break; 277 | int edgepos = (cur_x >= xnum ? xnum - 1 : cur_x) + (j >= ynum ? ynum - 1 : j) * xnum; 278 | if (IsIntersect(grid, edgepos, pindex1, pindex2)) 279 | return false; 280 | } 281 | x = x3; 282 | y = y3; 283 | } 284 | } 285 | return true; 286 | } 287 | 288 | void Polygon::Delaunay() 289 | { 290 | // 检查最大最小值合法性 291 | Point p0 = points[0]; 292 | double minx = p0.x, miny = p0.y, maxx = p0.x, maxy = p0.y; 293 | for (auto const &it : points) 294 | { 295 | double x = it.x; 296 | double y = it.y; 297 | if (x < minx) 298 | minx = x; 299 | if (x > maxx) 300 | maxx = x; 301 | if (y < miny) 302 | miny = y; 303 | if (y > maxy) 304 | maxy = y; 305 | } 306 | 307 | double dx = maxx - minx, dy = maxy - miny; 308 | int gride_len = (int)sqrt(dx * dy / (points.size())); 309 | int xnum = (int)ceil(dx / gride_len); 310 | int ynum = (int)ceil(dy / gride_len); 311 | 312 | grid.gride_len = gride_len; 313 | grid.minx = minx; 314 | grid.maxx = maxx; 315 | grid.miny = miny; 316 | grid.maxy = maxy; 317 | grid.xnum = xnum; 318 | grid.ynum = ynum; 319 | 320 | // 把点和边都放到格子里 321 | vector cells(xnum * ynum); 322 | for (auto it = points.cbegin(); it != points.cend(); it++) 323 | { 324 | // point放到Grid里 325 | double x = it->x; 326 | double y = it->y; 327 | int xn = (int)((x - minx) / gride_len); 328 | int yn = (int)((y - miny) / gride_len); 329 | int pos = (xn >= xnum ? xnum - 1 : xn) + (yn >= ynum ? ynum - 1 : yn) * xnum; 330 | int point = it - points.cbegin(); 331 | cells[pos].points.push_back(point); 332 | 333 | // edges放到Grid里 334 | Point p = GetPoint(point); 335 | Point p1 = GetPoint((point + 1) % points.size()); 336 | if (p.x > p1.x) 337 | { 338 | Point demo = p; 339 | p = p1; 340 | p1 = demo; 341 | } 342 | int xn1 = (int)((p.x - minx) / gride_len); 343 | int xn2 = (int)((p1.x - minx) / gride_len); 344 | int yn1 = (int)((p.y - miny) / gride_len); 345 | int yn2 = (int)((p1.y - miny) / gride_len); 346 | 347 | if (xn1 == xn2) 348 | { 349 | if (yn1 > yn2) 350 | { 351 | yn1 = yn1 ^ yn2; 352 | yn2 = yn1 ^ yn2; 353 | yn1 = yn1 ^ yn2; 354 | } 355 | for (int j = yn1; j <= yn2; j++) 356 | { 357 | if (j > ynum) 358 | break; 359 | int edgepos = (xn1 >= xnum ? xnum - 1 : xn1) + (j >= ynum ? ynum - 1 : j) * xnum; 360 | cells[edgepos].edges.push_back(point); 361 | } 362 | } 363 | else 364 | { 365 | 366 | // 将x值偏小的 y值保存起来 367 | double y = p.y; 368 | double x = p.x; 369 | for (int i = xn1; i <= xn2; i++) 370 | { 371 | double x3 = (i + 1) * gride_len + minx; 372 | if (x3 > p1.x) 373 | x3 = p1.x; 374 | // 两点求得方程 (y-y2)/(y1-y2)=(x-x2)/(x1-x2),把x3代入计算y3, 方程是边的方程 375 | // 知道直线方程后,分别把格子两端的x值代入方程,就可以知道直线穿过的y方向的格子 376 | double y3 = (p.x - x3) * (p.y - p1.y) / (p1.x - p.x) + p.y; 377 | 378 | int cur_x = (int)((x - minx) / gride_len); 379 | int cur_y = (int)((y - miny) / gride_len); // 格子左侧y点坐标 380 | int next_y = (int)((y3 - miny) / gride_len); // 格子右侧y点坐标 381 | if (cur_y > next_y) 382 | { 383 | cur_y = cur_y ^ next_y; 384 | next_y = cur_y ^ next_y; 385 | cur_y = cur_y ^ next_y; 386 | } 387 | for (int j = cur_y; j <= next_y; j++) // 记录x前进一格,线段在y方向上跨越的格子数 388 | { 389 | if (j > ynum) 390 | break; 391 | int edgepos = (cur_x >= xnum ? xnum - 1 : cur_x) + (j >= ynum ? ynum - 1 : j) * xnum; 392 | cells[edgepos].edges.push_back(point); 393 | } 394 | x = x3; 395 | y = y3; 396 | } 397 | } 398 | } 399 | 400 | grid.cells = cells; 401 | 402 | Hash eindexs; // k->v (Pindex->edges的index),存放着已经处理过的所有三角形的边 403 | Hash restrains; // 存放着所有的约束边,即内外边界的边 404 | for (unsigned i = 0; i < points.size() - 1; i++) 405 | { 406 | restrains.insert(make_pair((int)PIndex(i, i + 1), 1)); 407 | } 408 | restrains.insert(make_pair((int)PIndex(0, points.size() - 1), 1)); 409 | 410 | vector es; // 待处理的边的栈 411 | int p1 = 0, p2 = 1; 412 | int e = PIndex(p1, p2); 413 | while (1) 414 | { 415 | int p3 = FindDT(&grid, p1, p2); 416 | if (restrains.find((int)PIndex(p1, p3)) == restrains.end()) 417 | { 418 | vector::iterator it = std::find(es.begin(), es.end(), PIndex(p1, p3)); 419 | if (it == es.end()) 420 | { 421 | es.push_back(PIndex(p1, p3)); 422 | } 423 | else 424 | { 425 | es.erase(it); 426 | } 427 | } 428 | if (restrains.find((int)PIndex(p2, p3)) == restrains.end()) 429 | { 430 | vector::iterator it = std::find(es.begin(), es.end(), PIndex(p2, p3)); 431 | if (it == es.end()) 432 | { 433 | es.push_back(PIndex(p2, p3)); 434 | } 435 | else 436 | { 437 | es.erase(it); 438 | } 439 | } 440 | CreateTriangle(&eindexs, p1, p2, p3); 441 | if (es.empty()) 442 | break; 443 | // 得到新的两个点,循环计算。如果es为空。则说明已经遍历完,三角形网格化停止 444 | e = es.back(); 445 | es.pop_back(); 446 | int *points = edges[eindexs[e]].points; 447 | p1 = points[0], p2 = points[1]; 448 | } 449 | } 450 | 451 | #define distance(p1, p2) ((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y)) 452 | 453 | void Polygon::GenExtData() 454 | { 455 | for (unsigned i = 0; i < triangles.size(); i++) 456 | { 457 | Triangle t = triangles[i]; 458 | t.GenExtData(this); 459 | triangles[i] = t; 460 | } 461 | 462 | for (unsigned i = 0; i < edges.size(); i++) 463 | { 464 | Edge e = edges[i]; 465 | int e0 = e.triangles[0]; 466 | int e1 = e.triangles[1]; 467 | if (e0 >= 0 && e1 >= 0) // 一条边两个三角形的 468 | { 469 | Triangle t0 = triangles[e0]; 470 | int p0 = e.points[0], p1 = e.points[1]; 471 | 472 | // 使其在第一个三角中,让p1位于p0的右侧(点的位置固定起来,p0是左点,p1是右点),使寻路时拐点算法的两边方向都是一致的 473 | Point pp0 = GetPoint(p0) - t0.icenter; 474 | Point pp1 = GetPoint(p1) - t0.icenter; 475 | if (pp0.inLeft(pp1)) 476 | { 477 | e.points[0] = p1; 478 | e.points[1] = p0; 479 | edges[i] = e; 480 | } 481 | } 482 | } 483 | } 484 | 485 | vector Polygon::GetLines() 486 | { 487 | vector lines(edges.size()); 488 | for (unsigned i = 0; i < edges.size(); i++) 489 | { 490 | Line line; 491 | line.p1 = GetPoint(edges[i].points[0]); 492 | line.p2 = GetPoint(edges[i].points[1]); 493 | if (edges[i].IsRestrain(this)) 494 | { 495 | line.color[0] = 1.0; 496 | line.color[1] = 0.0; 497 | line.color[2] = 0.0; 498 | } 499 | else 500 | { 501 | line.color[0] = 0.0; 502 | line.color[1] = 1.0; 503 | line.color[2] = 0.0; 504 | } 505 | lines[i] = line; 506 | } 507 | return lines; 508 | } 509 | 510 | vector Polygon::GetGrideLines() 511 | { 512 | vector lines(grid.ynum + grid.xnum + 2); 513 | // 纵向的线 514 | for (int i = 0; i <= grid.xnum; i++) 515 | { 516 | Line line; 517 | Point pa1, pa2; 518 | double x = i * grid.gride_len + grid.minx; 519 | pa1.x = x; 520 | pa1.y = grid.miny; 521 | 522 | pa2.x = x; 523 | pa2.y = grid.miny + grid.ynum * grid.gride_len; 524 | line.p1 = pa1; 525 | line.p2 = pa2; 526 | 527 | line.color[0] = 0.2f; 528 | line.color[1] = 0.3f; 529 | line.color[2] = 0.3f; 530 | 531 | lines[i] = line; 532 | } 533 | // 横向的线 534 | for (int j = 0; j <= grid.ynum; j++) 535 | { 536 | Line line; 537 | Point pa1, pa2; 538 | double y = j * grid.gride_len + grid.miny; 539 | pa1.x = grid.minx; 540 | pa1.y = y; 541 | pa2.x = grid.minx + grid.xnum * grid.gride_len; 542 | pa2.y = y; 543 | line.p1 = pa1; 544 | line.p2 = pa2; 545 | 546 | line.color[0] = 0.2f; 547 | line.color[1] = 0.3f; 548 | line.color[2] = 0.3f; 549 | 550 | lines[j + grid.xnum + 1] = line; 551 | } 552 | return lines; 553 | } 554 | 555 | vector Polygon::GetCenters() 556 | { 557 | vector centers(triangles.size()); 558 | for (unsigned i = 0; i < triangles.size(); i++) 559 | { 560 | centers[i] = triangles[i].icenter; 561 | } 562 | return centers; 563 | } 564 | 565 | int Polygon::FindTriangle(Point p) 566 | { 567 | for (unsigned i = 0; i < triangles.size(); i++) 568 | { 569 | if (triangles[i].Contain(this, p)) 570 | return i; 571 | } 572 | return -1; 573 | } 574 | // 找路径 from是起点,to是终点 575 | vector Polygon::FindPath(Point from, Point to) 576 | { 577 | std::cout << "find path==========" << std::endl; 578 | int tfrom = FindTriangle(from); 579 | int tto = FindTriangle(to); 580 | 581 | vector ts; // 所有的三角形 582 | vector es; // 所有的经过的边,用于拐点算法 583 | vector ways; 584 | if (tfrom < 0) 585 | return ways; 586 | if (tto < 0) 587 | return ways; 588 | ways.push_back(from); 589 | if (tfrom == tto) 590 | { 591 | ways.push_back(to); 592 | return ways; 593 | } 594 | ts.push_back(tfrom); // 栈,存放三角形 595 | // A* F = G() + H() 变形的A*或者称为贪心算法的网格遍历 596 | // G() = 0 H() = 当前点到终点的距离 597 | int start = tfrom; 598 | Hash visited; 599 | visited.insert(make_pair(tfrom, 1)); 600 | 601 | while (!ts.empty()) 602 | { 603 | start = ts.back(); 604 | double weight = -1; 605 | int next = -1; 606 | int e; 607 | for (int i = 0; i < 3; i++) 608 | { 609 | int eindex = triangles[start].edges[i]; 610 | Edge edge = edges[eindex]; 611 | // 找到非约束边的,非原三角形的另外其他的三角形 612 | int nextt = edge.triangles[0] == start ? edge.triangles[1] : edge.triangles[0]; 613 | if (nextt >= 0) // 非约束边的,存在相邻三角形的 614 | { 615 | if (nextt == tto) 616 | { 617 | next = tto; 618 | e = eindex; 619 | break; 620 | } 621 | if (visited.find(nextt) == visited.end()) 622 | { 623 | Point p = triangles[nextt].icenter; 624 | double d = distance(p, to); 625 | if (next < 0 || weight > d) 626 | next = nextt, weight = d, e = eindex; 627 | } 628 | } 629 | } 630 | if (next == tto) 631 | { 632 | ts.push_back(next); 633 | es.push_back(e); 634 | break; 635 | } 636 | else if (next >= 0) 637 | { 638 | visited.insert(make_pair(next, 1)); 639 | ts.push_back(next); 640 | es.push_back(e); 641 | } 642 | else 643 | { // 没有路可走,再进行回溯然后继续查找,栈就具有这种回溯的功能 644 | ts.pop_back(); 645 | es.pop_back(); 646 | } 647 | } 648 | 649 | if (ts.empty()) 650 | return ways; 651 | 652 | for (int i = 0; i < triangles.size(); i++) 653 | { 654 | triangles[i].isPath = false; 655 | } 656 | for (int i : ts) 657 | { 658 | triangles[i].isPath = true; 659 | } 660 | 661 | // ===== 拐点算法 ===== 662 | // main variables: 663 | // e ep_l ep_r p_l p_r line_l line_r t t_l t_r 664 | // ne nep_l nep_r np_l np_r 665 | int t = 0; // 第几个穿出边 666 | int size = es.size(); 667 | while (t < size) // 每一次循环就是要找到一个拐点,然后下一次再从这个拐点找下一个拐点 668 | { 669 | Point p = ways.back(); 670 | Edge e = edges[es[t]]; 671 | int ep_r, ep_l; 672 | // ts[t]表示当前要处理的三角 673 | if (ts[t] == e.triangles[0]) // 判断是否是第0个三角,第0个三角p1是在p0左侧的 674 | { 675 | ep_r = e.points[1], ep_l = e.points[0]; 676 | } 677 | else 678 | { // 是第一个三角,p1在p0的右侧,需要换下顺序 679 | ep_r = e.points[0], ep_l = e.points[1]; 680 | } 681 | 682 | Point p_r = GetPoint(ep_r), p_l = GetPoint(ep_l); 683 | Point line_r = p_r - p, line_l = p_l - p; 684 | int i = t + 1; 685 | int t_r = i, t_l = i; 686 | // 每一次循环处理一个穿出边,直到找到一个拐点 687 | std::cout << "size = " << size << std::endl; 688 | for (; i < size; i++) 689 | { 690 | std::cout << "i = " << i << std::endl; 691 | Edge ne = edges[es[i]]; 692 | int nep_r, nep_l; 693 | if (ts[i] == ne.triangles[0]) 694 | { 695 | nep_r = ne.points[1], nep_l = ne.points[0]; 696 | } 697 | else 698 | { 699 | nep_r = ne.points[0], nep_l = ne.points[1]; 700 | } 701 | Point np_r = GetPoint(nep_r), np_l = GetPoint(nep_l); // np1是右点,np2是左点 702 | // 处理右线 703 | if (line_r.inRight(np_l - p) || line_r.inSame(np_l - p)) // 左点在*右线*的右侧,直接确定左点为拐点 704 | { 705 | std::cout << "左点在*右线*的右侧,直接确定左点为拐点" << std::endl; 706 | p = GetPoint(ep_r); 707 | ways.push_back(p); 708 | t_r++; 709 | t = nep_r == ep_r ? (i++, t_r + 1) : t_r; 710 | break; 711 | } 712 | else if (line_r.inLeft(np_r - p) || line_r.inSame(np_r - p)) // 右点在*右线*的左侧,更新右线 713 | { 714 | std::cout << "右点在*右线*的左侧,更新右线" << std::endl; 715 | line_r = np_r - p; 716 | ep_r = nep_r; 717 | t_r = i; 718 | } 719 | // 处理左线 720 | if (line_l.inLeft(np_r - p) || line_l.inSame(np_r - p)) // 右点在*左线*的左侧,直接确定拐点 721 | { 722 | std::cout << "右点在*左线*的左侧,直接确定右点为拐点" << std::endl; 723 | p = GetPoint(ep_l); 724 | ways.push_back(p); 725 | t_l++; 726 | t = nep_l == ep_l ? (i++, t_l + 1) : t_l; 727 | break; 728 | } 729 | else if (line_l.inRight(np_l - p) || line_l.inSame(np_l - p)) // 左点在*左线*的右侧,更新左线 730 | { 731 | std::cout << "左点在*左线*的右侧,更新左线" << std::endl; 732 | line_l = np_l - p; 733 | ep_l = nep_l; 734 | t_l = i; 735 | } 736 | } 737 | if (i >= size - 1) // 左线和右线一直更新更新到了最后 738 | { 739 | std::cout << "go in last deal" << std::endl; 740 | if (line_r.inRight(to - p) || line_r.inSame(to - p)) // 终点在line1(右线)右侧 741 | { 742 | std::cout << "go 1111111111" << std::endl; 743 | ways.push_back(GetPoint(ep_r)); // 左点为拐点 744 | t = t_r; 745 | } 746 | else if (line_l.inLeft(to - p) || line_l.inSame(to - p)) // 终点在line2(左线)左侧 747 | { 748 | std::cout << "go 222222222222" << std::endl; 749 | 750 | ways.push_back(GetPoint(ep_l)); 751 | t = t_l; 752 | } 753 | if (t >= size - 1) // //终点在中间 754 | { 755 | ways.push_back(to); 756 | } 757 | t++; 758 | } 759 | } 760 | 761 | return ways; 762 | } 763 | -------------------------------------------------------------------------------- /libs/freeglut_msvc/include/GL/freeglut_std.h: -------------------------------------------------------------------------------- 1 | #ifndef __FREEGLUT_STD_H__ 2 | #define __FREEGLUT_STD_H__ 3 | 4 | /* 5 | * freeglut_std.h 6 | * 7 | * The GLUT-compatible part of the freeglut library include file 8 | * 9 | * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. 10 | * Written by Pawel W. Olszta, 11 | * Creation date: Thu Dec 2 1999 12 | * 13 | * Permission is hereby granted, free of charge, to any person obtaining a 14 | * copy of this software and associated documentation files (the "Software"), 15 | * to deal in the Software without restriction, including without limitation 16 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 17 | * and/or sell copies of the Software, and to permit persons to whom the 18 | * Software is furnished to do so, subject to the following conditions: 19 | * 20 | * The above copyright notice and this permission notice shall be included 21 | * in all copies or substantial portions of the Software. 22 | * 23 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 24 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 26 | * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 27 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 28 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 29 | */ 30 | 31 | #ifdef __cplusplus 32 | extern "C" { 33 | #endif 34 | 35 | /* 36 | * Under windows, we have to differentiate between static and dynamic libraries 37 | */ 38 | #ifdef _WIN32 39 | /* #pragma may not be supported by some compilers. 40 | * Discussion by FreeGLUT developers suggests that 41 | * Visual C++ specific code involving pragmas may 42 | * need to move to a separate header. 24th Dec 2003 43 | */ 44 | 45 | /* Define FREEGLUT_LIB_PRAGMAS to 1 to include library 46 | * pragmas or to 0 to exclude library pragmas. 47 | * The default behavior depends on the compiler/platform. 48 | */ 49 | # ifndef FREEGLUT_LIB_PRAGMAS 50 | # if ( defined(_MSC_VER) || defined(__WATCOMC__) ) && !defined(_WIN32_WCE) 51 | # define FREEGLUT_LIB_PRAGMAS 1 52 | # else 53 | # define FREEGLUT_LIB_PRAGMAS 0 54 | # endif 55 | # endif 56 | 57 | # ifndef WIN32_LEAN_AND_MEAN 58 | # define WIN32_LEAN_AND_MEAN 1 59 | # endif 60 | # ifndef NOMINMAX 61 | # define NOMINMAX 62 | # endif 63 | # include 64 | 65 | /* Windows static library */ 66 | # ifdef FREEGLUT_STATIC 67 | 68 | #error Static linking is not supported with this build. Please remove the FREEGLUT_STATIC preprocessor directive, or download the source code from http://freeglut.sf.net/ and build against that. 69 | 70 | /* Windows shared library (DLL) */ 71 | # else 72 | 73 | # define FGAPIENTRY __stdcall 74 | # if defined(FREEGLUT_EXPORTS) 75 | # define FGAPI __declspec(dllexport) 76 | # else 77 | # define FGAPI __declspec(dllimport) 78 | 79 | /* Link with Win32 shared freeglut lib */ 80 | # if FREEGLUT_LIB_PRAGMAS 81 | # pragma comment (lib, "freeglut.lib") 82 | # endif 83 | 84 | # endif 85 | 86 | # endif 87 | 88 | /* Drag in other Windows libraries as required by FreeGLUT */ 89 | # if FREEGLUT_LIB_PRAGMAS 90 | # pragma comment (lib, "glu32.lib") /* link OpenGL Utility lib */ 91 | # pragma comment (lib, "opengl32.lib") /* link Microsoft OpenGL lib */ 92 | # pragma comment (lib, "gdi32.lib") /* link Windows GDI lib */ 93 | # pragma comment (lib, "winmm.lib") /* link Windows MultiMedia lib */ 94 | # pragma comment (lib, "user32.lib") /* link Windows user lib */ 95 | # endif 96 | 97 | #else 98 | 99 | /* Non-Windows definition of FGAPI and FGAPIENTRY */ 100 | # define FGAPI 101 | # define FGAPIENTRY 102 | 103 | #endif 104 | 105 | /* 106 | * The freeglut and GLUT API versions 107 | */ 108 | #define FREEGLUT 1 109 | #define GLUT_API_VERSION 4 110 | #define GLUT_XLIB_IMPLEMENTATION 13 111 | /* Deprecated: 112 | cf. http://sourceforge.net/mailarchive/forum.php?thread_name=CABcAi1hw7cr4xtigckaGXB5X8wddLfMcbA_rZ3NAuwMrX_zmsw%40mail.gmail.com&forum_name=freeglut-developer */ 113 | #define FREEGLUT_VERSION_2_0 1 114 | 115 | /* 116 | * Always include OpenGL and GLU headers 117 | */ 118 | /* Note: FREEGLUT_GLES is only used to cleanly bootstrap headers 119 | inclusion here; use GLES constants directly 120 | (e.g. GL_ES_VERSION_2_0) for all other needs */ 121 | #ifdef FREEGLUT_GLES 122 | # include 123 | # include 124 | # include 125 | #elif __APPLE__ 126 | # include 127 | # include 128 | #else 129 | # include 130 | # include 131 | #endif 132 | 133 | /* 134 | * GLUT API macro definitions -- the special key codes: 135 | */ 136 | #define GLUT_KEY_F1 0x0001 137 | #define GLUT_KEY_F2 0x0002 138 | #define GLUT_KEY_F3 0x0003 139 | #define GLUT_KEY_F4 0x0004 140 | #define GLUT_KEY_F5 0x0005 141 | #define GLUT_KEY_F6 0x0006 142 | #define GLUT_KEY_F7 0x0007 143 | #define GLUT_KEY_F8 0x0008 144 | #define GLUT_KEY_F9 0x0009 145 | #define GLUT_KEY_F10 0x000A 146 | #define GLUT_KEY_F11 0x000B 147 | #define GLUT_KEY_F12 0x000C 148 | #define GLUT_KEY_LEFT 0x0064 149 | #define GLUT_KEY_UP 0x0065 150 | #define GLUT_KEY_RIGHT 0x0066 151 | #define GLUT_KEY_DOWN 0x0067 152 | #define GLUT_KEY_PAGE_UP 0x0068 153 | #define GLUT_KEY_PAGE_DOWN 0x0069 154 | #define GLUT_KEY_HOME 0x006A 155 | #define GLUT_KEY_END 0x006B 156 | #define GLUT_KEY_INSERT 0x006C 157 | 158 | /* 159 | * GLUT API macro definitions -- mouse state definitions 160 | */ 161 | #define GLUT_LEFT_BUTTON 0x0000 162 | #define GLUT_MIDDLE_BUTTON 0x0001 163 | #define GLUT_RIGHT_BUTTON 0x0002 164 | #define GLUT_DOWN 0x0000 165 | #define GLUT_UP 0x0001 166 | #define GLUT_LEFT 0x0000 167 | #define GLUT_ENTERED 0x0001 168 | 169 | /* 170 | * GLUT API macro definitions -- the display mode definitions 171 | */ 172 | #define GLUT_RGB 0x0000 173 | #define GLUT_RGBA 0x0000 174 | #define GLUT_INDEX 0x0001 175 | #define GLUT_SINGLE 0x0000 176 | #define GLUT_DOUBLE 0x0002 177 | #define GLUT_ACCUM 0x0004 178 | #define GLUT_ALPHA 0x0008 179 | #define GLUT_DEPTH 0x0010 180 | #define GLUT_STENCIL 0x0020 181 | #define GLUT_MULTISAMPLE 0x0080 182 | #define GLUT_STEREO 0x0100 183 | #define GLUT_LUMINANCE 0x0200 184 | 185 | /* 186 | * GLUT API macro definitions -- windows and menu related definitions 187 | */ 188 | #define GLUT_MENU_NOT_IN_USE 0x0000 189 | #define GLUT_MENU_IN_USE 0x0001 190 | #define GLUT_NOT_VISIBLE 0x0000 191 | #define GLUT_VISIBLE 0x0001 192 | #define GLUT_HIDDEN 0x0000 193 | #define GLUT_FULLY_RETAINED 0x0001 194 | #define GLUT_PARTIALLY_RETAINED 0x0002 195 | #define GLUT_FULLY_COVERED 0x0003 196 | 197 | /* 198 | * GLUT API macro definitions -- fonts definitions 199 | * 200 | * Steve Baker suggested to make it binary compatible with GLUT: 201 | */ 202 | #if defined(_MSC_VER) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__WATCOMC__) 203 | # define GLUT_STROKE_ROMAN ((void *)0x0000) 204 | # define GLUT_STROKE_MONO_ROMAN ((void *)0x0001) 205 | # define GLUT_BITMAP_9_BY_15 ((void *)0x0002) 206 | # define GLUT_BITMAP_8_BY_13 ((void *)0x0003) 207 | # define GLUT_BITMAP_TIMES_ROMAN_10 ((void *)0x0004) 208 | # define GLUT_BITMAP_TIMES_ROMAN_24 ((void *)0x0005) 209 | # define GLUT_BITMAP_HELVETICA_10 ((void *)0x0006) 210 | # define GLUT_BITMAP_HELVETICA_12 ((void *)0x0007) 211 | # define GLUT_BITMAP_HELVETICA_18 ((void *)0x0008) 212 | #else 213 | /* 214 | * I don't really know if it's a good idea... But here it goes: 215 | */ 216 | extern void* glutStrokeRoman; 217 | extern void* glutStrokeMonoRoman; 218 | extern void* glutBitmap9By15; 219 | extern void* glutBitmap8By13; 220 | extern void* glutBitmapTimesRoman10; 221 | extern void* glutBitmapTimesRoman24; 222 | extern void* glutBitmapHelvetica10; 223 | extern void* glutBitmapHelvetica12; 224 | extern void* glutBitmapHelvetica18; 225 | 226 | /* 227 | * Those pointers will be used by following definitions: 228 | */ 229 | # define GLUT_STROKE_ROMAN ((void *) &glutStrokeRoman) 230 | # define GLUT_STROKE_MONO_ROMAN ((void *) &glutStrokeMonoRoman) 231 | # define GLUT_BITMAP_9_BY_15 ((void *) &glutBitmap9By15) 232 | # define GLUT_BITMAP_8_BY_13 ((void *) &glutBitmap8By13) 233 | # define GLUT_BITMAP_TIMES_ROMAN_10 ((void *) &glutBitmapTimesRoman10) 234 | # define GLUT_BITMAP_TIMES_ROMAN_24 ((void *) &glutBitmapTimesRoman24) 235 | # define GLUT_BITMAP_HELVETICA_10 ((void *) &glutBitmapHelvetica10) 236 | # define GLUT_BITMAP_HELVETICA_12 ((void *) &glutBitmapHelvetica12) 237 | # define GLUT_BITMAP_HELVETICA_18 ((void *) &glutBitmapHelvetica18) 238 | #endif 239 | 240 | /* 241 | * GLUT API macro definitions -- the glutGet parameters 242 | */ 243 | #define GLUT_WINDOW_X 0x0064 244 | #define GLUT_WINDOW_Y 0x0065 245 | #define GLUT_WINDOW_WIDTH 0x0066 246 | #define GLUT_WINDOW_HEIGHT 0x0067 247 | #define GLUT_WINDOW_BUFFER_SIZE 0x0068 248 | #define GLUT_WINDOW_STENCIL_SIZE 0x0069 249 | #define GLUT_WINDOW_DEPTH_SIZE 0x006A 250 | #define GLUT_WINDOW_RED_SIZE 0x006B 251 | #define GLUT_WINDOW_GREEN_SIZE 0x006C 252 | #define GLUT_WINDOW_BLUE_SIZE 0x006D 253 | #define GLUT_WINDOW_ALPHA_SIZE 0x006E 254 | #define GLUT_WINDOW_ACCUM_RED_SIZE 0x006F 255 | #define GLUT_WINDOW_ACCUM_GREEN_SIZE 0x0070 256 | #define GLUT_WINDOW_ACCUM_BLUE_SIZE 0x0071 257 | #define GLUT_WINDOW_ACCUM_ALPHA_SIZE 0x0072 258 | #define GLUT_WINDOW_DOUBLEBUFFER 0x0073 259 | #define GLUT_WINDOW_RGBA 0x0074 260 | #define GLUT_WINDOW_PARENT 0x0075 261 | #define GLUT_WINDOW_NUM_CHILDREN 0x0076 262 | #define GLUT_WINDOW_COLORMAP_SIZE 0x0077 263 | #define GLUT_WINDOW_NUM_SAMPLES 0x0078 264 | #define GLUT_WINDOW_STEREO 0x0079 265 | #define GLUT_WINDOW_CURSOR 0x007A 266 | 267 | #define GLUT_SCREEN_WIDTH 0x00C8 268 | #define GLUT_SCREEN_HEIGHT 0x00C9 269 | #define GLUT_SCREEN_WIDTH_MM 0x00CA 270 | #define GLUT_SCREEN_HEIGHT_MM 0x00CB 271 | #define GLUT_MENU_NUM_ITEMS 0x012C 272 | #define GLUT_DISPLAY_MODE_POSSIBLE 0x0190 273 | #define GLUT_INIT_WINDOW_X 0x01F4 274 | #define GLUT_INIT_WINDOW_Y 0x01F5 275 | #define GLUT_INIT_WINDOW_WIDTH 0x01F6 276 | #define GLUT_INIT_WINDOW_HEIGHT 0x01F7 277 | #define GLUT_INIT_DISPLAY_MODE 0x01F8 278 | #define GLUT_ELAPSED_TIME 0x02BC 279 | #define GLUT_WINDOW_FORMAT_ID 0x007B 280 | 281 | /* 282 | * GLUT API macro definitions -- the glutDeviceGet parameters 283 | */ 284 | #define GLUT_HAS_KEYBOARD 0x0258 285 | #define GLUT_HAS_MOUSE 0x0259 286 | #define GLUT_HAS_SPACEBALL 0x025A 287 | #define GLUT_HAS_DIAL_AND_BUTTON_BOX 0x025B 288 | #define GLUT_HAS_TABLET 0x025C 289 | #define GLUT_NUM_MOUSE_BUTTONS 0x025D 290 | #define GLUT_NUM_SPACEBALL_BUTTONS 0x025E 291 | #define GLUT_NUM_BUTTON_BOX_BUTTONS 0x025F 292 | #define GLUT_NUM_DIALS 0x0260 293 | #define GLUT_NUM_TABLET_BUTTONS 0x0261 294 | #define GLUT_DEVICE_IGNORE_KEY_REPEAT 0x0262 295 | #define GLUT_DEVICE_KEY_REPEAT 0x0263 296 | #define GLUT_HAS_JOYSTICK 0x0264 297 | #define GLUT_OWNS_JOYSTICK 0x0265 298 | #define GLUT_JOYSTICK_BUTTONS 0x0266 299 | #define GLUT_JOYSTICK_AXES 0x0267 300 | #define GLUT_JOYSTICK_POLL_RATE 0x0268 301 | 302 | /* 303 | * GLUT API macro definitions -- the glutLayerGet parameters 304 | */ 305 | #define GLUT_OVERLAY_POSSIBLE 0x0320 306 | #define GLUT_LAYER_IN_USE 0x0321 307 | #define GLUT_HAS_OVERLAY 0x0322 308 | #define GLUT_TRANSPARENT_INDEX 0x0323 309 | #define GLUT_NORMAL_DAMAGED 0x0324 310 | #define GLUT_OVERLAY_DAMAGED 0x0325 311 | 312 | /* 313 | * GLUT API macro definitions -- the glutVideoResizeGet parameters 314 | */ 315 | #define GLUT_VIDEO_RESIZE_POSSIBLE 0x0384 316 | #define GLUT_VIDEO_RESIZE_IN_USE 0x0385 317 | #define GLUT_VIDEO_RESIZE_X_DELTA 0x0386 318 | #define GLUT_VIDEO_RESIZE_Y_DELTA 0x0387 319 | #define GLUT_VIDEO_RESIZE_WIDTH_DELTA 0x0388 320 | #define GLUT_VIDEO_RESIZE_HEIGHT_DELTA 0x0389 321 | #define GLUT_VIDEO_RESIZE_X 0x038A 322 | #define GLUT_VIDEO_RESIZE_Y 0x038B 323 | #define GLUT_VIDEO_RESIZE_WIDTH 0x038C 324 | #define GLUT_VIDEO_RESIZE_HEIGHT 0x038D 325 | 326 | /* 327 | * GLUT API macro definitions -- the glutUseLayer parameters 328 | */ 329 | #define GLUT_NORMAL 0x0000 330 | #define GLUT_OVERLAY 0x0001 331 | 332 | /* 333 | * GLUT API macro definitions -- the glutGetModifiers parameters 334 | */ 335 | #define GLUT_ACTIVE_SHIFT 0x0001 336 | #define GLUT_ACTIVE_CTRL 0x0002 337 | #define GLUT_ACTIVE_ALT 0x0004 338 | 339 | /* 340 | * GLUT API macro definitions -- the glutSetCursor parameters 341 | */ 342 | #define GLUT_CURSOR_RIGHT_ARROW 0x0000 343 | #define GLUT_CURSOR_LEFT_ARROW 0x0001 344 | #define GLUT_CURSOR_INFO 0x0002 345 | #define GLUT_CURSOR_DESTROY 0x0003 346 | #define GLUT_CURSOR_HELP 0x0004 347 | #define GLUT_CURSOR_CYCLE 0x0005 348 | #define GLUT_CURSOR_SPRAY 0x0006 349 | #define GLUT_CURSOR_WAIT 0x0007 350 | #define GLUT_CURSOR_TEXT 0x0008 351 | #define GLUT_CURSOR_CROSSHAIR 0x0009 352 | #define GLUT_CURSOR_UP_DOWN 0x000A 353 | #define GLUT_CURSOR_LEFT_RIGHT 0x000B 354 | #define GLUT_CURSOR_TOP_SIDE 0x000C 355 | #define GLUT_CURSOR_BOTTOM_SIDE 0x000D 356 | #define GLUT_CURSOR_LEFT_SIDE 0x000E 357 | #define GLUT_CURSOR_RIGHT_SIDE 0x000F 358 | #define GLUT_CURSOR_TOP_LEFT_CORNER 0x0010 359 | #define GLUT_CURSOR_TOP_RIGHT_CORNER 0x0011 360 | #define GLUT_CURSOR_BOTTOM_RIGHT_CORNER 0x0012 361 | #define GLUT_CURSOR_BOTTOM_LEFT_CORNER 0x0013 362 | #define GLUT_CURSOR_INHERIT 0x0064 363 | #define GLUT_CURSOR_NONE 0x0065 364 | #define GLUT_CURSOR_FULL_CROSSHAIR 0x0066 365 | 366 | /* 367 | * GLUT API macro definitions -- RGB color component specification definitions 368 | */ 369 | #define GLUT_RED 0x0000 370 | #define GLUT_GREEN 0x0001 371 | #define GLUT_BLUE 0x0002 372 | 373 | /* 374 | * GLUT API macro definitions -- additional keyboard and joystick definitions 375 | */ 376 | #define GLUT_KEY_REPEAT_OFF 0x0000 377 | #define GLUT_KEY_REPEAT_ON 0x0001 378 | #define GLUT_KEY_REPEAT_DEFAULT 0x0002 379 | 380 | #define GLUT_JOYSTICK_BUTTON_A 0x0001 381 | #define GLUT_JOYSTICK_BUTTON_B 0x0002 382 | #define GLUT_JOYSTICK_BUTTON_C 0x0004 383 | #define GLUT_JOYSTICK_BUTTON_D 0x0008 384 | 385 | /* 386 | * GLUT API macro definitions -- game mode definitions 387 | */ 388 | #define GLUT_GAME_MODE_ACTIVE 0x0000 389 | #define GLUT_GAME_MODE_POSSIBLE 0x0001 390 | #define GLUT_GAME_MODE_WIDTH 0x0002 391 | #define GLUT_GAME_MODE_HEIGHT 0x0003 392 | #define GLUT_GAME_MODE_PIXEL_DEPTH 0x0004 393 | #define GLUT_GAME_MODE_REFRESH_RATE 0x0005 394 | #define GLUT_GAME_MODE_DISPLAY_CHANGED 0x0006 395 | 396 | /* 397 | * Initialization functions, see fglut_init.c 398 | */ 399 | FGAPI void FGAPIENTRY glutInit( int* pargc, char** argv ); 400 | FGAPI void FGAPIENTRY glutInitWindowPosition( int x, int y ); 401 | FGAPI void FGAPIENTRY glutInitWindowSize( int width, int height ); 402 | FGAPI void FGAPIENTRY glutInitDisplayMode( unsigned int displayMode ); 403 | FGAPI void FGAPIENTRY glutInitDisplayString( const char* displayMode ); 404 | 405 | /* 406 | * Process loop function, see fg_main.c 407 | */ 408 | FGAPI void FGAPIENTRY glutMainLoop( void ); 409 | 410 | /* 411 | * Window management functions, see fg_window.c 412 | */ 413 | FGAPI int FGAPIENTRY glutCreateWindow( const char* title ); 414 | FGAPI int FGAPIENTRY glutCreateSubWindow( int window, int x, int y, int width, int height ); 415 | FGAPI void FGAPIENTRY glutDestroyWindow( int window ); 416 | FGAPI void FGAPIENTRY glutSetWindow( int window ); 417 | FGAPI int FGAPIENTRY glutGetWindow( void ); 418 | FGAPI void FGAPIENTRY glutSetWindowTitle( const char* title ); 419 | FGAPI void FGAPIENTRY glutSetIconTitle( const char* title ); 420 | FGAPI void FGAPIENTRY glutReshapeWindow( int width, int height ); 421 | FGAPI void FGAPIENTRY glutPositionWindow( int x, int y ); 422 | FGAPI void FGAPIENTRY glutShowWindow( void ); 423 | FGAPI void FGAPIENTRY glutHideWindow( void ); 424 | FGAPI void FGAPIENTRY glutIconifyWindow( void ); 425 | FGAPI void FGAPIENTRY glutPushWindow( void ); 426 | FGAPI void FGAPIENTRY glutPopWindow( void ); 427 | FGAPI void FGAPIENTRY glutFullScreen( void ); 428 | 429 | /* 430 | * Display-related functions, see fg_display.c 431 | */ 432 | FGAPI void FGAPIENTRY glutPostWindowRedisplay( int window ); 433 | FGAPI void FGAPIENTRY glutPostRedisplay( void ); 434 | FGAPI void FGAPIENTRY glutSwapBuffers( void ); 435 | 436 | /* 437 | * Mouse cursor functions, see fg_cursor.c 438 | */ 439 | FGAPI void FGAPIENTRY glutWarpPointer( int x, int y ); 440 | FGAPI void FGAPIENTRY glutSetCursor( int cursor ); 441 | 442 | /* 443 | * Overlay stuff, see fg_overlay.c 444 | */ 445 | FGAPI void FGAPIENTRY glutEstablishOverlay( void ); 446 | FGAPI void FGAPIENTRY glutRemoveOverlay( void ); 447 | FGAPI void FGAPIENTRY glutUseLayer( GLenum layer ); 448 | FGAPI void FGAPIENTRY glutPostOverlayRedisplay( void ); 449 | FGAPI void FGAPIENTRY glutPostWindowOverlayRedisplay( int window ); 450 | FGAPI void FGAPIENTRY glutShowOverlay( void ); 451 | FGAPI void FGAPIENTRY glutHideOverlay( void ); 452 | 453 | /* 454 | * Menu stuff, see fg_menu.c 455 | */ 456 | FGAPI int FGAPIENTRY glutCreateMenu( void (* callback)( int menu ) ); 457 | FGAPI void FGAPIENTRY glutDestroyMenu( int menu ); 458 | FGAPI int FGAPIENTRY glutGetMenu( void ); 459 | FGAPI void FGAPIENTRY glutSetMenu( int menu ); 460 | FGAPI void FGAPIENTRY glutAddMenuEntry( const char* label, int value ); 461 | FGAPI void FGAPIENTRY glutAddSubMenu( const char* label, int subMenu ); 462 | FGAPI void FGAPIENTRY glutChangeToMenuEntry( int item, const char* label, int value ); 463 | FGAPI void FGAPIENTRY glutChangeToSubMenu( int item, const char* label, int value ); 464 | FGAPI void FGAPIENTRY glutRemoveMenuItem( int item ); 465 | FGAPI void FGAPIENTRY glutAttachMenu( int button ); 466 | FGAPI void FGAPIENTRY glutDetachMenu( int button ); 467 | 468 | /* 469 | * Global callback functions, see fg_callbacks.c 470 | */ 471 | FGAPI void FGAPIENTRY glutTimerFunc( unsigned int time, void (* callback)( int ), int value ); 472 | FGAPI void FGAPIENTRY glutIdleFunc( void (* callback)( void ) ); 473 | 474 | /* 475 | * Window-specific callback functions, see fg_callbacks.c 476 | */ 477 | FGAPI void FGAPIENTRY glutKeyboardFunc( void (* callback)( unsigned char, int, int ) ); 478 | FGAPI void FGAPIENTRY glutSpecialFunc( void (* callback)( int, int, int ) ); 479 | FGAPI void FGAPIENTRY glutReshapeFunc( void (* callback)( int, int ) ); 480 | FGAPI void FGAPIENTRY glutVisibilityFunc( void (* callback)( int ) ); 481 | FGAPI void FGAPIENTRY glutDisplayFunc( void (* callback)( void ) ); 482 | FGAPI void FGAPIENTRY glutMouseFunc( void (* callback)( int, int, int, int ) ); 483 | FGAPI void FGAPIENTRY glutMotionFunc( void (* callback)( int, int ) ); 484 | FGAPI void FGAPIENTRY glutPassiveMotionFunc( void (* callback)( int, int ) ); 485 | FGAPI void FGAPIENTRY glutEntryFunc( void (* callback)( int ) ); 486 | 487 | FGAPI void FGAPIENTRY glutKeyboardUpFunc( void (* callback)( unsigned char, int, int ) ); 488 | FGAPI void FGAPIENTRY glutSpecialUpFunc( void (* callback)( int, int, int ) ); 489 | FGAPI void FGAPIENTRY glutJoystickFunc( void (* callback)( unsigned int, int, int, int ), int pollInterval ); 490 | FGAPI void FGAPIENTRY glutMenuStateFunc( void (* callback)( int ) ); 491 | FGAPI void FGAPIENTRY glutMenuStatusFunc( void (* callback)( int, int, int ) ); 492 | FGAPI void FGAPIENTRY glutOverlayDisplayFunc( void (* callback)( void ) ); 493 | FGAPI void FGAPIENTRY glutWindowStatusFunc( void (* callback)( int ) ); 494 | 495 | FGAPI void FGAPIENTRY glutSpaceballMotionFunc( void (* callback)( int, int, int ) ); 496 | FGAPI void FGAPIENTRY glutSpaceballRotateFunc( void (* callback)( int, int, int ) ); 497 | FGAPI void FGAPIENTRY glutSpaceballButtonFunc( void (* callback)( int, int ) ); 498 | FGAPI void FGAPIENTRY glutButtonBoxFunc( void (* callback)( int, int ) ); 499 | FGAPI void FGAPIENTRY glutDialsFunc( void (* callback)( int, int ) ); 500 | FGAPI void FGAPIENTRY glutTabletMotionFunc( void (* callback)( int, int ) ); 501 | FGAPI void FGAPIENTRY glutTabletButtonFunc( void (* callback)( int, int, int, int ) ); 502 | 503 | /* 504 | * State setting and retrieval functions, see fg_state.c 505 | */ 506 | FGAPI int FGAPIENTRY glutGet( GLenum query ); 507 | FGAPI int FGAPIENTRY glutDeviceGet( GLenum query ); 508 | FGAPI int FGAPIENTRY glutGetModifiers( void ); 509 | FGAPI int FGAPIENTRY glutLayerGet( GLenum query ); 510 | 511 | /* 512 | * Font stuff, see fg_font.c 513 | */ 514 | FGAPI void FGAPIENTRY glutBitmapCharacter( void* font, int character ); 515 | FGAPI int FGAPIENTRY glutBitmapWidth( void* font, int character ); 516 | FGAPI void FGAPIENTRY glutStrokeCharacter( void* font, int character ); 517 | FGAPI int FGAPIENTRY glutStrokeWidth( void* font, int character ); 518 | FGAPI GLfloat FGAPIENTRY glutStrokeWidthf( void* font, int character ); /* GLUT 3.8 */ 519 | FGAPI int FGAPIENTRY glutBitmapLength( void* font, const unsigned char* string ); 520 | FGAPI int FGAPIENTRY glutStrokeLength( void* font, const unsigned char* string ); 521 | FGAPI GLfloat FGAPIENTRY glutStrokeLengthf( void* font, const unsigned char *string ); /* GLUT 3.8 */ 522 | 523 | /* 524 | * Geometry functions, see fg_geometry.c 525 | */ 526 | 527 | FGAPI void FGAPIENTRY glutWireCube( double size ); 528 | FGAPI void FGAPIENTRY glutSolidCube( double size ); 529 | FGAPI void FGAPIENTRY glutWireSphere( double radius, GLint slices, GLint stacks ); 530 | FGAPI void FGAPIENTRY glutSolidSphere( double radius, GLint slices, GLint stacks ); 531 | FGAPI void FGAPIENTRY glutWireCone( double base, double height, GLint slices, GLint stacks ); 532 | FGAPI void FGAPIENTRY glutSolidCone( double base, double height, GLint slices, GLint stacks ); 533 | FGAPI void FGAPIENTRY glutWireTorus( double innerRadius, double outerRadius, GLint sides, GLint rings ); 534 | FGAPI void FGAPIENTRY glutSolidTorus( double innerRadius, double outerRadius, GLint sides, GLint rings ); 535 | FGAPI void FGAPIENTRY glutWireDodecahedron( void ); 536 | FGAPI void FGAPIENTRY glutSolidDodecahedron( void ); 537 | FGAPI void FGAPIENTRY glutWireOctahedron( void ); 538 | FGAPI void FGAPIENTRY glutSolidOctahedron( void ); 539 | FGAPI void FGAPIENTRY glutWireTetrahedron( void ); 540 | FGAPI void FGAPIENTRY glutSolidTetrahedron( void ); 541 | FGAPI void FGAPIENTRY glutWireIcosahedron( void ); 542 | FGAPI void FGAPIENTRY glutSolidIcosahedron( void ); 543 | 544 | /* 545 | * Teapot rendering functions, found in fg_teapot.c 546 | * NB: front facing polygons have clockwise winding, not counter clockwise 547 | */ 548 | FGAPI void FGAPIENTRY glutWireTeapot( double size ); 549 | FGAPI void FGAPIENTRY glutSolidTeapot( double size ); 550 | 551 | /* 552 | * Game mode functions, see fg_gamemode.c 553 | */ 554 | FGAPI void FGAPIENTRY glutGameModeString( const char* string ); 555 | FGAPI int FGAPIENTRY glutEnterGameMode( void ); 556 | FGAPI void FGAPIENTRY glutLeaveGameMode( void ); 557 | FGAPI int FGAPIENTRY glutGameModeGet( GLenum query ); 558 | 559 | /* 560 | * Video resize functions, see fg_videoresize.c 561 | */ 562 | FGAPI int FGAPIENTRY glutVideoResizeGet( GLenum query ); 563 | FGAPI void FGAPIENTRY glutSetupVideoResizing( void ); 564 | FGAPI void FGAPIENTRY glutStopVideoResizing( void ); 565 | FGAPI void FGAPIENTRY glutVideoResize( int x, int y, int width, int height ); 566 | FGAPI void FGAPIENTRY glutVideoPan( int x, int y, int width, int height ); 567 | 568 | /* 569 | * Colormap functions, see fg_misc.c 570 | */ 571 | FGAPI void FGAPIENTRY glutSetColor( int color, GLfloat red, GLfloat green, GLfloat blue ); 572 | FGAPI GLfloat FGAPIENTRY glutGetColor( int color, int component ); 573 | FGAPI void FGAPIENTRY glutCopyColormap( int window ); 574 | 575 | /* 576 | * Misc keyboard and joystick functions, see fg_misc.c 577 | */ 578 | FGAPI void FGAPIENTRY glutIgnoreKeyRepeat( int ignore ); 579 | FGAPI void FGAPIENTRY glutSetKeyRepeat( int repeatMode ); 580 | FGAPI void FGAPIENTRY glutForceJoystickFunc( void ); 581 | 582 | /* 583 | * Misc functions, see fg_misc.c 584 | */ 585 | FGAPI int FGAPIENTRY glutExtensionSupported( const char* extension ); 586 | FGAPI void FGAPIENTRY glutReportErrors( void ); 587 | 588 | /* Comment from glut.h of classic GLUT: 589 | 590 | Win32 has an annoying issue where there are multiple C run-time 591 | libraries (CRTs). If the executable is linked with a different CRT 592 | from the GLUT DLL, the GLUT DLL will not share the same CRT static 593 | data seen by the executable. In particular, atexit callbacks registered 594 | in the executable will not be called if GLUT calls its (different) 595 | exit routine). GLUT is typically built with the 596 | "/MD" option (the CRT with multithreading DLL support), but the Visual 597 | C++ linker default is "/ML" (the single threaded CRT). 598 | 599 | One workaround to this issue is requiring users to always link with 600 | the same CRT as GLUT is compiled with. That requires users supply a 601 | non-standard option. GLUT 3.7 has its own built-in workaround where 602 | the executable's "exit" function pointer is covertly passed to GLUT. 603 | GLUT then calls the executable's exit function pointer to ensure that 604 | any "atexit" calls registered by the application are called if GLUT 605 | needs to exit. 606 | 607 | Note that the __glut*WithExit routines should NEVER be called directly. 608 | To avoid the atexit workaround, #define GLUT_DISABLE_ATEXIT_HACK. */ 609 | 610 | /* to get the prototype for exit() */ 611 | #include 612 | 613 | #if defined(_WIN32) && !defined(GLUT_DISABLE_ATEXIT_HACK) && !defined(__WATCOMC__) 614 | FGAPI void FGAPIENTRY __glutInitWithExit(int *argcp, char **argv, void (__cdecl *exitfunc)(int)); 615 | FGAPI int FGAPIENTRY __glutCreateWindowWithExit(const char *title, void (__cdecl *exitfunc)(int)); 616 | FGAPI int FGAPIENTRY __glutCreateMenuWithExit(void (* func)(int), void (__cdecl *exitfunc)(int)); 617 | #ifndef FREEGLUT_BUILDING_LIB 618 | #if defined(__GNUC__) 619 | #define FGUNUSED __attribute__((unused)) 620 | #else 621 | #define FGUNUSED 622 | #endif 623 | static void FGAPIENTRY FGUNUSED glutInit_ATEXIT_HACK(int *argcp, char **argv) { __glutInitWithExit(argcp, argv, exit); } 624 | #define glutInit glutInit_ATEXIT_HACK 625 | static int FGAPIENTRY FGUNUSED glutCreateWindow_ATEXIT_HACK(const char *title) { return __glutCreateWindowWithExit(title, exit); } 626 | #define glutCreateWindow glutCreateWindow_ATEXIT_HACK 627 | static int FGAPIENTRY FGUNUSED glutCreateMenu_ATEXIT_HACK(void (* func)(int)) { return __glutCreateMenuWithExit(func, exit); } 628 | #define glutCreateMenu glutCreateMenu_ATEXIT_HACK 629 | #endif 630 | #endif 631 | 632 | #ifdef __cplusplus 633 | } 634 | #endif 635 | 636 | /*** END OF FILE ***/ 637 | 638 | #endif /* __FREEGLUT_STD_H__ */ 639 | -------------------------------------------------------------------------------- /libs/freeglut_mingw/include/GL/freeglut_std.h: -------------------------------------------------------------------------------- 1 | #ifndef __FREEGLUT_STD_H__ 2 | #define __FREEGLUT_STD_H__ 3 | 4 | /* 5 | * freeglut_std.h 6 | * 7 | * The GLUT-compatible part of the freeglut library include file 8 | * 9 | * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. 10 | * Written by Pawel W. Olszta, 11 | * Creation date: Thu Dec 2 1999 12 | * 13 | * Permission is hereby granted, free of charge, to any person obtaining a 14 | * copy of this software and associated documentation files (the "Software"), 15 | * to deal in the Software without restriction, including without limitation 16 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 17 | * and/or sell copies of the Software, and to permit persons to whom the 18 | * Software is furnished to do so, subject to the following conditions: 19 | * 20 | * The above copyright notice and this permission notice shall be included 21 | * in all copies or substantial portions of the Software. 22 | * 23 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 24 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 26 | * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 27 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 28 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 29 | */ 30 | 31 | #ifdef __cplusplus 32 | extern "C" { 33 | #endif 34 | 35 | /* 36 | * Under windows, we have to differentiate between static and dynamic libraries 37 | */ 38 | #ifdef _WIN32 39 | /* #pragma may not be supported by some compilers. 40 | * Discussion by FreeGLUT developers suggests that 41 | * Visual C++ specific code involving pragmas may 42 | * need to move to a separate header. 24th Dec 2003 43 | */ 44 | 45 | /* Define FREEGLUT_LIB_PRAGMAS to 1 to include library 46 | * pragmas or to 0 to exclude library pragmas. 47 | * The default behavior depends on the compiler/platform. 48 | */ 49 | # ifndef FREEGLUT_LIB_PRAGMAS 50 | # if ( defined(_MSC_VER) || defined(__WATCOMC__) ) && !defined(_WIN32_WCE) 51 | # define FREEGLUT_LIB_PRAGMAS 1 52 | # else 53 | # define FREEGLUT_LIB_PRAGMAS 0 54 | # endif 55 | # endif 56 | 57 | # ifndef WIN32_LEAN_AND_MEAN 58 | # define WIN32_LEAN_AND_MEAN 1 59 | # endif 60 | # ifndef NOMINMAX 61 | # define NOMINMAX 62 | # endif 63 | # include 64 | 65 | /* Windows static library */ 66 | # ifdef FREEGLUT_STATIC 67 | 68 | # define FGAPI 69 | # define FGAPIENTRY 70 | 71 | /* Link with Win32 static freeglut lib */ 72 | # if FREEGLUT_LIB_PRAGMAS 73 | # ifdef NDEBUG 74 | # pragma comment (lib, "freeglut_static.lib") 75 | # else 76 | # pragma comment (lib, "freeglut_staticd.lib") 77 | # endif 78 | # endif 79 | 80 | /* Windows shared library (DLL) */ 81 | # else 82 | 83 | # define FGAPIENTRY __stdcall 84 | # if defined(FREEGLUT_EXPORTS) 85 | # define FGAPI __declspec(dllexport) 86 | # else 87 | # define FGAPI __declspec(dllimport) 88 | 89 | /* Link with Win32 shared freeglut lib */ 90 | # if FREEGLUT_LIB_PRAGMAS 91 | # ifdef NDEBUG 92 | # pragma comment (lib, "freeglut.lib") 93 | # else 94 | # pragma comment (lib, "freeglutd.lib") 95 | # endif 96 | # endif 97 | 98 | # endif 99 | 100 | # endif 101 | 102 | /* Drag in other Windows libraries as required by FreeGLUT */ 103 | # if FREEGLUT_LIB_PRAGMAS 104 | # pragma comment (lib, "glu32.lib") /* link OpenGL Utility lib */ 105 | # pragma comment (lib, "opengl32.lib") /* link Microsoft OpenGL lib */ 106 | # pragma comment (lib, "gdi32.lib") /* link Windows GDI lib */ 107 | # pragma comment (lib, "winmm.lib") /* link Windows MultiMedia lib */ 108 | # pragma comment (lib, "user32.lib") /* link Windows user lib */ 109 | # endif 110 | 111 | #else 112 | 113 | /* Non-Windows definition of FGAPI and FGAPIENTRY */ 114 | # define FGAPI 115 | # define FGAPIENTRY 116 | 117 | #endif 118 | 119 | /* 120 | * The freeglut and GLUT API versions 121 | */ 122 | #define FREEGLUT 1 123 | #define GLUT_API_VERSION 4 124 | #define GLUT_XLIB_IMPLEMENTATION 13 125 | /* Deprecated: 126 | cf. http://sourceforge.net/mailarchive/forum.php?thread_name=CABcAi1hw7cr4xtigckaGXB5X8wddLfMcbA_rZ3NAuwMrX_zmsw%40mail.gmail.com&forum_name=freeglut-developer */ 127 | #define FREEGLUT_VERSION_2_0 1 128 | 129 | /* 130 | * Always include OpenGL and GLU headers 131 | */ 132 | /* Note: FREEGLUT_GLES is only used to cleanly bootstrap headers 133 | inclusion here; use GLES constants directly 134 | (e.g. GL_ES_VERSION_2_0) for all other needs */ 135 | #ifdef FREEGLUT_GLES 136 | # include 137 | # include 138 | # include 139 | #elif __APPLE__ 140 | # include 141 | # include 142 | #else 143 | # include 144 | # include 145 | #endif 146 | 147 | /* 148 | * GLUT API macro definitions -- the special key codes: 149 | */ 150 | #define GLUT_KEY_F1 0x0001 151 | #define GLUT_KEY_F2 0x0002 152 | #define GLUT_KEY_F3 0x0003 153 | #define GLUT_KEY_F4 0x0004 154 | #define GLUT_KEY_F5 0x0005 155 | #define GLUT_KEY_F6 0x0006 156 | #define GLUT_KEY_F7 0x0007 157 | #define GLUT_KEY_F8 0x0008 158 | #define GLUT_KEY_F9 0x0009 159 | #define GLUT_KEY_F10 0x000A 160 | #define GLUT_KEY_F11 0x000B 161 | #define GLUT_KEY_F12 0x000C 162 | #define GLUT_KEY_LEFT 0x0064 163 | #define GLUT_KEY_UP 0x0065 164 | #define GLUT_KEY_RIGHT 0x0066 165 | #define GLUT_KEY_DOWN 0x0067 166 | #define GLUT_KEY_PAGE_UP 0x0068 167 | #define GLUT_KEY_PAGE_DOWN 0x0069 168 | #define GLUT_KEY_HOME 0x006A 169 | #define GLUT_KEY_END 0x006B 170 | #define GLUT_KEY_INSERT 0x006C 171 | 172 | /* 173 | * GLUT API macro definitions -- mouse state definitions 174 | */ 175 | #define GLUT_LEFT_BUTTON 0x0000 176 | #define GLUT_MIDDLE_BUTTON 0x0001 177 | #define GLUT_RIGHT_BUTTON 0x0002 178 | #define GLUT_DOWN 0x0000 179 | #define GLUT_UP 0x0001 180 | #define GLUT_LEFT 0x0000 181 | #define GLUT_ENTERED 0x0001 182 | 183 | /* 184 | * GLUT API macro definitions -- the display mode definitions 185 | */ 186 | #define GLUT_RGB 0x0000 187 | #define GLUT_RGBA 0x0000 188 | #define GLUT_INDEX 0x0001 189 | #define GLUT_SINGLE 0x0000 190 | #define GLUT_DOUBLE 0x0002 191 | #define GLUT_ACCUM 0x0004 192 | #define GLUT_ALPHA 0x0008 193 | #define GLUT_DEPTH 0x0010 194 | #define GLUT_STENCIL 0x0020 195 | #define GLUT_MULTISAMPLE 0x0080 196 | #define GLUT_STEREO 0x0100 197 | #define GLUT_LUMINANCE 0x0200 198 | 199 | /* 200 | * GLUT API macro definitions -- windows and menu related definitions 201 | */ 202 | #define GLUT_MENU_NOT_IN_USE 0x0000 203 | #define GLUT_MENU_IN_USE 0x0001 204 | #define GLUT_NOT_VISIBLE 0x0000 205 | #define GLUT_VISIBLE 0x0001 206 | #define GLUT_HIDDEN 0x0000 207 | #define GLUT_FULLY_RETAINED 0x0001 208 | #define GLUT_PARTIALLY_RETAINED 0x0002 209 | #define GLUT_FULLY_COVERED 0x0003 210 | 211 | /* 212 | * GLUT API macro definitions -- fonts definitions 213 | * 214 | * Steve Baker suggested to make it binary compatible with GLUT: 215 | */ 216 | #if defined(_MSC_VER) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__WATCOMC__) 217 | # define GLUT_STROKE_ROMAN ((void *)0x0000) 218 | # define GLUT_STROKE_MONO_ROMAN ((void *)0x0001) 219 | # define GLUT_BITMAP_9_BY_15 ((void *)0x0002) 220 | # define GLUT_BITMAP_8_BY_13 ((void *)0x0003) 221 | # define GLUT_BITMAP_TIMES_ROMAN_10 ((void *)0x0004) 222 | # define GLUT_BITMAP_TIMES_ROMAN_24 ((void *)0x0005) 223 | # define GLUT_BITMAP_HELVETICA_10 ((void *)0x0006) 224 | # define GLUT_BITMAP_HELVETICA_12 ((void *)0x0007) 225 | # define GLUT_BITMAP_HELVETICA_18 ((void *)0x0008) 226 | #else 227 | /* 228 | * I don't really know if it's a good idea... But here it goes: 229 | */ 230 | extern void* glutStrokeRoman; 231 | extern void* glutStrokeMonoRoman; 232 | extern void* glutBitmap9By15; 233 | extern void* glutBitmap8By13; 234 | extern void* glutBitmapTimesRoman10; 235 | extern void* glutBitmapTimesRoman24; 236 | extern void* glutBitmapHelvetica10; 237 | extern void* glutBitmapHelvetica12; 238 | extern void* glutBitmapHelvetica18; 239 | 240 | /* 241 | * Those pointers will be used by following definitions: 242 | */ 243 | # define GLUT_STROKE_ROMAN ((void *) &glutStrokeRoman) 244 | # define GLUT_STROKE_MONO_ROMAN ((void *) &glutStrokeMonoRoman) 245 | # define GLUT_BITMAP_9_BY_15 ((void *) &glutBitmap9By15) 246 | # define GLUT_BITMAP_8_BY_13 ((void *) &glutBitmap8By13) 247 | # define GLUT_BITMAP_TIMES_ROMAN_10 ((void *) &glutBitmapTimesRoman10) 248 | # define GLUT_BITMAP_TIMES_ROMAN_24 ((void *) &glutBitmapTimesRoman24) 249 | # define GLUT_BITMAP_HELVETICA_10 ((void *) &glutBitmapHelvetica10) 250 | # define GLUT_BITMAP_HELVETICA_12 ((void *) &glutBitmapHelvetica12) 251 | # define GLUT_BITMAP_HELVETICA_18 ((void *) &glutBitmapHelvetica18) 252 | #endif 253 | 254 | /* 255 | * GLUT API macro definitions -- the glutGet parameters 256 | */ 257 | #define GLUT_WINDOW_X 0x0064 258 | #define GLUT_WINDOW_Y 0x0065 259 | #define GLUT_WINDOW_WIDTH 0x0066 260 | #define GLUT_WINDOW_HEIGHT 0x0067 261 | #define GLUT_WINDOW_BUFFER_SIZE 0x0068 262 | #define GLUT_WINDOW_STENCIL_SIZE 0x0069 263 | #define GLUT_WINDOW_DEPTH_SIZE 0x006A 264 | #define GLUT_WINDOW_RED_SIZE 0x006B 265 | #define GLUT_WINDOW_GREEN_SIZE 0x006C 266 | #define GLUT_WINDOW_BLUE_SIZE 0x006D 267 | #define GLUT_WINDOW_ALPHA_SIZE 0x006E 268 | #define GLUT_WINDOW_ACCUM_RED_SIZE 0x006F 269 | #define GLUT_WINDOW_ACCUM_GREEN_SIZE 0x0070 270 | #define GLUT_WINDOW_ACCUM_BLUE_SIZE 0x0071 271 | #define GLUT_WINDOW_ACCUM_ALPHA_SIZE 0x0072 272 | #define GLUT_WINDOW_DOUBLEBUFFER 0x0073 273 | #define GLUT_WINDOW_RGBA 0x0074 274 | #define GLUT_WINDOW_PARENT 0x0075 275 | #define GLUT_WINDOW_NUM_CHILDREN 0x0076 276 | #define GLUT_WINDOW_COLORMAP_SIZE 0x0077 277 | #define GLUT_WINDOW_NUM_SAMPLES 0x0078 278 | #define GLUT_WINDOW_STEREO 0x0079 279 | #define GLUT_WINDOW_CURSOR 0x007A 280 | 281 | #define GLUT_SCREEN_WIDTH 0x00C8 282 | #define GLUT_SCREEN_HEIGHT 0x00C9 283 | #define GLUT_SCREEN_WIDTH_MM 0x00CA 284 | #define GLUT_SCREEN_HEIGHT_MM 0x00CB 285 | #define GLUT_MENU_NUM_ITEMS 0x012C 286 | #define GLUT_DISPLAY_MODE_POSSIBLE 0x0190 287 | #define GLUT_INIT_WINDOW_X 0x01F4 288 | #define GLUT_INIT_WINDOW_Y 0x01F5 289 | #define GLUT_INIT_WINDOW_WIDTH 0x01F6 290 | #define GLUT_INIT_WINDOW_HEIGHT 0x01F7 291 | #define GLUT_INIT_DISPLAY_MODE 0x01F8 292 | #define GLUT_ELAPSED_TIME 0x02BC 293 | #define GLUT_WINDOW_FORMAT_ID 0x007B 294 | 295 | /* 296 | * GLUT API macro definitions -- the glutDeviceGet parameters 297 | */ 298 | #define GLUT_HAS_KEYBOARD 0x0258 299 | #define GLUT_HAS_MOUSE 0x0259 300 | #define GLUT_HAS_SPACEBALL 0x025A 301 | #define GLUT_HAS_DIAL_AND_BUTTON_BOX 0x025B 302 | #define GLUT_HAS_TABLET 0x025C 303 | #define GLUT_NUM_MOUSE_BUTTONS 0x025D 304 | #define GLUT_NUM_SPACEBALL_BUTTONS 0x025E 305 | #define GLUT_NUM_BUTTON_BOX_BUTTONS 0x025F 306 | #define GLUT_NUM_DIALS 0x0260 307 | #define GLUT_NUM_TABLET_BUTTONS 0x0261 308 | #define GLUT_DEVICE_IGNORE_KEY_REPEAT 0x0262 309 | #define GLUT_DEVICE_KEY_REPEAT 0x0263 310 | #define GLUT_HAS_JOYSTICK 0x0264 311 | #define GLUT_OWNS_JOYSTICK 0x0265 312 | #define GLUT_JOYSTICK_BUTTONS 0x0266 313 | #define GLUT_JOYSTICK_AXES 0x0267 314 | #define GLUT_JOYSTICK_POLL_RATE 0x0268 315 | 316 | /* 317 | * GLUT API macro definitions -- the glutLayerGet parameters 318 | */ 319 | #define GLUT_OVERLAY_POSSIBLE 0x0320 320 | #define GLUT_LAYER_IN_USE 0x0321 321 | #define GLUT_HAS_OVERLAY 0x0322 322 | #define GLUT_TRANSPARENT_INDEX 0x0323 323 | #define GLUT_NORMAL_DAMAGED 0x0324 324 | #define GLUT_OVERLAY_DAMAGED 0x0325 325 | 326 | /* 327 | * GLUT API macro definitions -- the glutVideoResizeGet parameters 328 | */ 329 | #define GLUT_VIDEO_RESIZE_POSSIBLE 0x0384 330 | #define GLUT_VIDEO_RESIZE_IN_USE 0x0385 331 | #define GLUT_VIDEO_RESIZE_X_DELTA 0x0386 332 | #define GLUT_VIDEO_RESIZE_Y_DELTA 0x0387 333 | #define GLUT_VIDEO_RESIZE_WIDTH_DELTA 0x0388 334 | #define GLUT_VIDEO_RESIZE_HEIGHT_DELTA 0x0389 335 | #define GLUT_VIDEO_RESIZE_X 0x038A 336 | #define GLUT_VIDEO_RESIZE_Y 0x038B 337 | #define GLUT_VIDEO_RESIZE_WIDTH 0x038C 338 | #define GLUT_VIDEO_RESIZE_HEIGHT 0x038D 339 | 340 | /* 341 | * GLUT API macro definitions -- the glutUseLayer parameters 342 | */ 343 | #define GLUT_NORMAL 0x0000 344 | #define GLUT_OVERLAY 0x0001 345 | 346 | /* 347 | * GLUT API macro definitions -- the glutGetModifiers parameters 348 | */ 349 | #define GLUT_ACTIVE_SHIFT 0x0001 350 | #define GLUT_ACTIVE_CTRL 0x0002 351 | #define GLUT_ACTIVE_ALT 0x0004 352 | 353 | /* 354 | * GLUT API macro definitions -- the glutSetCursor parameters 355 | */ 356 | #define GLUT_CURSOR_RIGHT_ARROW 0x0000 357 | #define GLUT_CURSOR_LEFT_ARROW 0x0001 358 | #define GLUT_CURSOR_INFO 0x0002 359 | #define GLUT_CURSOR_DESTROY 0x0003 360 | #define GLUT_CURSOR_HELP 0x0004 361 | #define GLUT_CURSOR_CYCLE 0x0005 362 | #define GLUT_CURSOR_SPRAY 0x0006 363 | #define GLUT_CURSOR_WAIT 0x0007 364 | #define GLUT_CURSOR_TEXT 0x0008 365 | #define GLUT_CURSOR_CROSSHAIR 0x0009 366 | #define GLUT_CURSOR_UP_DOWN 0x000A 367 | #define GLUT_CURSOR_LEFT_RIGHT 0x000B 368 | #define GLUT_CURSOR_TOP_SIDE 0x000C 369 | #define GLUT_CURSOR_BOTTOM_SIDE 0x000D 370 | #define GLUT_CURSOR_LEFT_SIDE 0x000E 371 | #define GLUT_CURSOR_RIGHT_SIDE 0x000F 372 | #define GLUT_CURSOR_TOP_LEFT_CORNER 0x0010 373 | #define GLUT_CURSOR_TOP_RIGHT_CORNER 0x0011 374 | #define GLUT_CURSOR_BOTTOM_RIGHT_CORNER 0x0012 375 | #define GLUT_CURSOR_BOTTOM_LEFT_CORNER 0x0013 376 | #define GLUT_CURSOR_INHERIT 0x0064 377 | #define GLUT_CURSOR_NONE 0x0065 378 | #define GLUT_CURSOR_FULL_CROSSHAIR 0x0066 379 | 380 | /* 381 | * GLUT API macro definitions -- RGB color component specification definitions 382 | */ 383 | #define GLUT_RED 0x0000 384 | #define GLUT_GREEN 0x0001 385 | #define GLUT_BLUE 0x0002 386 | 387 | /* 388 | * GLUT API macro definitions -- additional keyboard and joystick definitions 389 | */ 390 | #define GLUT_KEY_REPEAT_OFF 0x0000 391 | #define GLUT_KEY_REPEAT_ON 0x0001 392 | #define GLUT_KEY_REPEAT_DEFAULT 0x0002 393 | 394 | #define GLUT_JOYSTICK_BUTTON_A 0x0001 395 | #define GLUT_JOYSTICK_BUTTON_B 0x0002 396 | #define GLUT_JOYSTICK_BUTTON_C 0x0004 397 | #define GLUT_JOYSTICK_BUTTON_D 0x0008 398 | 399 | /* 400 | * GLUT API macro definitions -- game mode definitions 401 | */ 402 | #define GLUT_GAME_MODE_ACTIVE 0x0000 403 | #define GLUT_GAME_MODE_POSSIBLE 0x0001 404 | #define GLUT_GAME_MODE_WIDTH 0x0002 405 | #define GLUT_GAME_MODE_HEIGHT 0x0003 406 | #define GLUT_GAME_MODE_PIXEL_DEPTH 0x0004 407 | #define GLUT_GAME_MODE_REFRESH_RATE 0x0005 408 | #define GLUT_GAME_MODE_DISPLAY_CHANGED 0x0006 409 | 410 | /* 411 | * Initialization functions, see fglut_init.c 412 | */ 413 | FGAPI void FGAPIENTRY glutInit( int* pargc, char** argv ); 414 | FGAPI void FGAPIENTRY glutInitWindowPosition( int x, int y ); 415 | FGAPI void FGAPIENTRY glutInitWindowSize( int width, int height ); 416 | FGAPI void FGAPIENTRY glutInitDisplayMode( unsigned int displayMode ); 417 | FGAPI void FGAPIENTRY glutInitDisplayString( const char* displayMode ); 418 | 419 | /* 420 | * Process loop function, see fg_main.c 421 | */ 422 | FGAPI void FGAPIENTRY glutMainLoop( void ); 423 | 424 | /* 425 | * Window management functions, see fg_window.c 426 | */ 427 | FGAPI int FGAPIENTRY glutCreateWindow( const char* title ); 428 | FGAPI int FGAPIENTRY glutCreateSubWindow( int window, int x, int y, int width, int height ); 429 | FGAPI void FGAPIENTRY glutDestroyWindow( int window ); 430 | FGAPI void FGAPIENTRY glutSetWindow( int window ); 431 | FGAPI int FGAPIENTRY glutGetWindow( void ); 432 | FGAPI void FGAPIENTRY glutSetWindowTitle( const char* title ); 433 | FGAPI void FGAPIENTRY glutSetIconTitle( const char* title ); 434 | FGAPI void FGAPIENTRY glutReshapeWindow( int width, int height ); 435 | FGAPI void FGAPIENTRY glutPositionWindow( int x, int y ); 436 | FGAPI void FGAPIENTRY glutShowWindow( void ); 437 | FGAPI void FGAPIENTRY glutHideWindow( void ); 438 | FGAPI void FGAPIENTRY glutIconifyWindow( void ); 439 | FGAPI void FGAPIENTRY glutPushWindow( void ); 440 | FGAPI void FGAPIENTRY glutPopWindow( void ); 441 | FGAPI void FGAPIENTRY glutFullScreen( void ); 442 | 443 | /* 444 | * Display-related functions, see fg_display.c 445 | */ 446 | FGAPI void FGAPIENTRY glutPostWindowRedisplay( int window ); 447 | FGAPI void FGAPIENTRY glutPostRedisplay( void ); 448 | FGAPI void FGAPIENTRY glutSwapBuffers( void ); 449 | 450 | /* 451 | * Mouse cursor functions, see fg_cursor.c 452 | */ 453 | FGAPI void FGAPIENTRY glutWarpPointer( int x, int y ); 454 | FGAPI void FGAPIENTRY glutSetCursor( int cursor ); 455 | 456 | /* 457 | * Overlay stuff, see fg_overlay.c 458 | */ 459 | FGAPI void FGAPIENTRY glutEstablishOverlay( void ); 460 | FGAPI void FGAPIENTRY glutRemoveOverlay( void ); 461 | FGAPI void FGAPIENTRY glutUseLayer( GLenum layer ); 462 | FGAPI void FGAPIENTRY glutPostOverlayRedisplay( void ); 463 | FGAPI void FGAPIENTRY glutPostWindowOverlayRedisplay( int window ); 464 | FGAPI void FGAPIENTRY glutShowOverlay( void ); 465 | FGAPI void FGAPIENTRY glutHideOverlay( void ); 466 | 467 | /* 468 | * Menu stuff, see fg_menu.c 469 | */ 470 | FGAPI int FGAPIENTRY glutCreateMenu( void (* callback)( int menu ) ); 471 | FGAPI void FGAPIENTRY glutDestroyMenu( int menu ); 472 | FGAPI int FGAPIENTRY glutGetMenu( void ); 473 | FGAPI void FGAPIENTRY glutSetMenu( int menu ); 474 | FGAPI void FGAPIENTRY glutAddMenuEntry( const char* label, int value ); 475 | FGAPI void FGAPIENTRY glutAddSubMenu( const char* label, int subMenu ); 476 | FGAPI void FGAPIENTRY glutChangeToMenuEntry( int item, const char* label, int value ); 477 | FGAPI void FGAPIENTRY glutChangeToSubMenu( int item, const char* label, int value ); 478 | FGAPI void FGAPIENTRY glutRemoveMenuItem( int item ); 479 | FGAPI void FGAPIENTRY glutAttachMenu( int button ); 480 | FGAPI void FGAPIENTRY glutDetachMenu( int button ); 481 | 482 | /* 483 | * Global callback functions, see fg_callbacks.c 484 | */ 485 | FGAPI void FGAPIENTRY glutTimerFunc( unsigned int time, void (* callback)( int ), int value ); 486 | FGAPI void FGAPIENTRY glutIdleFunc( void (* callback)( void ) ); 487 | 488 | /* 489 | * Window-specific callback functions, see fg_callbacks.c 490 | */ 491 | FGAPI void FGAPIENTRY glutKeyboardFunc( void (* callback)( unsigned char, int, int ) ); 492 | FGAPI void FGAPIENTRY glutSpecialFunc( void (* callback)( int, int, int ) ); 493 | FGAPI void FGAPIENTRY glutReshapeFunc( void (* callback)( int, int ) ); 494 | FGAPI void FGAPIENTRY glutVisibilityFunc( void (* callback)( int ) ); 495 | FGAPI void FGAPIENTRY glutDisplayFunc( void (* callback)( void ) ); 496 | FGAPI void FGAPIENTRY glutMouseFunc( void (* callback)( int, int, int, int ) ); 497 | FGAPI void FGAPIENTRY glutMotionFunc( void (* callback)( int, int ) ); 498 | FGAPI void FGAPIENTRY glutPassiveMotionFunc( void (* callback)( int, int ) ); 499 | FGAPI void FGAPIENTRY glutEntryFunc( void (* callback)( int ) ); 500 | 501 | FGAPI void FGAPIENTRY glutKeyboardUpFunc( void (* callback)( unsigned char, int, int ) ); 502 | FGAPI void FGAPIENTRY glutSpecialUpFunc( void (* callback)( int, int, int ) ); 503 | FGAPI void FGAPIENTRY glutJoystickFunc( void (* callback)( unsigned int, int, int, int ), int pollInterval ); 504 | FGAPI void FGAPIENTRY glutMenuStateFunc( void (* callback)( int ) ); 505 | FGAPI void FGAPIENTRY glutMenuStatusFunc( void (* callback)( int, int, int ) ); 506 | FGAPI void FGAPIENTRY glutOverlayDisplayFunc( void (* callback)( void ) ); 507 | FGAPI void FGAPIENTRY glutWindowStatusFunc( void (* callback)( int ) ); 508 | 509 | FGAPI void FGAPIENTRY glutSpaceballMotionFunc( void (* callback)( int, int, int ) ); 510 | FGAPI void FGAPIENTRY glutSpaceballRotateFunc( void (* callback)( int, int, int ) ); 511 | FGAPI void FGAPIENTRY glutSpaceballButtonFunc( void (* callback)( int, int ) ); 512 | FGAPI void FGAPIENTRY glutButtonBoxFunc( void (* callback)( int, int ) ); 513 | FGAPI void FGAPIENTRY glutDialsFunc( void (* callback)( int, int ) ); 514 | FGAPI void FGAPIENTRY glutTabletMotionFunc( void (* callback)( int, int ) ); 515 | FGAPI void FGAPIENTRY glutTabletButtonFunc( void (* callback)( int, int, int, int ) ); 516 | 517 | /* 518 | * State setting and retrieval functions, see fg_state.c 519 | */ 520 | FGAPI int FGAPIENTRY glutGet( GLenum query ); 521 | FGAPI int FGAPIENTRY glutDeviceGet( GLenum query ); 522 | FGAPI int FGAPIENTRY glutGetModifiers( void ); 523 | FGAPI int FGAPIENTRY glutLayerGet( GLenum query ); 524 | 525 | /* 526 | * Font stuff, see fg_font.c 527 | */ 528 | FGAPI void FGAPIENTRY glutBitmapCharacter( void* font, int character ); 529 | FGAPI int FGAPIENTRY glutBitmapWidth( void* font, int character ); 530 | FGAPI void FGAPIENTRY glutStrokeCharacter( void* font, int character ); 531 | FGAPI int FGAPIENTRY glutStrokeWidth( void* font, int character ); 532 | FGAPI GLfloat FGAPIENTRY glutStrokeWidthf( void* font, int character ); /* GLUT 3.8 */ 533 | FGAPI int FGAPIENTRY glutBitmapLength( void* font, const unsigned char* string ); 534 | FGAPI int FGAPIENTRY glutStrokeLength( void* font, const unsigned char* string ); 535 | FGAPI GLfloat FGAPIENTRY glutStrokeLengthf( void* font, const unsigned char *string ); /* GLUT 3.8 */ 536 | 537 | /* 538 | * Geometry functions, see fg_geometry.c 539 | */ 540 | 541 | FGAPI void FGAPIENTRY glutWireCube( double size ); 542 | FGAPI void FGAPIENTRY glutSolidCube( double size ); 543 | FGAPI void FGAPIENTRY glutWireSphere( double radius, GLint slices, GLint stacks ); 544 | FGAPI void FGAPIENTRY glutSolidSphere( double radius, GLint slices, GLint stacks ); 545 | FGAPI void FGAPIENTRY glutWireCone( double base, double height, GLint slices, GLint stacks ); 546 | FGAPI void FGAPIENTRY glutSolidCone( double base, double height, GLint slices, GLint stacks ); 547 | FGAPI void FGAPIENTRY glutWireTorus( double innerRadius, double outerRadius, GLint sides, GLint rings ); 548 | FGAPI void FGAPIENTRY glutSolidTorus( double innerRadius, double outerRadius, GLint sides, GLint rings ); 549 | FGAPI void FGAPIENTRY glutWireDodecahedron( void ); 550 | FGAPI void FGAPIENTRY glutSolidDodecahedron( void ); 551 | FGAPI void FGAPIENTRY glutWireOctahedron( void ); 552 | FGAPI void FGAPIENTRY glutSolidOctahedron( void ); 553 | FGAPI void FGAPIENTRY glutWireTetrahedron( void ); 554 | FGAPI void FGAPIENTRY glutSolidTetrahedron( void ); 555 | FGAPI void FGAPIENTRY glutWireIcosahedron( void ); 556 | FGAPI void FGAPIENTRY glutSolidIcosahedron( void ); 557 | 558 | /* 559 | * Teapot rendering functions, found in fg_teapot.c 560 | * NB: front facing polygons have clockwise winding, not counter clockwise 561 | */ 562 | FGAPI void FGAPIENTRY glutWireTeapot( double size ); 563 | FGAPI void FGAPIENTRY glutSolidTeapot( double size ); 564 | 565 | /* 566 | * Game mode functions, see fg_gamemode.c 567 | */ 568 | FGAPI void FGAPIENTRY glutGameModeString( const char* string ); 569 | FGAPI int FGAPIENTRY glutEnterGameMode( void ); 570 | FGAPI void FGAPIENTRY glutLeaveGameMode( void ); 571 | FGAPI int FGAPIENTRY glutGameModeGet( GLenum query ); 572 | 573 | /* 574 | * Video resize functions, see fg_videoresize.c 575 | */ 576 | FGAPI int FGAPIENTRY glutVideoResizeGet( GLenum query ); 577 | FGAPI void FGAPIENTRY glutSetupVideoResizing( void ); 578 | FGAPI void FGAPIENTRY glutStopVideoResizing( void ); 579 | FGAPI void FGAPIENTRY glutVideoResize( int x, int y, int width, int height ); 580 | FGAPI void FGAPIENTRY glutVideoPan( int x, int y, int width, int height ); 581 | 582 | /* 583 | * Colormap functions, see fg_misc.c 584 | */ 585 | FGAPI void FGAPIENTRY glutSetColor( int color, GLfloat red, GLfloat green, GLfloat blue ); 586 | FGAPI GLfloat FGAPIENTRY glutGetColor( int color, int component ); 587 | FGAPI void FGAPIENTRY glutCopyColormap( int window ); 588 | 589 | /* 590 | * Misc keyboard and joystick functions, see fg_misc.c 591 | */ 592 | FGAPI void FGAPIENTRY glutIgnoreKeyRepeat( int ignore ); 593 | FGAPI void FGAPIENTRY glutSetKeyRepeat( int repeatMode ); 594 | FGAPI void FGAPIENTRY glutForceJoystickFunc( void ); 595 | 596 | /* 597 | * Misc functions, see fg_misc.c 598 | */ 599 | FGAPI int FGAPIENTRY glutExtensionSupported( const char* extension ); 600 | FGAPI void FGAPIENTRY glutReportErrors( void ); 601 | 602 | /* Comment from glut.h of classic GLUT: 603 | 604 | Win32 has an annoying issue where there are multiple C run-time 605 | libraries (CRTs). If the executable is linked with a different CRT 606 | from the GLUT DLL, the GLUT DLL will not share the same CRT static 607 | data seen by the executable. In particular, atexit callbacks registered 608 | in the executable will not be called if GLUT calls its (different) 609 | exit routine). GLUT is typically built with the 610 | "/MD" option (the CRT with multithreading DLL support), but the Visual 611 | C++ linker default is "/ML" (the single threaded CRT). 612 | 613 | One workaround to this issue is requiring users to always link with 614 | the same CRT as GLUT is compiled with. That requires users supply a 615 | non-standard option. GLUT 3.7 has its own built-in workaround where 616 | the executable's "exit" function pointer is covertly passed to GLUT. 617 | GLUT then calls the executable's exit function pointer to ensure that 618 | any "atexit" calls registered by the application are called if GLUT 619 | needs to exit. 620 | 621 | Note that the __glut*WithExit routines should NEVER be called directly. 622 | To avoid the atexit workaround, #define GLUT_DISABLE_ATEXIT_HACK. */ 623 | 624 | /* to get the prototype for exit() */ 625 | #include 626 | 627 | #if defined(_WIN32) && !defined(GLUT_DISABLE_ATEXIT_HACK) && !defined(__WATCOMC__) 628 | FGAPI void FGAPIENTRY __glutInitWithExit(int *argcp, char **argv, void (__cdecl *exitfunc)(int)); 629 | FGAPI int FGAPIENTRY __glutCreateWindowWithExit(const char *title, void (__cdecl *exitfunc)(int)); 630 | FGAPI int FGAPIENTRY __glutCreateMenuWithExit(void (* func)(int), void (__cdecl *exitfunc)(int)); 631 | #ifndef FREEGLUT_BUILDING_LIB 632 | #if defined(__GNUC__) 633 | #define FGUNUSED __attribute__((unused)) 634 | #else 635 | #define FGUNUSED 636 | #endif 637 | static void FGAPIENTRY FGUNUSED glutInit_ATEXIT_HACK(int *argcp, char **argv) { __glutInitWithExit(argcp, argv, exit); } 638 | #define glutInit glutInit_ATEXIT_HACK 639 | static int FGAPIENTRY FGUNUSED glutCreateWindow_ATEXIT_HACK(const char *title) { return __glutCreateWindowWithExit(title, exit); } 640 | #define glutCreateWindow glutCreateWindow_ATEXIT_HACK 641 | static int FGAPIENTRY FGUNUSED glutCreateMenu_ATEXIT_HACK(void (* func)(int)) { return __glutCreateMenuWithExit(func, exit); } 642 | #define glutCreateMenu glutCreateMenu_ATEXIT_HACK 643 | #endif 644 | #endif 645 | 646 | #ifdef __cplusplus 647 | } 648 | #endif 649 | 650 | /*** END OF FILE ***/ 651 | 652 | #endif /* __FREEGLUT_STD_H__ */ 653 | 654 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | Copyright (C) 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Copyright (C) 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | --------------------------------------------------------------------------------