【发布时间】:2016-01-28 22:09:39
【问题描述】:
假设我们有一个 3D 网格,每个顶点都有纹理坐标,所以如果我打开它渲染它,我会得到这样的结果(忽略红色方块):
现在我正在尝试找到合适的算法来使用顶点 UV 来唯一地识别这些区域,并使用这个唯一的 id 值存储一个属性。我们的想法是将此值用作颜色表的索引并获得类似的东西(手工制作):
我尝试迭代每个顶点并找到比较纹理坐标的“未连接”三角形,但网格索引顺序似乎与 UV 的放置方式无关,或者我没有应用正确的公式。我毫不怀疑如何存储这个值并将其传递给着色器或其他任何东西,问题是如何知道顶点所属的“区域”,或者最终是像素。
谢谢。
更新: 用于渲染网格的数据是一个顶点列表 (GL_VERTEX_BUFFER) 加上一个索引列表 (GL_ELEMENT_ARRAY)。网格被渲染为 GL_TRIANGLES,每个顶点都是这样的结构:
struct Vertex
{
float x, y, z;
float nx, ny, nz;
float tcx, tcy;
float regionId; //the attribute I want to fill
};
struct MPUVRegionVertex
{
float x, y;
int faceId, regionId;
};
更新 2:我创建了一个新的 MPUVRegionVertex 顶点数组,每个索引都有一个元素(不是每个唯一顶点)。在@CsabaBálint 回复之后,我得到了以下代码:
MPUVRegionVertex* uvVertexData = new MPUVRegionVertex[indexCount];
for(int ic = 0; ic < indexCount / 3; ic++)
{
for(int vc = 0; vc < 3; vc++)
{
uvVertexData[3*ic+vc].x = vertexData[indexData[3*ic+vc]].tcx;
uvVertexData[3*ic+vc].y = vertexData[indexData[3*ic+vc]].tcy;
uvVertexData[3*ic+vc].faceId = ic;
}
}
std::vector<std::forward_list<int> > graph(indexCount);
for(int t1=0;t1 < indexCount; ++t1)
{
for(int t2 = t1 + 1; t2 < indexCount; ++t2)
{
if (uvVertexData[t1].faceId == uvVertexData[t2].faceId)
{
graph[t1].push_front(t2);
graph[t2].push_front(t1);
}
}
}
std::forward_list<int> stack;
std::vector<int> component(indexCount);
std::set<int> notvisited;
for(int nv = 0; nv < indexCount; nv++)
{
notvisited.insert(nv);
}
int k = 0;
while(notvisited.size() > 0)
{
stack.push_front(*notvisited.begin());
notvisited.erase(notvisited.begin());
while(!stack.empty())
{
//SOMETHING WRONG HERE
int temp = stack.front();
notvisited.erase(temp);
stack.pop_front();
component[temp] = k;
stack.merge(graph[temp]);
graph[temp].clear();
}
k++;
}
结果是每三个索引都有一个不同的 k,这意味着每个新三角形都会调用 k++,所以我在算法中遗漏了一些东西:S。
component[0]=0
component[1]=0
component[2]=0
component[3]=1
component[4]=1
component[5]=1
component[6]=2
component[7]=2
component[8]=2
component[9]=3
...
component[1778]=592
component[1779]=593
component[1780]=593
component[1781]=593
关于网格的一些信息:
Size of shape[0].indices: 1782
shape[0].positions: 1242
shape[0].texcoords: 828
shape[0].normals: 1242
更新 3
有关详细信息,每个顶点只有一个 UV 坐标。
到目前为止的扣除/规则:
- 一个顶点可以位于多个面上(多个三角形的一部分)。
- 顶点将在 vertexToFace 数组中出现 n 次,它所属的每个面一次。
- vertexToFace 数组中的第一个顶点将任意具有 regionId = 0。
- 如果一个顶点共享相同的 x 和 y 坐标或该区域中另一个顶点的相同面,则该顶点属于该区域。
如果我理解得很好,这是实现非递归图遍历的正确信息。我需要迭代并保存已连接和未连接的顶点,所有连接的顶点都将成为当前区域的一部分,所有未连接的顶点都将再次检查,第一次迭代存储第一个三角形顶点,第二次存储所有顶点“接触”第一个三角形的三角形,继续直到迭代没有给出新的连接顶点(如果我们只检查最后一次迭代中添加的顶点列表,则优化这里),没有添加新顶点意味着是时候增加 regionId 和从第一个未连接的顶点重新开始。
我将尝试按照该设计实现搜索。
【问题讨论】:
标签: c++ opengl shader vertex uv-mapping