- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
假设我们有一个 3D 网格,每个顶点都有纹理坐标,所以如果我渲染它展开,我会得到这样的东西(忽略红色方 block ):
现在我正在尝试找到合适的算法来使用顶点 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 坐标。
到目前为止的扣除/规则:
如果我没看错的话,这是实现非递归图遍历的正确信息。我需要迭代并保存连接和未连接的顶点,所有连接的顶点都将成为当前区域的一部分,所有不连接的顶点都将再次检查已连接的顶点,第一次迭代存储第一个三角形顶点,第二次存储所有顶点“接触”第一个三角形的三角形,继续直到迭代没有给出新的连接顶点(如果我们只检查上次迭代中添加的顶点列表,则此处优化),没有添加新顶点意味着是时候增加 regionId 和从第一个未连接的顶点重新开始。
我将尝试按照该设计实现搜索。
最佳答案
Now I'm trying to find the proper algorithm to uniquely identify those regions using the vertex UVs and storing an attribute with this unique id value.
创建图表
为顶点和面创建 id(给它们编号)。但要确保相同的顶点获得相同的 id-s,通过 UV 或位置进行比较。
创建一个 vector :std::vector<int> vertexToFace;
vertexToFace[i]==j
表示第 i 个顶点在 j 面上。
如果两个顶点在同一个面上,则它们是相邻的。
然后创建一个 std::vector<std::forward_list<int> > graph;
将顶点存储为 vector 索引,并添加邻居。 (O(n^2) 复杂度)
为此,您必须取第 i 个顶点,并且对于每个 j,您必须检查它们是否在同一面上。稍微优化的版本:
for(int i=0; i<n; ++i) for(int j=i+1; j <n ++j)
if (vertexToFace[i] == vertexToFace[j])
{
graph[i].push_front(j);
graph[j].push_front(i);
}
这是 O(n^2),但很容易实现。一个更难但更快的需要另一个 vector :std::vector<std::array<int,3>> faceToVertex;
,这样,从第 i 个顶点你可以在常数时间内访问它的邻居。无论哪种方式,我们都建立了一个图表,我们正在寻找 connected components。 , 这很容易 depth-first search .
实现连通分量算法
要实现这一点,您必须创建另一个 vector :std::vector<bool> visited(n,false);
, 和另一个 std::vector<int> component(n)
.您的问题的解决方案将在最后一个中。
算法简单,从顶点0开始,设visited[0] = true;
和 component[0]=0;
.然后对每个未访问的邻居做完全相同的事情,所以对于邻居 i(forward_list 的某个元素)if (!visited[i]) component[i] = 0;
,然后做同样的事情。当组件的所有元素都被访问时它停止。因此,您必须寻找一个未访问的元素,然后再次执行上述操作,但要知道您正在执行组件 1,依此类推。示例:
int l, k=0;
while(l!=n)
{
l=0;
while(visited[l]) l++;
fill_from(graph, visited, component, l, k);
++k;
}
我想你明白了,所以:(伪代码)
void fill_from(graph, visited, component, l, k)
{
if(visited[l]) return;
component[l] = k;
for(auto &i : graph[l])
fill_from(graph,visited,component,i,k);
}
然后我们完成了任务,但这还不是最快的解决方案。
更快的算法
为了更快,我们必须摆脱递归,之后我们不需要图表,使用 std::forward_list<int>
用于堆栈。将第一个顶点插入堆栈。然后弹出一个顶点,将其组件设置为 k。将 所有邻居 插入堆栈,然后删除邻居。换句话说,将邻居列表附加到堆栈(非常快的操作)。重复直到栈不为空。
这样我们就不会无限循环,因为如果我们回到同一个顶点,它就没有邻居,而且我们已经访问过它们。因此不需要访问 vector 。我们可以多次设置分量 vector 元素,但总是设置相同的值,所以为什么要检查它?
但是,如果我们没有访问过的 vector ,那么就很难找到我们没有访问过的另一个顶点。虽然我们可以在图中寻找一些仍然有邻居的顶点,但有更好的解决方案。
创建 std::set<int> notvisited();
对于那些还没有访问过的点。起初它应该包含所有顶点 ID,然后每次我们设置组件 ID 时,我们都会尝试从 notvisited
中删除一个顶点。放。我们重复从集合中获取一个顶点并运行 fill_from() 算法直到集合变空,同时,我们拥有所有组件 id-s。
更新:使用有关如何存储网格的更新信息。
如果您在“顶点列表”中没有相等的元素(为什么会这样),那么顶点的索引就是它在数组中的位置。这样,顶点的 id-s 就完成了。
三角形或面的 id-s 在“索引列表”中,让我将此数组命名为 int listOfIndices[];
,对于第j个面,与其相连的顶点为listOfIndices[3*j + 0]
, listOfIndices[3*j + 1]
和 listOfIndices[3*j + 2]
.要制作第一个 vector ,您必须执行以下操作:
std::vector<int> vertexToFace(num_of_verteces); //previously n
for(int j = 0; j < num_of_faces; ++j)
{
vertexToFace[listOfIndices[3*j + 0]]=j;
vertexToFace[listOfIndices[3*j + 1]]=j;
vertexToFace[listOfIndices[3*j + 2]]=j;
}
(建立逆关系的算法);请注意,在这种情况下,您甚至不需要不同的 faceToVertex
数组,因为你已经有了它(listOfIndices
),你只需要用不同的方式索引它(每次除以 3)。
关于c++ - 识别展开的网格 UV 区域,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33402857/
我使用的是linux的windows子系统,安装了ubuntu,bash运行流畅。 我正在尝试使用make,似乎bash 无法识别gcc。尝试将其添加到 PATH,但没有任何改变。奇怪的是 - cmd
ImageMagick 已正确安装。 WAMP 的“PHP 扩展”菜单也显示带有勾选的 php_imagick。除了 Apache 和系统环境变量外,phpinfo() 没有显示任何 imagick
我是这么想的,因为上限是 2^n,并且考虑到它们都是有限机,n 状态 NFA 和具有 2^n 或更少状态的 DFA 的交集将是有效。 我错了吗? 最佳答案 你是对的。 2^n 是一个上限,因此生成的
我有一个大型数据集,其中包含每日值,指示一年中的特定一天是否特别热(用 1 或 0 表示)。我的目标是识别 3 个或更多特别炎热的日子的序列,并创建一个包含每个日子的长度以及开始和结束日期的新数据集。
我有一个向量列表,每个向量看起来像这样 c("Japan", "USA", "country", "Japan", "source", "country", "UK", "source", "coun
是否有任何工具或方法可以识别静态定义数组中的缓冲区溢出(即 char[1234] 而不是 malloc(1234))? 昨天我花了大部分时间来追踪崩溃和奇怪的行为,最终证明是由以下行引起的: // e
我一直在尝试通过导入制表符分隔的文件来手动创建 Snakemake 通配符,如下所示: dataset sample species frr PRJNA493818_GSE120639_SRP1628
我一直在尝试通过导入制表符分隔的文件来手动创建 Snakemake 通配符,如下所示: dataset sample species frr PRJNA493818_GSE120639_SRP1628
我想录下某人的声音,然后根据我获得的关于他/她声音的信息,如果那个人再次说话,我就能认出来!问题是我没有关于哪些统计数据(如频率)导致人声差异的信息,如果有人可以帮助我如何识别某人的声音? 在研究过程
我希望我的程序能够识别用户何时按下“enter”并继续循环播放。但是我不知道如何使程序识别“输入”。尝试了两种方法: string enter; string ent = "\n"; dice d1;
我创建了这个带有一个参数(文件名)的 Bash 小脚本,该脚本应该根据文件的扩展名做出响应: #!/bin/bash fileFormat=${1} if [[ ${fileFormat} =~ [F
我正在寻找一种在 for 循环内迭代时识别 subview 对象的方法,我基本上通过执行 cell.contentView.subviews 从 UITableView 的 contentView 获
我正在尝试在 Swift 中使用 CallKit 来识别调用者。 我正在寻找一种通过发出 URL 请求来识别调用者的方法。 例如:+1-234-45-241 给我打电话,我希望它向 mydomain.
我将(相当古老的)插件称为“thickbox”,如下所述: 创建厚盒时,它包含基于查询的内容列表。 使用 JavaScript 或 jQuery,我希望能够访问 type 的值(在上面的示例中 t
我想编写一些可以接受某种输入并将其识别为方波、三角波或某种波形的代码。我还需要一些产生所述波的方法。 我确实有使用 C/C++ 的经验,但是,我不确定我将如何模拟所有这些。最终,我想将其转换为微 Co
我创建了一个 for 循环,用于在每个部分显示 8 个项目,但我试图在循环中识别某些项目。例如,我想识别前两项,然后是第五项和第六项,但我的识别技术似乎是正确的。 for (int i = 0; i
如何识别 UIStoryboard? 该类具有创建和实例化的方法,但我没有看到带有类似name 的@property。例如 获取 Storyboard对象 + storyboardWithName:b
如何确定所运行的SQLServer2005的版本 要确定所运行的SQLServer2005的版本,请使用SQLServerManagementStudio连接到SQLServer2005,然后运行
这个问题在这里已经有了答案: How to check whether an object is a date? (26 个答案) 关闭2 年前。 我正在使用一个 npm 模块,它在错误时抛出一个空
我正在制作一个使用 ActivityRecognition API 在后台跟踪用户 Activity 的应用,如果用户在指定时间段(例如 1 小时)内停留在同一个地方,系统就会推送通知告诉用户去散步.
我是一名优秀的程序员,十分优秀!