【发布时间】:2021-10-07 11:43:17
【问题描述】:
所以我目前正在处理一个大小为 16x256x16 的块,并为块类型创建一个整数网格。但我的问题是如何实现无限体素块??? 顺便说一句,我使用的是 SFML 1.6。
这是我的代码:
头文件(chunk.hpp):
#ifndef CHUNK_HPP
#define CHUNK_HPP
#pragma once
#include <SFML/Graphics.hpp>
#include "player.hpp"
#include "types.hpp"
#include "frustumcull.hpp"
#include "noise_generator.hpp"
const int horiz_chunksize = 16;
const int vert_chunksize = 256;
class Chunk {
public:
Chunk();
~Chunk();
int get(int x, int y, int z); // get block type in position
void set(int x, int y, int z, int type); // set block type in position
void render(Player &p, FrustumCull &cull, int renderDistance = 20); // render chunk
int getTerrainHeight(int x, int y); // returns noise height on the given position
private:
Perlin_Noise m_noise;
void update(int x, int y, int z, int type); // update block faces
};
#endif // CHUNK_HPP
来源(chunk.cpp):
我将 m_blockgrid 放在 .cpp 中,因为如果我将它放在标题中,它会 只画一个立方体,在 Chunk::~Chunk() delete[] chnk::m_blockgrid 中也有必要???
#include "chunk.hpp"
#include "block.hpp"
#include "maths.hpp"
#include <iostream>
namespace chnk {
int m_blockgrid[horiz_chunksize][vert_chunksize][horiz_chunksize]; // block grid
Block *m_block;
}
Chunk::Chunk() {
chnk::m_block = new Block(); // initialize block class
m_noise.setSeed(sf::Randomizer::Random(2736473, 8476864));
for(int x = 0; x < horiz_chunksize; x++) {
for(int z = 0; z < horiz_chunksize; z++) {
int heightmap = 16;
for(int y =-1; y < heightmap; y++) {
if(y > heightmap-2) set(x, y, z, BlockType::GRASS);
if(y < heightmap-1 && y > heightmap - 4) set(x, y, z, BlockType::DIRT);
if(y < heightmap-3 && y > 0) set(x, y, z, BlockType::STONE);
if(y == 0) set(x, y, z, BlockType::BEDROCK);
}
}
}
}
Chunk::~Chunk() {
delete[] chnk::m_blockgrid;
}
int Chunk::get(int x, int y, int z) {
// check boundary
if((x<0) || (x>=horiz_chunksize) ||
(y<0) || (y>=vert_chunksize) ||
(z<0) || (z>=horiz_chunksize)) return BlockType::AIR;
return chnk::m_blockgrid[x][y][z];
}
void Chunk::set(int x, int y, int z, int type) {
chnk::m_blockgrid[x][y][z] = type;
m_update = true;
}
void Chunk::render(Player &p, FrustumCull &cull, int renderDistance) {
int px = p.m_position.x / chnk::m_block->m_size;
int py = (p.m_position.y + p.m_bottom) / chnk::m_block->m_size;
int pz = p.m_position.z / chnk::m_block->m_size;
float radius = sqrt(Maths::sqr(chnk::m_block->m_size) * 5);
glEnable(GL_CULL_FACE); // hide back face
glEnable(GL_DEPTH_TEST); // depth testing
// render object(s)
for(int x = 0; x < horiz_chunksize; x++) {
for(int z = 0; z < horiz_chunksize; z++) {
for(int y = 0; y < vert_chunksize; y++) {
int type = get(x, y, z);
if(!cull.sphereInFrustum(sf::Vector3f(chnk::m_block->m_size * x + chnk::m_block->m_size / 2, chnk::m_block->m_size * y + chnk::m_block->m_size / 2, chnk::m_block->m_size * z + chnk::m_block->m_size / 2), radius)) continue;
update(x, y, z, type); // update for block texture & etc.
}
}
}
}
void Chunk::update(int x, int y, int z, int type) {
// only show face in outside not inside
// I use get(x, y, z) to get block position at given grid
if(BlockType::getSolidBlocks(type)) {
if(BlockType::getSolidBlocks(get(x, y+1, z)) == 0 && get(x, y+1, z) != type) {
chnk::m_block->setupBlock(x, y, z, Block::Top); // Top Face
}
if(BlockType::getSolidBlocks(get(x, y-1, z)) == 0 && get(x, y-1, z) != type) {
chnk::m_block->setupBlock(x, y, z, Block::Bottom); // Bottom Face
}
if(BlockType::getSolidBlocks(get(x, y, z-1)) == 0 && get(x, y, z-1) != type) {
chnk::m_block->setupBlock(x, y, z, Block::Front); // Front Face
}
if(BlockType::getSolidBlocks(get(x, y, z+1)) == 0 && get(x, y, z+1) != type) {
chnk::m_block->setupBlock(x, y, z, Block::Back); // Back Face
}
if(BlockType::getSolidBlocks(get(x-1, y, z)) == 0 && get(x-1, y, z) != type) {
chnk::m_block->setupBlock(x, y, z, Block::Left); // Left Face
}
if(BlockType::getSolidBlocks(get(x+1, y, z)) == 0 && get(x+1, y, z) != type) {
chnk::m_block->setupBlock(x, y, z, Block::Right); // Right Face
}
}
}
int Chunk::getTerrainHeight(int x, int y) {
return ( m_noise.getHeight(x, y) + 64 ); // total height of the given coordinates
}
有些人使用 unordered_map 来存储加载/卸载的块,但我不知道如何使用它以及它是否有效??
有人愿意帮助我吗? :)
【问题讨论】:
-
欢迎@rentheprogrammer。 “不减速”到底是什么意思:你想访问 O(k) 中的一个块吗?你想在 O(k) 中访问给定块内的特定块吗? “无限”有多大?
-
m_update 不包含在代码中,顺便说一句抱歉。 :)
-
@AdrianMaire O(k) 是什么?
-
"Big O" (en.wikipedia.org/wiki/Big_O_notation) 是一个表示算法在给定输入时有多快的符号。 O(k) 表示输入是什么,它在恒定时间内返回,O(n) 表示线性(就像迭代所有元素),O(n^2) 是......你猜对了吗?
-
@AdrianMaire 我真的不知道任何代数公式,但是我明白了,谢谢。