- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
所以,过去一周半我一直在研究这个 .OBJ/.MTL 网格解析器。在这段时间里,我一直在追踪/修复很多错误、清理代码、记录代码等等。
问题是,每修复一个错误,仍然会出现这个问题,而且一张图片胜过一千个字......
使用 GL_LINE_LOOP
(注意:右侧的金字塔从球体向外倾斜是这里的问题)
使用 GL_TRIANGLES
更有趣的是,当这个“坏”顶点数据漂浮在场景周围时,它似乎会随着相机移动......只不过它会缩放并粘在网格之外。
这里奇怪的是,虽然我确信问题与内存有关,但我一直在检查与解析算法是否正常工作相矛盾的问题。经过一些单元测试,它似乎工作正常。
所以,我认为这可能是 Linux nVidia 驱动程序问题。我把驱动更新到下一个版本,重新启动,还是没有骰子。
经过深思熟虑,我一直在尝试找出以下代码中的错误。
//! every 3 vertices should represent a triangle, therefore we'll want to
//! use the indices to grab their corresponding vertices. Since the cross product
//! of two sides of every triangle (where one side = Vn - Vm, 'n' and 'm' being on the range of 1..3),
//! we first grab the three vertices, and then compute the normal using the their differences.
const uInt32 length = mesh->vertices.size();
//! declare a pointer to the vector so we can perform simple
//! memory copies to get the indices for each triangle within the
//! iteration.
GLuint* const pIndexBuf = &mesh->indices[ 0 ];
for ( uInt32 i = 0; i < length; i += 3 )
{
GLuint thisTriIndices[ 3 ];
memcpy( thisTriIndices, pIndexBuf + i, sizeof( GLuint ) * 3 );
vec3 vertexOne = vec3( mesh->vertices[ thisTriIndices[ 0 ] ] );
vec3 vertexTwo = vec3( mesh->vertices[ thisTriIndices[ 1 ] ] );
vec3 vertexThree = vec3( mesh->vertices[ thisTriIndices[ 2 ] ] );
vec3 sideOne = vertexTwo - vertexOne;
vec3 sideTwo = vertexThree - vertexOne;
vec3 surfaceNormal = glm::cross( sideOne, sideTwo );
mesh->normals.push_back( surfaceNormal );
}
图中当前显示的甚至没有法线数据,因此我们的想法是计算它的表面法线,因此有了上面的代码。虽然我已经进行了一些检查以查看索引数据是否在循环内正确加载,但我还没有找到任何内容。
我认为我布置内存的方式也可能有问题,但我不太清楚问题出在哪里。如果我错过了一些东西,我会加入 glVertexAttribPointer 调用:
//! Gen some buf handles
glGenBuffers( NUM_BUFFERS_PER_MESH, mesh->buffers );
//! Load the respective buffer data for the mesh
__LoadVec4Buffer( mesh->buffers[ BUFFER_VERTEX ], mesh->vertices ); //! positons
__LoadVec4Buffer( mesh->buffers[ BUFFER_COLOR ], mesh->colors ); //! material colors
__LoadVec3Buffer( mesh->buffers[ BUFFER_NORMAL ], mesh->normals ); //! normals
__LoadIndexBuffer( mesh->buffers[ BUFFER_INDEX ], mesh->indices ); //! indices
//! assign the vertex array a value
glGenVertexArrays( 1, &mesh->vertexArray );
//! Specify the memory layout for each attribute
glBindVertexArray( mesh->vertexArray );
//! Position and color are both stored in BUFFER_VERTEX.
glBindBuffer( GL_ARRAY_BUFFER, mesh->buffers[ BUFFER_VERTEX ] );
glEnableVertexAttribArray( meshProgram->attributes[ "position" ] );
glVertexAttribPointer( meshProgram->attributes[ "position" ], //! index
4, //! num vals
GL_FLOAT, GL_FALSE, //! value type, normalized?
sizeof( vec4 ), //! number of bytes until next value in the buffer
( void* ) 0 ); //! offset of the memory in the buffer
glBindBuffer( GL_ARRAY_BUFFER, mesh->buffers[ BUFFER_COLOR ] );
glEnableVertexAttribArray( meshProgram->attributes[ "color" ] );
glVertexAttribPointer( meshProgram->attributes[ "color" ],
4,
GL_FLOAT, GL_FALSE,
sizeof( vec4 ),
( void* ) 0 );
//! Now we specify the layout for the normals
glBindBuffer( GL_ARRAY_BUFFER, mesh->buffers[ BUFFER_NORMAL ] );
glEnableVertexAttribArray( meshProgram->attributes[ "normal" ] );
glVertexAttribPointer( meshProgram->attributes[ "normal" ],
3,
GL_FLOAT, GL_FALSE,
sizeof( vec3 ),
( void* )0 );
//! Include the index buffer within the vertex array
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, mesh->buffers[ BUFFER_INDEX ] );
glBindVertexArray( 0 );
至少任何方向正确的观点都会受到赞赏:我不知道这些问题的常见原因是什么。
编辑:根据请求发布抽奖代码
glBindVertexArray( mMeshes[ i ]->vertexArray );
UBO::LoadMatrix4( UBO::MATRIX_MODELVIEW, modelView.top() );
UBO::LoadMatrix4( UBO::MATRIX_PROJECTION, camera.projection() );
glDrawElements( GL_TRIANGLES, mMeshes[ i ]->indices.size(), GL_UNSIGNED_INT, ( void* )0 );
glBindVertexArray( 0 );
最佳答案
我找到了最终的罪魁祸首,结合@radical7的建议,这些解决了大部分问题。
// round mesh->indices.size() down if it's not already divisible by 3.
// the rounded value is stored in numTris
std::vector< vec4 > newVertices;
uInt32 indicesLen = Math_FloorForMultiple( mesh->indices.size(), 3 );
// declare a pointer to the vector so we can perform simple
// memory copies to get the indices for each triangle within the
// iteration.
newVertices.reserve( indicesLen );
const GLuint* const pIndexBuf = &mesh->indices[ 0 ];
for ( uInt32 i = 0; i < indicesLen; i += 3 )
{
const GLuint* const thisTriIndices = pIndexBuf + i;
vec4 vertexOne = mesh->vertices[ thisTriIndices[ 0 ] - 1 ];
vec4 vertexTwo = mesh->vertices[ thisTriIndices[ 1 ] - 1 ];
vec4 vertexThree = mesh->vertices[ thisTriIndices[ 2 ] - 1 ];
vec4 sideOne = vertexTwo - vertexOne;
vec4 sideTwo = vertexThree - vertexOne;
vec3 surfaceNormal = glm::cross( vec3( sideOne ), vec3( sideTwo ) );
mesh->normals.push_back( surfaceNormal );
mesh->normals.push_back( surfaceNormal + vec3( sideOne ) );
mesh->normals.push_back( surfaceNormal + vec3( sideTwo ) );
newVertices.push_back( vertexOne );
newVertices.push_back( vertexTwo );
newVertices.push_back( vertexThree );
}
mesh->vertices.clear();
mesh->vertices = newVertices;
请注意,当在循环中抓取顶点时,通过调用 mesh->vertices[ thisTriIndices[ x ] - 1 ]
,- 1
非常重要:OBJ 网格文件存储从 1...N 索引开始的面索引,而不是 0...N-1 索引。
索引本身也不应该用于绘制网格,而是作为从已经临时的顶点缓冲区中获取新的顶点缓冲区的一种方法:您使用索引来访问临时顶点中的元素,然后对于从临时缓冲区中获取的每个顶点,您将该顶点添加到新的缓冲区中。这样,您将获得以正确的绘制顺序指定的顶点数。因此,您只想使用顶点数组来绘制它们。
关于c++ - 不良顶点数据的常见陷阱/原因?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17333942/
正如问题所说,C++ 程序员在转向 Java 时面临哪些常见/主要问题?我正在寻找一些广泛的主题名称或示例以及工程师必须进行的日常调整。然后我可以去深入阅读这个。 我对多年来使用 C++ 并不得不使用
我们正在准备发布一个在过去一年中一直在开发的大型网络应用程序。我们即将开始集成 ActiveMerchant 的过程,以处理该服务的经常性订阅费用。 我正在寻找关于考虑到我们的要求(如下所列)的最佳实
您陷入过哪些 Powershell 陷阱? :-) 我的是: # ----------------------------------- function foo() { @("text")
对于商业数据库而言,数据库升级是一个优先级很高的事情,有版本升级路线图,有相应的补丁,而且对于方案还有一系列的演练,显然是一场硬仗。而在MySQL方向上,升级这件事情就被淡化了许多,好像只能证明它的
Android 新增了 AsyncLayoutInflater类到他们的支持库版本 24.0 和更高版本,并且可以在 Android SDK 4.0 或更高版本(几乎所有可用的设备)中使用。 根据 A
作为一名刚接触 Vala 的程序员,您对刚接触该语言的人的第一条建议是什么? 最佳答案 这很大程度上取决于您的背景。如果您来自 C/C++/Java,最好的建议是学习函数式编程。 Vala 支持真正的
作为 Spring 世界的新手,我认为如果有一个社区 Wiki 页面列出基于 Spring 的项目中常见的陷阱会很好。 这些包括: 被误解的概念 在 Spring 3.X 中不再推荐的 Spring
我正在开发一个脚本来管理一些陷阱。一开始我只用这段代码管理 INT 和 SIGTSTP,它工作得很好: #!/bin/bash function capture_traps() { echo
bash 中是否可以在函数退出时调用某些命令。我的意思是: function foo { # something like this maybe? trap "echo \"exit
我们在我们的域中托管了一个应用程序。所有用户都需要先通过 POST 表单登录。登录后,表单会自动重定向到我们网站上的仪表板页面。 是否可以允许一些客户托管他们自己的登录表单(在他们的网站上),然后发布
我有一个无窗口计时器(没有 WM_TIMER),它只在给定的时间段过去后触发一次回调函数。它作为 SetTimer()/KillTimer() 实现。时间段足够小:100-300 毫秒。 对于每个如此
我使用 Java 大约一个月了,总体而言仍然是编程方面的业余爱好者,所以如果我有什么不对的地方,请随时纠正我。也许我会提供一些多余的细节,但我现在很困惑,无法决定什么才是重要的。 因此,我一直在开发多
我正在开发一个需要使用 FileSystemWatcher 类的 C# 程序,以便在创建新文件时通知它。作为初始化的一部分,程序会扫描目录,以便处理其中已存在的任何文件。一切正常。 但是,在与另一位开
下面材料整理自Internet&著作。 STL中的容器按存储方式分为两类,一类是按以数组形式存储的容器(如:vector 、deque);另一类是以不连续的节点形式存储的容器(如:list
我正在使用 NuGet 包 Polly实现捕获故障转移 SQL 异常的重试逻辑。我在 Azure 中设置了 SQL Server Always On 高可用性。 我不想捕获所有 SQL 异常(这是不正
在编写 Scala RemoteActor 代码时,我注意到了一些陷阱: 必须设置 RemoteActor.classLoader = getClass().getClassLoader() 以避免“
出于某种原因,当我针对不存在的文件运行以下脚本时,我的脚本没有捕获异常。我基于我在网上找到的示例中的代码,但它似乎对我不起作用。 我将不胜感激有关如何解决此问题的任何提示或指示。 注意:在下面的例子中
我正在尝试从 R 调用 winBUGS 来估计逻辑回归。我正在使用以下代码: # Directorio de trabajo setwd("~/3 Diplomado/7 Bayesiana/8t1"
我正在尝试从 R 调用 winBUGS 来估计逻辑回归。我正在使用以下代码: # Directorio de trabajo setwd("~/3 Diplomado/7 Bayesiana/8t1"
我正在使用 ctypes 包装一个大型 C 库。 ctypesgen生成了包装代码(与我自己的做法相差不远)。作为包装 C 结构的 ctypes 的一部分,它们被制作为对象,其中一些在 C 中具有“s
我是一名优秀的程序员,十分优秀!