处理鼠标和键盘事件的主要目的是控制相机,在 CG 中相机由拍摄方向(镜头方向),相机坐标系的向上方向,以及相机位置三个参数控制。由于在 MC 中玩家没有类似 FPS 游戏侧头瞄准那种转头,因此相机坐标系的向上方向一定是世界坐标系的 y 轴,故此处仅键盘鼠标需要控制相机方向front以及相机位置p。对于前者可使用鼠标控制,直接定义欧拉角,然后通过直角坐标系向球坐标转换即可。而对于后者,直接使用 WASD 控制镜头当前方向,此处需要注意的是,在 MC 中玩家操控时候的前后左右实际上是相对方向(front.x,0,front.z)的,也就是说相机的左右偏转角会影响玩家方向,但是俯仰角不会。
voidSubChunk::createMesh(){ this->mesh_ = newSubChunkMesh(); for (int x = 0; x < 16; x++) { for (int y = 0; y < 16; y++) { for (int z = 0; z < 16; z++) { auto b = getBlock(x, y, z); auto p = BlockPos{x, y, z}; if (b == air) continue; if (!hasBlock(x + 1, y, z)) mesh_->AddFace({px, b, p}); if (!hasBlock(x - 1, y, z)) mesh_->AddFace({nx, b, p}); if (!hasBlock(x, y + 1, z)) mesh_->AddFace({py, b, p}); if (!hasBlock(x, y - 1, z)) mesh_->AddFace({ny, b, p}); if (!hasBlock(x, y, z + 1)) mesh_->AddFace({pz, b, p}); if (!hasBlock(x, y, z - 1)) mesh_->AddFace({nz, b, p}); } } } mesh_->buildData(); }
voidSubChunkMesh::buildData(){ std::unordered_map<GLuint, std::vector<FacePointList>> temp_textures_ids_; for (auto &block : this->blocks_) { // 遍历每一个面 for (auto block_face : block.second) { auto face = static_cast<Face>(block_face.first); auto face_info = block_face.second; auto vs = createFaceVertices(face); auto normal = getFaceNormal(face); // 4个顶点 for (int i = 0; i < vs.size(); i++) { auto U = 0.0f, V = 0.0f; if (i == 1) V = 1.0f; if (i == 2) U = 1.0f; if (i == 3) { U = 1.0f, V = 1.0f; } auto vi = vs[i]; auto dx = static_cast<GLfloat>(vi % 2); auto dy = static_cast<GLfloat>(vi >= 4 ? 1 : 0); auto dz = static_cast<GLfloat>((vi % 4) >= 2 ? 1 : 0); VertexAttribute va{static_cast<GLfloat>(face_info.pos.x + dx), static_cast<GLfloat>(face_info.pos.y + dy), static_cast<GLfloat>(face_info.pos.z + dz), 1.0f,0.35f,0.21f,U,V, (float)normal.x, (float)normal.y, (float)normal.z}; this->vertices_.push_back(va); } auto size = (GLuint)vertices_.size(); FacePointList list{size - 4u, size - 3u, size - 2u, size - 3u, size - 2u, size - 1u}; temp_textures_ids_[TexturePool::instance().getTextureID(block_face.second.type, block_face.second.face)] .push_back(list); } }
for (auto &kv : temp_textures_ids_) { this->texture_mappings_[kv.first] = {6 * kv.second.size(), this->indices_.size()}; for (auto face : kv.second) { indices_.push_back(face.p1); indices_.push_back(face.p2); indices_.push_back(face.p3); indices_.push_back(face.p4); indices_.push_back(face.p5); indices_.push_back(face.p6); } } };