[英]C++: std::vector - std::find & std::distance query
To give context to my question I will describe what it is I am ultimately trying to achieve - I am developing a game, I have a .obj
model that I am using as my terrain and I must update the players height as they traverse the terrain (because the terrain is far from flat).为了给我的问题提供上下文,我将描述我最终想要实现的目标 - 我正在开发一个游戏,我有一个.obj
模型用作我的地形,我必须在玩家穿越地形时更新他们的高度(因为地势远非平坦)。 I am achieving this currently by doing the following - when I load the mesh ( terrain.obj
) I store all its vertices (each vertex is a Vector3f
object that has an x
y
and z
value) in a std::vector<Vector3f> meshVertices
, then every second in the "main game loop" I loop through every one of the Vector3f
objects in meshVertices
and check its x
and z
value against the players x
and z
value, if they are colliding I set the players height as the y
value of the matched Vector3f
object.我目前通过执行以下操作来实现这一点 - 当我加载网格( terrain.obj
)时,我将其所有顶点(每个顶点都是具有x
y
和z
值的Vector3f
对象)存储在std::vector<Vector3f> meshVertices
,然后在“游戏主循环”我循环每秒通过的每一个Vector3f
中的对象meshVertices
并检查其x
和z
值对玩家x
和z
价值,如果他们碰撞我设置了玩家高度为y
匹配的Vector3f
对象的值。
This system actually works and updates my players height as they traverse through the terrain, the only issue is this - my approach of checking every single mesh vertex against player position every second kills my frame rate, I need a much better system.这个系统实际上可以工作并在我的玩家穿越地形时更新他们的高度,唯一的问题是 - 我每秒检查每个网格顶点与玩家位置的方法会降低我的帧速率,我需要一个更好的系统。
I will now describe my new optimized approach in the attempt of saving my frame rate - Firstly, when creating the mesh I don't just store each Vector3f
vertex in a single std::vector<Vector3f>
, I store the x
y
and z
values of each Vector3f
vertex of the mesh in three seperate std::vector<Vector3f>
's, named meshVerticesX
, mechVerticesY
and meshVerticesZ
.我现在将描述我尝试保存帧速率的新优化方法 - 首先,在创建网格时,我不只是将每个Vector3f
顶点存储在单个std::vector<Vector3f>
,而是存储x
y
和z
网格的每个Vector3f
顶点的值在三个单独的std::vector<Vector3f>
,命名为meshVerticesX
、 mechVerticesY
和meshVerticesZ
。 These std::vector
's can be seen in the following code: These std::vector
可以在以下代码中看到:
for (Vector3f currentVertex : meshVertices) {
meshVerticesX.push_back((int)currentVertex.GetX());
}
for (Vector3f currentVertex : meshVertices) {
meshVerticesZ.push_back((int)currentVertex.GetZ());
}
for (Vector3f currentVertex : meshVertices) {
meshVerticesY.push_back((int)currentVertex.GetY());
}
Now every second I get the x
and z
value of the players position (casted to an int because I feel like making this system work with int values and not float values will be much easier for comparisons later) and then send them to functions that check to see if they exist in the before mentioned meshVerticesX
and mechVerticesZ
by returning a bool, the code responsible for this is as follows:现在每一秒我都会得到玩家位置的x
和z
值(被转换为 int,因为我觉得让这个系统使用 int 值而不是浮点值会更容易稍后进行比较),然后将它们发送到检查函数通过返回bool来查看它们是否存在于前面提到的meshVerticesX
和mechVerticesZ
,负责此的代码如下:
int playerPosX = (int) freeMoveObjects[0]->GetParent()->GetTransform()->GetPos()->GetX();
int playerPosZ = (int) freeMoveObjects[0]->GetParent()->GetTransform()->GetPos()->GetZ();
bool x = meshObjects[0]->checkMeshVerticesX(playerPosX);
bool z = meshObjects[0]->checkMeshVerticesZ(playerPosZ);
The functions checkMeshVerticesX
and checkMeshVerticesZ
are as follows:函数checkMeshVerticesX
和checkMeshVerticesZ
如下:
bool Mesh::checkMeshVerticesX(int playerPosX)
{
return std::find(meshVerticesX.begin(), meshVerticesX.end(), playerPosX) != meshVerticesX.end();
}
bool Mesh::checkMeshVerticesZ(int playerPosZ)
{
return std::find(meshVerticesZ.begin(), meshVerticesZ.end(), playerPosZ) != meshVerticesZ.end();
}
Using the returned boolean values (true if the players position was in the respective std::vector
or false if it was not) I then call another function ( getMeshYHeight
) that also gets passed the players x and z position that then checks the index of the respective std::vector
's ( meshVerticesX
& meshVerticesZ
) were the match was found, then checks if these indexes are equal and if so returns an int of that index from the meshVerticesY
std::vector
mentioned earlier, this code can be seen in the following:使用返回的布尔值(如果玩家位置在各自的std::vector
,则为 true,否则为 false),然后我调用另一个函数( getMeshYHeight
),该函数也传递了玩家 x 和 z 位置,然后检查找到匹配的相应std::vector
的( meshVerticesX
和meshVerticesZ
),然后检查这些索引是否相等,如果相等, meshVerticesY
前面提到的meshVerticesY
std::vector
返回该索引的 int,可以看到此代码在下面的:
if (x == true & z == true) {// boolean values returned by checkMeshVerticesX & checkMeshVerticesZ
int terrainVertexYHeight = meshObjects[0]->getMeshYHeight(playerPosX, playerPosZ);
freeMoveObjects[0]->GetParent()->GetTransform()->GetPos()->SetY(terrainVertexYHeight);
}
The function getMeshYHeight
is as follows:函数getMeshYHeight
如下:
int Mesh::getMeshYHeight(int playerXPos, int playerZPos) {//15/2/20
auto iterX = std::find(meshVerticesX.begin(), meshVerticesX.end(), playerXPos) != meshVerticesX.end();
auto iterZ = std::find(meshVerticesZ.begin(), meshVerticesZ.end(), playerZPos) != meshVerticesZ.end();
int indexX = std::distance(meshVerticesX.begin(), iterX);
int indexZ = std::distance(meshVerticesZ.begin(), iterZ);
if (indexX == indexZ)
{
return meshVerticesY[indexX];
}
}
The idea here is that if the index from the meshVerticesX
and meshVerticesZ
std::vectors
's for the original check match, then they must be the x and z values from an original Vector3f object when I first made the mesh as described earlier, and so that same index in meshVerticesY
must contain that same Vector3f
's objects y
value, therefore return it and use it to set the players height.这里的想法是,如果来自meshVerticesX
和meshVerticesZ
std::vectors
的原始检查的索引匹配,那么当我第一次创建网格时,它们必须是来自原始 Vector3f 对象的 x 和 z 值,并且所以meshVerticesY
中的相同索引必须包含相同的Vector3f
对象y
值,因此返回它并使用它来设置玩家高度。
The issue is that I cant even test if this works because the line of code int indexX = std::distance(meshVerticesX.begin(), iterX);
问题是我什至无法测试这是否有效,因为代码行int indexX = std::distance(meshVerticesX.begin(), iterX);
gives an error saying the arguments supplied to std::distance
are wrong (it says iterX
is a bool instead of an int
which is what I thought it would be).给出一个错误,说提供给std::distance
的参数是错误的(它说iterX
是一个 bool 而不是一个int
,这就是我认为的那样)。
So my question is - Firstly, if I diden't have this error would my approach even work?所以我的问题是 - 首先,如果我没有这个错误,我的方法会起作用吗? and if so, how can I fix the error?如果是这样,我该如何修复错误?
I kind of lost track of your logic somewhere in the middle there, but to address the issue at hand: iterX is a bool!我有点忘记了你在中间某个地方的逻辑,但要解决手头的问题:iterX 是一个布尔值!
auto iterX = std::find(...) != meshVerticesX.end();
In this statement, find returns an iterator, which you compare to another iterator, meshVerticesX.end().在此语句中,find 返回一个迭代器,您可以将它与另一个迭代器 meshVerticesX.end() 进行比较。 The result of that expression (the comparison operator) is a bool, which is then assigned to iterX, so auto deduces that iterX needs to be of type bool.该表达式(比较运算符)的结果是一个 bool,然后将其分配给 iterX,因此 auto 推断 iterX 需要是 bool 类型。
could you convert your terrain's x,y coordinates to ints, you may need to scale it, then when you load the mesh you could just store the z value for every x,y point (you may have to take some sort of average over the 1x1 square).你能不能把你的地形的 x,y 坐标转换成整数,你可能需要缩放它,然后当你加载网格时,你可以只存储每个 x,y 点的 z 值(你可能需要对1x1 正方形)。 Now you don't have to look for collisions, instead for each object in the game you can just look up it's z value by it's (scaled) x,y coordinates.现在您不必寻找碰撞,相反,对于游戏中的每个对象,您只需通过它的(缩放的)x,y 坐标查找它的 z 值。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.