Opengl es 对多边形进行细分和三角剖分
我得到一个随机轮廓作为输入。我需要将其转换为多边形并在三维空间中显示(A) 通常,我会通过一个标准的耳朵剪辑算法来做,结果会像(B) 然而,由于我正在开发的视频卡(VIVANTE GC 2000)的图形驱动程序中存在一个bug,我只能对这样的小形状进行三角剖分。原因是,在渲染时,如果网格顶点位于截锥体左侧或右侧太远的外部,则位置计算不正确。这会导致屏幕上大网格的剧烈闪烁和变形。 这是一个已确认的驱动程序问题,在其他平台上,甚至同一显卡的旧版本驱动程序上都不会发生这种情况。不幸的是,我不能使用旧的驱动程序,而且卡制造商也不太可能修复这个bug,因为它已经被知道了将近十年 下面是一个关于这个问题的更深入的线程 所以我得用拐杖。换句话说,我必须将网格分割成几个较小的三角形,比如(C) 因此,在任何时间点,渲染的三角形的顶点都不会离平截头体太远 不幸的是,在我看来,真的没有别的办法。我知道这是一个非常不雅观的解决方案,但实际上没有其他方法可以绕过驱动程序错误 但我被困在实际做这件事上了。不知何故,我无法思考如何生成三角化数据(A->C)。有人能以这种方式帮助我分割/三角剖分网格的算法吗?假设所有“正方形”都是N乘N的正方形,其中N由我指定 也许有人对我如何处理这个问题提出了其他建议Opengl es 对多边形进行细分和三角剖分,opengl-es,mesh,triangulation,Opengl Es,Mesh,Triangulation,我得到一个随机轮廓作为输入。我需要将其转换为多边形并在三维空间中显示(A) 通常,我会通过一个标准的耳朵剪辑算法来做,结果会像(B) 然而,由于我正在开发的视频卡(VIVANTE GC 2000)的图形驱动程序中存在一个bug,我只能对这样的小形状进行三角剖分。原因是,在渲染时,如果网格顶点位于截锥体左侧或右侧太远的外部,则位置计算不正确。这会导致屏幕上大网格的剧烈闪烁和变形。 这是一个已确认的驱动程序问题,在其他平台上,甚至同一显卡的旧版本驱动程序上都不会发生这种情况。不幸的是,我不能使用旧的
< P>我猜你可以考虑在你有B之后继续细分每一个三角形,像这样: 根据需要设置尽可能多的细分: 所以,我成功了 构思大纲:
- 画一个等高线
- 计算横穿X和Y的等分线(可以是多条线
- 将初始轮廓细分为“切片”,在特定Y坐标上对分
- 遍历每个切片并在特定的X坐标上分割其边
- 对每个生成的子图进行三角剖分
- 细分非凸轮廓:
- 耳削三角测量:
public triangulation输出三角形subdivide(列表等高线)
{
//清除列表并重置变量
input.clear();
polygonVerts.clear();;
凸面。清除();
反射波清除();
清晰的;
earVerts.clear();
canBeEars.clear();
角=空;
uniqueVectors.clear();
列表结果=新建ArrayList();
//如果列表为顺时针方向,则反转顶点的顺序
if(逆时针(轮廓))
{
收藏。反向(等高线);
}
//查找图形中最左侧和最顶部的点
Vector2f top=轮廓。获取(0);
Vector2f left=轮廓。获取(0);
Vector2f-bottom=等高线.get(0);
Vector2f right=轮廓。获取(0);
对于(int i=1;i顶部y)
top=电流;
if(当前y<底部y)
底部=电流;
如果(当前.x<左.x)
左=电流;
如果(当前.x>右.x)
右=电流;
}
//检查整个网格是否适合该空间
if((Math.abs(top.y-bottom.y)bottom.y)
{
linesY.add(lineCoord);
lineCoord-=GlobalSettings.OPT_MAX_DISTANCE;
}
List linesX=new ArrayList();
lineCoord=((float)((int)(right.x/GlobalSettings.OPT_MAX_DISTANCE))*GlobalSettings.OPT_MAX_DISTANCE;
而(lineCoord>left.x)
{
linesX.add(lineCoord);
lineCoord-=GlobalSettings.OPT_MAX_DISTANCE;
}
列表子画面=新建ArrayList();
List contourCpy=new ArrayList();
contourCpy.addAll(轮廓);
对于(int i=0;i=contourCpy.size()?0:(j+1);
Vector2f next=contourCpy.get(索引);
//确定顶点位于直线的哪一侧,或者它们是否直接位于直线上
VertexStatus vsCurrent=新的VertexStatus(当前,yCoord,true);
VertexStatus vsNext=新的VertexStatus(next,yCoord,true);
VertexStatus vsPrevious=新的VertexStatus(previous,yCoord,true);
if(vsPrevious.isOn()&&vsCurrent.isOn()&&vsNext.isOn())
{
//相邻边完全位于直线上
继续;
}
if(vsCurrent.isOn())
{
//如果它位于th上,则添加点
public TriangulationOutput triangulateSubdivide(List<Vector2f> contour)
{
// clear lists and reset variables
input.clear();
polygonVerts.clear();;
convexVerts.clear();
reflexVerts.clear();
straightVerts.clear();
earVerts.clear();
canBeEars.clear();
corner = null;
uniqueVectors.clear();
List<Triangle> result = new ArrayList<>();
// Reverse the order of verts if the list is clockwise
if (isClockwise(contour))
{
Collections.reverse(contour);
}
// find leftmost and topmost points in the
Vector2f top = contour.get(0);
Vector2f left = contour.get(0);
Vector2f bottom = contour.get(0);
Vector2f right = contour.get(0);
for (int i = 1; i < contour.size(); i++)
{
Vector2f current = contour.get(i);
if (current.y > top.y)
top = current;
if (current.y < bottom.y)
bottom = current;
if (current.x < left.x)
left = current;
if (current.x > right.x)
right = current;
}
// check if the entire mesh fits within the space
if ((Math.abs(top.y - bottom.y) <= GlobalSettings.OPT_MAX_DISTANCE)&&(Math.abs(right.x - left.x) <= GlobalSettings.OPT_MAX_DISTANCE))
{
// I haven't tested this edge case yet, but it's not really relevant to the algorythm
System.err.println("TriangulateSubdivide -> shortcut used");
return new TriangulationOutput(triangulateSimple(contour), contour);
//TODO: Could be trouble
}
//Find X and Y split coordinates
List<Float> linesY = new ArrayList<>();
float lineCoord = ((float)((int)(top.y / GlobalSettings.OPT_MAX_DISTANCE))) * GlobalSettings.OPT_MAX_DISTANCE;
while (lineCoord > bottom.y)
{
linesY.add(lineCoord);
lineCoord -= GlobalSettings.OPT_MAX_DISTANCE;
}
List<Float> linesX = new ArrayList<>();
lineCoord = ((float)((int)(right.x / GlobalSettings.OPT_MAX_DISTANCE))) * GlobalSettings.OPT_MAX_DISTANCE;
while (lineCoord > left.x)
{
linesX.add(lineCoord);
lineCoord -= GlobalSettings.OPT_MAX_DISTANCE;
}
List<List<Vector2f>> submeshes = new ArrayList<>();
List<Vector2f> contourCpy = new ArrayList<>();
contourCpy.addAll(contour);
for (int i = 0; i < linesY.size(); i++)
{
List<Vector2f> submesh;
List<Vector2f> intersections = new ArrayList<>();
float yCoord = linesY.get(i);
// split polygon edges on dividing horizontal lines
// store found intersections to find them easier later
for (int j = 0; j < contourCpy.size(); j++)
{
Vector2f current = contourCpy.get(j);
int index = (j - 1) < 0 ? contourCpy.size()-1 : (j - 1);
Vector2f previous = contourCpy.get(index);
index = (j + 1) >= contourCpy.size() ? 0 : (j + 1);
Vector2f next = contourCpy.get(index);
// determines on which side of the line vertexes lie, or if they lie directly on it
VertexStatus vsCurrent = new VertexStatus(current, yCoord, true);
VertexStatus vsNext = new VertexStatus(next, yCoord, true);
VertexStatus vsPrevious = new VertexStatus(previous, yCoord, true);
if (vsPrevious.isOn() && vsCurrent.isOn() && vsNext.isOn())
{
// adjacient edges lie completely on the line
continue;
}
if (vsCurrent.isOn())
{
// add point if it lies on the line
intersections.add(current);
}
else if ((vsCurrent.status() != vsNext.status()) && (!vsNext.isOn()))
{
// line intersects current edge in a point other than vertexes
float x = current.x + ((yCoord - current.y)*(next.x - current.x)) / (next.y - current.y);
Vector2f ip = new Vector2f(x, yCoord);
intersections.add(ip);
contourCpy.add(index, ip); //TODO: possible trouble at last node
j++; //increment to skip the point we just added
}
}
//sort intersections
intersections.sort(new Comparator<Vector2f>()
{
@Override
public int compare(Vector2f v1, Vector2f v2)
{
return (v1.x < v2.x) ? -1 : 1;
}
});
// find submeshes that lie above the line. Every two intersections
for (int j = 0; j < intersections.size(); j+=2)
{
// for every two points we find a linked submesh
submesh = new ArrayList<>();
int indexEnd = contourCpy.indexOf(intersections.get(j));
int indexStart = contourCpy.indexOf(intersections.get(j+1));
int index = indexStart;
boolean cont = true;
while (contourCpy.size() > 0)
{
submesh.add(contourCpy.get(index));
if (index == indexEnd)
{
break;
}
if ((index != indexStart))
{
// remove points between intersections from future countour
contourCpy.remove(index);
if (index < indexEnd)
{
indexEnd--;
}
}
else
{
index++;
}
if (index >= contourCpy.size())
{
index = 0;
}
}
//while (index != indexEnd);
submeshes.add(submesh);
}
}
// add the remaining contour as final bottom-most mesh
submeshes.add(contourCpy);
for (List<Vector2f> submesh : submeshes)
{
// Add more vertexes for X coord divisions
for (int i = 0; i < submesh.size(); i++)
{
Vector2f current = submesh.get(i);
// add current vector to unique
boolean add = true;
for (int v = 0; v < uniqueVectors.size(); v++)
{
if (uniqueVectors.get(v).equals(current))
{
add = false;
break;
}
}
if (add)
{
uniqueVectors.add(current);
}
int index = (i + 1) >= submesh.size() ? 0 : (i + 1);
Vector2f next = submesh.get(index);
for (int j = 0; j < linesX.size(); j++)
{
float xCoord = linesX.get(j);
VertexStatus vsCurrent = new VertexStatus(current, xCoord, false);
VertexStatus vsNext = new VertexStatus(next, xCoord, false);
if (vsCurrent.isOn() || vsNext.isOn())
{
continue;
}
if (vsCurrent.status() != vsNext.status())
{
// vectors lie on different sides of xCoord
float y = current.y + ((next.y - current.y)*(xCoord - current.x)) / (next.x - current.x);
Vector2f ip = new Vector2f(xCoord, y);
// add current vector to unique
add = true;
for (int v = 0; v < uniqueVectors.size(); v++)
{
if (uniqueVectors.get(v).equals(ip))
{
ip = uniqueVectors.get(v);
add = false;
break;
}
}
if (add)
{
uniqueVectors.add(ip);
}
submesh.add(index,ip);
//TODO: possible trouble here
if (current.x > next.x)
{
index++;
}
i++;
}
}
}
result.addAll(triangulateSimple(submesh));
}
// this basically just stores triangles and a list of vertexes and doesn't do anything else.
return new TriangulationOutput(result, uniqueVectors);
}