简体   繁体   English

C++: std::vector - std::find & std::distance 查询

[英]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 yz值的Vector3f对象)存储在std::vector<Vector3f> meshVertices ,然后在“游戏主循环”我循环每秒通过的每一个Vector3f中的对象meshVertices并检查其xz值对玩家xz价值,如果他们碰撞我设置了玩家高度为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 yz网格的每个Vector3f顶点的值在三个单独的std::vector<Vector3f> ,命名为meshVerticesXmechVerticesYmeshVerticesZ 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:现在每一秒我都会得到玩家位置的xz值(被转换为 int,因为我觉得让这个系统使用 int 值而不是浮点值会更容易稍后进行比较),然后将它们发送到检查函数通过返回bool来查看它们是否存在于前面提到的meshVerticesXmechVerticesZ ,负责此的代码如下:

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:函数checkMeshVerticesXcheckMeshVerticesZ如下:

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的( meshVerticesXmeshVerticesZ ),然后检查这些索引是否相等,如果相等, 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.这里的想法是,如果来自meshVerticesXmeshVerticesZ 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM