用于 OpenGL ES 的多边形三角剖分为三角形带

2023-11-27

我正在寻找一个快速多边形三角剖分算法可以将不是很复杂的二维凹多边形(无孔)三角化为三角条准备发送到 OpenGL ES 进行绘图GL_TRIANGLE_STRIP.

我知道一些算法,但我找不到适合我需要的算法:

  • http://www.flipcode.com/archives/Efficient_Polygon_Triangulation.shtml
    • 这个算法工作正常,但问题是它返回你无法绘制的简单三角形GL_TRIANGLE_STRIP,你需要使用GL_TRIANGLES这对于大量顶点来说不是很有效。
  • http://code.google.com/p/iphone-glu/
    • 它没有任何关联的示例,而且我找不到任何人在 iOS 上通过 OpenGL ES 2.0 成功使用它
    • 我不知道它返回什么,而且它似乎还调用了我不想要的相应 OpenGL 命令 - 我只需要返回三角形
    • 它会泄漏内存

我正在开发的平台是:iOS、OpenGL ES 2.0、cocos2d 2.0。

谁能帮我解决这样的算法吗?或者任何其他建议将不胜感激。


在二维且没有孔的情况下,这相当容易。首先,您需要将多边形分解为一个或多个单调多边形.

单调多边形很容易变成三条带,只需按以下方式对值进行排序即可y,找到最顶部和最底部的顶点,然后您将获得右侧和左侧的顶点列表(因为顶点以某种定义的顺序(例如顺时针顺序)出现)。然后从最顶部的顶点开始,并以交替的方式从左侧和右侧添加顶点。

该技术适用于任何没有自相交边的二维多边形,其中包括一些带有孔的多边形的情况(但孔必须正确缠绕)。

您可以尝试使用以下代码:

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(-.5f, -.5f, 0);

std::vector<Vector2f> my_polygon;

my_polygon.push_back(Vector2f(-0.300475f, 0.862924f));
my_polygon.push_back(Vector2f(0.302850f, 1.265013f));
my_polygon.push_back(Vector2f(0.811164f, 1.437337f));
my_polygon.push_back(Vector2f(1.001188f, 1.071802f));
my_polygon.push_back(Vector2f(0.692399f, 0.936031f));
my_polygon.push_back(Vector2f(0.934679f, 0.622715f));
my_polygon.push_back(Vector2f(0.644893f, 0.408616f));
my_polygon.push_back(Vector2f(0.592637f, 0.753264f));
my_polygon.push_back(Vector2f(0.269596f, 0.278068f));
my_polygon.push_back(Vector2f(0.996437f, -0.092689f));
my_polygon.push_back(Vector2f(0.735154f, -0.338120f));
my_polygon.push_back(Vector2f(0.112827f, 0.079634f));
my_polygon.push_back(Vector2f(-0.167458f, 0.330287f));
my_polygon.push_back(Vector2f(0.008314f, 0.664491f));
my_polygon.push_back(Vector2f(0.393112f, 1.040470f));
// from wiki (http://en.wikipedia.org/wiki/File:Polygon-to-monotone.png)

glEnable(GL_POINT_SMOOTH);
glEnable(GL_LINE_SMOOTH);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

glLineWidth(6);
glColor3f(1, 1, 1);
glBegin(GL_LINE_LOOP);
for(size_t i = 0, n = my_polygon.size(); i < n; ++ i)
    glVertex2f(my_polygon[i].x, my_polygon[i].y);
glEnd();
glPointSize(6);
glBegin(GL_POINTS);
for(size_t i = 0, n = my_polygon.size(); i < n; ++ i)
    glVertex2f(my_polygon[i].x, my_polygon[i].y);
glEnd();
// draw the original polygon

std::vector<int> working_set;
for(size_t i = 0, n = my_polygon.size(); i < n; ++ i)
    working_set.push_back(i);
_ASSERTE(working_set.size() == my_polygon.size());
// add vertex indices to the list (could be done using iota)

std::list<std::vector<int> > monotone_poly_list;
// list of monotone polygons (the output)

glPointSize(14);
glLineWidth(4);
// prepare to draw split points and slice lines

for(;;) {
    std::vector<int> sorted_vertex_list;
    {
        for(size_t i = 0, n = working_set.size(); i < n; ++ i)
            sorted_vertex_list.push_back(i);
        _ASSERTE(working_set.size() == working_set.size());
        // add vertex indices to the list (could be done using iota)

        for(;;) {
            bool b_change = false;

            for(size_t i = 1, n = sorted_vertex_list.size(); i < n; ++ i) {
                int a = sorted_vertex_list[i - 1];
                int b = sorted_vertex_list[i];
                if(my_polygon[working_set[a]].y < my_polygon[working_set[b]].y) {
                    std::swap(sorted_vertex_list[i - 1], sorted_vertex_list[i]);
                    b_change = true;
                }
            }

            if(!b_change)
                break;
        }
        // sort vertex indices by the y coordinate
        // (note this is using bubblesort to maintain portability
        // but it should be done using a better sorting method)
    }
    // build sorted vertex list

    bool b_change = false;
    for(size_t i = 0, n = sorted_vertex_list.size(), m = working_set.size(); i < n; ++ i) {
        int n_ith = sorted_vertex_list[i];
        Vector2f ith = my_polygon[working_set[n_ith]];
        Vector2f prev = my_polygon[working_set[(n_ith + m - 1) % m]];
        Vector2f next = my_polygon[working_set[(n_ith + 1) % m]];
        // get point in the list, and get it's neighbours
        // (neighbours are not in sorted list ordering
        // but in the original polygon order)

        float sidePrev = sign(ith.y - prev.y);
        float sideNext = sign(ith.y - next.y);
        // calculate which side they lie on
        // (sign function gives -1 for negative and 1 for positive argument)

        if(sidePrev * sideNext >= 0) { // if they are both on the same side
            glColor3f(1, 0, 0);
            glBegin(GL_POINTS);
            glVertex2f(ith.x, ith.y);
            glEnd();
            // marks points whose neighbours are both on the same side (split points)

            int n_next = -1;
            if(sidePrev + sideNext > 0) {
                if(i > 0)
                    n_next = sorted_vertex_list[i - 1];
                // get the next vertex above it
            } else {
                if(i + 1 < n)
                    n_next = sorted_vertex_list[i + 1];
                // get the next vertex below it
            }
            // this is kind of simplistic, one needs to check if
            // a line between n_ith and n_next doesn't exit the polygon
            // (but that doesn't happen in the example)

            if(n_next != -1) {
                glColor3f(0, 1, 0);
                glBegin(GL_POINTS);
                glVertex2f(my_polygon[working_set[n_next]].x, my_polygon[working_set[n_next]].y);
                glEnd();
                glBegin(GL_LINES);
                glVertex2f(ith.x, ith.y);
                glVertex2f(my_polygon[working_set[n_next]].x, my_polygon[working_set[n_next]].y);
                glEnd();

                std::vector<int> poly, remove_list;

                int n_last = n_ith;
                if(n_last > n_next)
                    std::swap(n_last, n_next);
                int idx = n_next;
                poly.push_back(working_set[idx]); // add n_next
                for(idx = (idx + 1) % m; idx != n_last; idx = (idx + 1) % m) {
                    poly.push_back(working_set[idx]);
                    // add it to the polygon

                    remove_list.push_back(idx);
                    // mark this vertex to be erased from the working set
                }
                poly.push_back(working_set[idx]); // add n_ith
                // build a new monotone polygon by cutting the original one

                std::sort(remove_list.begin(), remove_list.end());
                for(size_t i = remove_list.size(); i > 0; -- i) {
                    int n_which = remove_list[i - 1];
                    working_set.erase(working_set.begin() + n_which);
                }
                // sort indices of vertices to be removed and remove them
                // from the working set (have to do it in reverse order)

                monotone_poly_list.push_back(poly);
                // add it to the list

                b_change = true;

                break;
                // the polygon was sliced, restart the algorithm, regenerate sorted list and slice again
            }
        }
    }

    if(!b_change)
        break;
    // no moves
}

if(!working_set.empty())
    monotone_poly_list.push_back(working_set);
// use the remaining vertices (which the algorithm was unable to slice) as the last polygon

std::list<std::vector<int> >::const_iterator p_mono_poly = monotone_poly_list.begin();
for(; p_mono_poly != monotone_poly_list.end(); ++ p_mono_poly) {
    const std::vector<int> &r_mono_poly = *p_mono_poly;

    glLineWidth(2);
    glColor3f(0, 0, 1);
    glBegin(GL_LINE_LOOP);
    for(size_t i = 0, n = r_mono_poly.size(); i < n; ++ i)
        glVertex2f(my_polygon[r_mono_poly[i]].x, my_polygon[r_mono_poly[i]].y);
    glEnd();
    glPointSize(2);
    glBegin(GL_POINTS);
    for(size_t i = 0, n = r_mono_poly.size(); i < n; ++ i)
        glVertex2f(my_polygon[r_mono_poly[i]].x, my_polygon[r_mono_poly[i]].y);
    glEnd();
    // draw the sliced part of the polygon

    int n_top = 0;
    for(size_t i = 0, n = r_mono_poly.size(); i < n; ++ i) {
        if(my_polygon[r_mono_poly[i]].y < my_polygon[r_mono_poly[n_top]].y)
            n_top = i;
    }
    // find the top-most point

    glLineWidth(1);
    glColor3f(0, 1, 0);
    glBegin(GL_LINE_STRIP);
    glVertex2f(my_polygon[r_mono_poly[n_top]].x, my_polygon[r_mono_poly[n_top]].y);
    for(size_t i = 1, n = r_mono_poly.size(); i <= n; ++ i) {
        int n_which = (n_top + ((i & 1)? n - i / 2 : i / 2)) % n;
        glVertex2f(my_polygon[r_mono_poly[n_which]].x, my_polygon[r_mono_poly[n_which]].y);
    }
    glEnd();
    // draw as if triangle strip
}

这段代码不是最优的,但应该很容易理解。首先,创建一个凹多边形。然后创建顶点的“工作集”。在该工作集上,计算排列,按顶点对顶点进行排序y协调。然后循环该排列,寻找分裂点。一旦找到分割点,就会创建一个新的单调多边形。然后,从工作集中删除新多边形中使用的顶点,并重复整个过程。最后,工作集包含最后一个无法分割的多边形。最后,渲染单调多边形以及三角形条带排序。它有点乱,但我相信您会弄清楚(这是 C++ 代码,只需将其放入 GLUT 窗口中,看看它会做什么)。

希望这可以帮助 ...

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

用于 OpenGL ES 的多边形三角剖分为三角形带 的相关文章

  • StackOverflowError 计算 BigInteger 的阶乘?

    我正在尝试编写一个Java程序来计算大数的阶乘 它似乎BigInteger无法容纳这么大的数量 下面是我编写的 简单的 代码 public static BigInteger getFactorial BigInteger num if n
  • 对矩阵进行舍入,保留行和列总计

    想要 以保留行和列总计的方式对矩阵进行舍入的 伪 代码 问题从向量开始 X and Y of 非负整数 with Sum X Sum Y 想要圆X Y Sum X 同时保留行和列总计 这是婚姻问题的一种 Xa需要进行一定次数的握手 拨打该号
  • Python 中的空填字游戏求解器

    我得到了一个包含填字游戏蓝图的矩阵 当然 它是空的 我们的目标是填补整个难题 这是 Checkio 的一项任务 我已经为此奋斗了相当长一段时间 根据我对复杂性的理解 这个问题没有完美的算法 不过 必须有最好的方法来做到这一点 对吧 我尝试了
  • 数组中最远的相等元素

    假设你有一个未排序的数组 你如何找到两个相等的元素 使它们成为数组中最远的元素 例如8 7 3 4 7 5 3 9 3 7 9 0ans 将是7 9 7 1 8 我想到了以下几点 initialise max 0 using hashing
  • 计算具有 3 个循环的算法的复杂度

    我尝试解决以下练习 以下代码片段最坏情况运行时间的增长顺序是什么 作为 N 的函数 int sum 0 for int i 1 i lt N i for int j 1 j lt i i j for int k 1 k lt j j k s
  • 使用 Numba 加速矢量距离计算

    以下是我为 3 D 环形几何中的距离 平方 计算编写的一些函数 用于该 3 D 空间中的粒子集合 import itertools import time import numpy as np import scipy import num
  • 运行时间为 O(n) 且就地排序的排序算法

    有没有运行时间为O n 并且还分类到位 在某些情况下 最好的情况是 O n 但这可能是因为项目集合已经排序 你正在看 O nlogn 一些较好的平均值 话虽如此 排序算法的 Wiki 还是相当不错的 有一个表格比较了流行的算法 说明了它们的
  • 当平方和为N时,如何找到四个变量的所有可能值?

    A 2 B 2 C 2 D 2 N给定一个整数N 打印出整数值的所有可能组合ABCD求解方程 我猜我们可以比暴力做得更好 天真的暴力会是这样的 n 3200724 lim sqrt n 1 for a 0 a lt lim a for b
  • 在 3d 网格中转发(绘制)线

    我需要类似 Bresenham 算法的东西 但是 对于 3d 网格空间来说不完全是这样 我需要 3d 单元网格 边缘尺寸 1 0 从 S 点开始 前进到 K 点 接触 该线接触的所有单元格 即使只有边缘 点被触摸我需要触摸所有 8 个单元
  • 一种良好且简单的随机性测量方法

    获取一长整数序列 例如 100 000 个 并返回序列随机性的测量值的最佳算法是什么 该函数应返回单个结果 如果序列并非完全随机 则返回 0 如果完全随机 则返回 1 如果序列有点随机 它可以给出介于两者之间的东西 例如0 95 可能是一个
  • 计算字符串的所有子串中子序列的出现次数

    我想编写一个算法来计算字符串的所有子字符串中字符子序列 不相交 出现的总数 下面是一个例子 字符串 jabcohnnyjohnny 后续 约翰尼 包含子序列的子字符串 jabcohnny jabcohnnyj jabcohnnyjo jab
  • 从原点开始在离散 2D 网格上迭代向外螺旋的算法

    例如 这是预期螺旋的形状 以及迭代的每个步骤 y 16 15 14 13 12 17 4 3 2 11 18 5 0 1 10 x 19 6 7 8 9 20 21 22 23 24 其中线条是 x 轴和 y 轴 以下是算法每次迭代 返回
  • 定点数学比浮点运算快吗?

    多年前 即 20 世纪 90 年代初期 我构建了图形软件包 该软件包基于定点算术和预先计算的 cos sin 表格以及使用牛顿近似方法进行 sqrt 和对数近似的缩放方程来优化计算 这些先进技术似乎已经成为图形和内置数学处理器的一部分 大约
  • 在任意时间范围内找到最佳日/月/年间隔的算法?

    如果您有时间表 请说 March 19 2009 July 15 2011 是否有一种算法可以将该时间范围分解为 March 19 2009 March 31 2009 complete days April 1 2009 December
  • “包含字符串”的快速索引

    在我的应用程序中 我有多达数百万个短字符串 大部分短于 32 个字符 我想实现一个带有附加列表的搜索框 该列表仅包含包含在搜索框中输入的整个字符串的元素 如何预先建立索引来快速找到此类字符串 所有排序的 STL 容器都会检查整个字符串 对于
  • 如何求两个地点的经纬度距离?

    我有一组位置的纬度和经度 怎么找distance从集合中的一个位置到另一个位置 有公式吗 半正矢公式假定地球是球形的 然而 地球的形状更为复杂 扁球体模型会给出更好的结果 如果需要这样的精度 你应该更好地使用文森特逆公式 See http
  • 我应该对算法使用递归还是记忆化?

    如果我可以选择使用递归或记忆来解决问题 我应该使用哪一个 换句话说 如果它们都是可行的解决方案 因为它们提供了正确的输出并且可以在我正在使用的代码中合理地表达 那么我什么时候会使用其中一个而不是另一个 它们并不相互排斥 您可以同时使用它们
  • 如何光栅化旋转矩形(通过 setpixel 在 2d 中)

    我有四个 2d 顶点 A B C D 的旋转矩形 我需要在像素缓冲区中 有效地 光栅化 绘制它 使用 setpixel x y 颜色 怎么做 我正在尝试使用一些代码 例如 convertilg a b c d do up down left
  • 总和不小于 key 的数组的最小子集

    给定一个数组 假设为非负整数 我们需要找到最小长度子集 使得元素之和不小于 K K 是作为输入提供的另一个整数 是否有可能找到时间复杂度为 O n n 的大 oh 的解决方案 我目前的想法是这样的 我们可以在 O n log n 中对数组进
  • 删除近排序数组中未排序/离群元素

    给定一个像这样的数组 15 14 12 3 10 4 2 1 我如何确定哪些元素乱序并删除它们 在本例中为数字 3 我不想对列表进行排序 而是检测异常值并将其删除 另一个例子 13 12 4 9 8 6 7 3 2 我希望能够删除 4 和

随机推荐

  • WCF - 如何有效发送 GUID(不是作为字符串)

    我有一个包含大量数据传输对象的集合 我需要将它们通过 WCF 发送到 Silverlight 客户端 我使用默认的 DataContractSerializer 和 HTTPS 通道 下面是一种 DTO 的示例 DataContract N
  • 如何在 node.js 上调试“错误:spawn ENOENT”?

    当我收到以下错误时 events js 72 throw er Unhandled error event Error spawn ENOENT at errnoException child process js 1000 11 at P
  • 通过 service-worker 的请求会被完成两次

    我做了一个简单的服务工作者来推迟我的 JS 应用程序失败的请求 以下这个例子 并且效果很好 但是当请求成功时我仍然遇到一个问题 请求完成了两次 一次正常 一次由服务人员由于fetch 打电话我猜 这是一个真正的问题 因为当客户端想要保存数据
  • 将图像嵌入 Jupyter Notebook 并导出为 HTML

    我正在 Windows 上使用 pycharm 运行 Python 3 7 我有一个 jupyter 笔记本 我想将图像嵌入到笔记本中 我知道使用 Markdown 语言进行标准嵌入的所有方法 但理想情况下我想要的是 A 通过 markdo
  • 如何在使用 Intent 集调用 Activity 后让 getIntent() 返回 null

    这个问题与我原来的问题类似 但我认为有更好的方法来解决问题 当 setIntent 后面跟着旋转时 getIntent 返回错误的意图 基本上 在我的主要Activity 这延伸了FragmentActivity 有两个实例在片段中我将意图
  • 如何在C#中使用迭代器反向读取文本文件

    我需要处理一个大文件 大约400K行和200M 但有时我必须从下往上处理 我如何在这里使用迭代器 yield return 基本上我不喜欢将所有内容加载到内存中 我知道在 NET 中使用迭代器效率更高 向后读取文本文件确实很棘手 除非您使用
  • 覆盖 R 中 C++ 编译标志的系统默认值

    我正在使用 RcppEigen 为我的 R 代码编写一些 C 函数 并且我想尽可能优化它们的编译 当我过去使用 Eigen 时 O3 和 fopenmp 给我带来了显着的提升 关注德克的advice 我编辑了 R Makevars 以便我的
  • EventLogQuery:如何形成查询字符串?

    我有以下代码 string query EventLogQuery elq new EventLogQuery Application PathType LogName query elq Session new EventLogSessi
  • Google Apps 脚本中的简单弹出窗口或对话框

    我正在寻找简单的代码 在我的 Google Apps 脚本 Ui 中添加一个弹出窗口 当我点击提交按钮时会出现该弹出窗口 弹出框将显示一条消息并有一个用于关闭弹出窗口的按钮 我已经看遍了所有地方 一切看起来都很复杂 而且做的事情比我需要做的
  • Jboss Fuse ESB 入门

    我是 ESB 新手 正在尝试了解 ESB 概念和实际用例 我研究了几个开源 ESB 产品 似乎 Apache Camel 是最有名的 一位 来自阿帕奇家族 我发现 大多数人使用在 Apache Camel 上开发的 Jboss Fuse 或
  • 焦点在 IE 中不起作用

    我有以下功能 function change var input document getElementById pas var input2 input cloneNode false input2 type password input
  • 本地主机的自签名 SSL 证书,如何使其可信

    我有一个 Owin 自托管 C 应用程序 它通过 127 0 0 1 5555 提供 Web API 服务 它只侦听本地主机 没有外部连接 这些 Web API 服务是使用 Ajax 从 AngularJS 应用程序调用的 顺便说一句 Ow
  • 使用 API 路由时,未授权时返回 Http Response 401,而不是重定向到登录页面

    我正在使用 MVC 和 WebAPI 构建一个 ASP NET Core 2 0 网站 以提供对一系列微服务的访问 WebAPI 控制器要求用户进行身份验证和授权 使用Authorize属性 任何未经授权或未登录的用户都会收到作为 MVC
  • Sun 的 Java 包命名约定:sun 与 com.sun

    在JRE中 Sun的内部包以2个顶级域 sun和com 为前缀 例如 com sun security jgss sun security jgss 对我来说 他们选择哪个前缀似乎很随机 我很好奇Sun 为此使用什么规则 不是问题的答案 但
  • 如何保证在粘贴之前参数完全宏展开?

    我有一个通用宏 define mSwitch Root Case Root Case Case define mSpecialDisplay what Val mSwitch mSpecialDisplay what Val define
  • Java可以连接通配符ssl吗

    我们希望购买通配符 SSL 证书 因为我们有很多子域 但是我不知道Java是否信任通配符证书 当人们通过 SSL 连接到我们的 API 时 我们不足以强制与我们通信的所有第三方将我们的 SSL 证书添加到他们的本地信任库中 目前 我面临着两
  • 使用Python获取pptx文件幻灯片的标题

    我正在尝试使用 Python 获取 powerpoint 文件的每张幻灯片的标题 我正在Python 中使用Presentation 包 但我找不到任何指定标题的内容 我有这段代码返回 powerpoint 文件的内容 但我需要指定标题 f
  • Angular 4 - 如何为 type='input' 渲染 2 位小数

    这个问题是关于当用户将数据输入数字类型的输入时限制 验证输入 我遇到的问题是 当模型首次加载时 任何整数或 1dp 的数字都仅以 1dp 渲染 例如 40 或 40 0 均显示为 40 0 而不是 40 00 我添加了此代码 以便在用户输入
  • AES 算法 - 解密问题

    我已经编写了AES解密代码 但没有成功 我的 AES 算法课程在这里 http pastebin com QtpFnW84和实施是 String Masterkey eX0XcsF8lkeX0XcsF8lkeX0XcsF8lkeX0XcsF
  • 用于 OpenGL ES 的多边形三角剖分为三角形带

    我正在寻找一个快速多边形三角剖分算法可以将不是很复杂的二维凹多边形 无孔 三角化为三角条准备发送到 OpenGL ES 进行绘图GL TRIANGLE STRIP 我知道一些算法 但我找不到适合我需要的算法 http www flipcod