#include "profiler.h"
#include "settings.h"
#include "camera.h" // CameraModes
-#include "util/mathconstants.h"
#include "util/basic_macros.h"
#include <algorithm>
+#include "client/renderingengine.h"
ClientMap::ClientMap(
Client *client,
- IGameDef *gamedef,
MapDrawControl &control,
- scene::ISceneNode* parent,
- scene::ISceneManager* mgr,
s32 id
):
- Map(dout_client, gamedef),
- scene::ISceneNode(parent, mgr, id),
+ Map(dout_client, client),
+ scene::ISceneNode(RenderingEngine::get_scene_manager()->getRootSceneNode(),
+ RenderingEngine::get_scene_manager(), id),
m_client(client),
m_control(control),
m_camera_position(0,0,0),
ClientMap::~ClientMap()
{
- /*MutexAutoLock lock(mesh_mutex);
-
- if(mesh != NULL)
- {
- mesh->drop();
- mesh = NULL;
- }*/
}
MapSector * ClientMap::emergeSector(v2s16 p2d)
ISceneNode::OnRegisterSceneNode();
}
-static bool isOccluded(Map *map, v3s16 p0, v3s16 p1, float step, float stepfac,
- float start_off, float end_off, u32 needed_count, INodeDefManager *nodemgr)
-{
- float d0 = (float)BS * p0.getDistanceFrom(p1);
- v3s16 u0 = p1 - p0;
- v3f uf = v3f(u0.X, u0.Y, u0.Z) * BS;
- uf.normalize();
- v3f p0f = v3f(p0.X, p0.Y, p0.Z) * BS;
- u32 count = 0;
- for(float s=start_off; s<d0+end_off; s+=step){
- v3f pf = p0f + uf * s;
- v3s16 p = floatToInt(pf, BS);
- MapNode n = map->getNodeNoEx(p);
- bool is_transparent = false;
- const ContentFeatures &f = nodemgr->get(n);
- if(f.solidness == 0)
- is_transparent = (f.visual_solidness != 2);
- else
- is_transparent = (f.solidness != 2);
- if(!is_transparent){
- count++;
- if(count >= needed_count)
- return true;
- }
- step *= stepfac;
- }
- return false;
-}
-
-void ClientMap::getBlocksInViewRange(v3s16 cam_pos_nodes,
+void ClientMap::getBlocksInViewRange(v3s16 cam_pos_nodes,
v3s16 *p_blocks_min, v3s16 *p_blocks_max)
{
v3s16 box_nodes_d = m_control.wanted_range * v3s16(1, 1, 1);
if not seen on display
*/
- if (block->mesh != NULL)
+ if (block->mesh)
block->mesh->updateCameraOffset(m_camera_offset);
float range = 100000 * BS;
- if (m_control.range_all == false)
+ if (!m_control.range_all)
range = m_control.wanted_range * BS;
float d = 0.0;
/*
Ignore if mesh doesn't exist
*/
- if (block->mesh == NULL) {
+ if (!block->mesh) {
blocks_in_range_without_mesh++;
continue;
}
/*
Occlusion culling
*/
- v3s16 cpn = block->getPos() * MAP_BLOCKSIZE;
- cpn += v3s16(MAP_BLOCKSIZE / 2, MAP_BLOCKSIZE / 2, MAP_BLOCKSIZE / 2);
- float step = BS * 1;
- float stepfac = 1.1;
- float startoff = BS * 1;
- // The occlusion search of 'isOccluded()' must stop short of the target
- // point by distance 'endoff' (end offset) to not enter the target mapblock.
- // For the 8 mapblock corners 'endoff' must therefore be the maximum diagonal
- // of a mapblock, because we must consider all view angles.
- // sqrt(1^2 + 1^2 + 1^2) = 1.732
- float endoff = -BS * MAP_BLOCKSIZE * 1.732050807569;
- v3s16 spn = cam_pos_nodes;
- s16 bs2 = MAP_BLOCKSIZE / 2 + 1;
- // to reduce the likelihood of falsely occluded blocks
- // require at least two solid blocks
- // this is a HACK, we should think of a more precise algorithm
- u32 needed_count = 2;
- if (occlusion_culling_enabled &&
- // For the central point of the mapblock 'endoff' can be halved
- isOccluded(this, spn, cpn,
- step, stepfac, startoff, endoff / 2.0f, needed_count, m_nodedef) &&
- isOccluded(this, spn, cpn + v3s16(bs2,bs2,bs2),
- step, stepfac, startoff, endoff, needed_count, m_nodedef) &&
- isOccluded(this, spn, cpn + v3s16(bs2,bs2,-bs2),
- step, stepfac, startoff, endoff, needed_count, m_nodedef) &&
- isOccluded(this, spn, cpn + v3s16(bs2,-bs2,bs2),
- step, stepfac, startoff, endoff, needed_count, m_nodedef) &&
- isOccluded(this, spn, cpn + v3s16(bs2,-bs2,-bs2),
- step, stepfac, startoff, endoff, needed_count, m_nodedef) &&
- isOccluded(this, spn, cpn + v3s16(-bs2,bs2,bs2),
- step, stepfac, startoff, endoff, needed_count, m_nodedef) &&
- isOccluded(this, spn, cpn + v3s16(-bs2,bs2,-bs2),
- step, stepfac, startoff, endoff, needed_count, m_nodedef) &&
- isOccluded(this, spn, cpn + v3s16(-bs2,-bs2,bs2),
- step, stepfac, startoff, endoff, needed_count, m_nodedef) &&
- isOccluded(this, spn, cpn + v3s16(-bs2,-bs2,-bs2),
- step, stepfac, startoff, endoff, needed_count, m_nodedef)) {
+ if (occlusion_culling_enabled && isBlockOccluded(block, cam_pos_nodes)) {
blocks_occlusion_culled++;
continue;
}
struct MeshBufListList
{
- std::vector<MeshBufList> lists;
+ /*!
+ * Stores the mesh buffers of the world.
+ * The array index is the material's layer.
+ * The vector part groups vertices by material.
+ */
+ std::vector<MeshBufList> lists[MAX_TILE_LAYERS];
void clear()
{
- lists.clear();
+ for (int l = 0; l < MAX_TILE_LAYERS; l++)
+ lists[l].clear();
}
- void add(scene::IMeshBuffer *buf)
+ void add(scene::IMeshBuffer *buf, u8 layer)
{
- for(std::vector<MeshBufList>::iterator i = lists.begin();
- i != lists.end(); ++i){
- MeshBufList &l = *i;
- video::SMaterial &m = buf->getMaterial();
-
+ // Append to the correct layer
+ std::vector<MeshBufList> &list = lists[layer];
+ const video::SMaterial &m = buf->getMaterial();
+ for (MeshBufList &l : list) {
// comparing a full material is quite expensive so we don't do it if
// not even first texture is equal
if (l.m.TextureLayer[0].Texture != m.TextureLayer[0].Texture)
}
}
MeshBufList l;
- l.m = buf->getMaterial();
+ l.m = m;
l.bufs.push_back(buf);
- lists.push_back(l);
+ list.push_back(l);
}
};
Measuring time is very useful for long delays when the
machine is swapping a lot.
*/
- int time1 = time(0);
+ std::time_t time1 = time(0);
/*
Get animation parameters
MapBlock *block = i->second;
// If the mesh of the block happened to get deleted, ignore it
- if (block->mesh == NULL)
+ if (!block->mesh)
continue;
float d = 0.0;
continue;
// Mesh animation
- {
+ if (pass == scene::ESNRP_SOLID) {
//MutexAutoLock lock(block->mesh_mutex);
MapBlockMesh *mapBlockMesh = block->mesh;
assert(mapBlockMesh);
MapBlockMesh *mapBlockMesh = block->mesh;
assert(mapBlockMesh);
- scene::IMesh *mesh = mapBlockMesh->getMesh();
- assert(mesh);
-
- u32 c = mesh->getMeshBufferCount();
- for (u32 i = 0; i < c; i++)
- {
- scene::IMeshBuffer *buf = mesh->getMeshBuffer(i);
+ for (int layer = 0; layer < MAX_TILE_LAYERS; layer++) {
+ scene::IMesh *mesh = mapBlockMesh->getMesh(layer);
+ assert(mesh);
- buf->getMaterial().setFlag(video::EMF_TRILINEAR_FILTER, m_cache_trilinear_filter);
- buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, m_cache_bilinear_filter);
- buf->getMaterial().setFlag(video::EMF_ANISOTROPIC_FILTER, m_cache_anistropic_filter);
- buf->getMaterial().setFlag(video::EMF_WIREFRAME, m_control.show_wireframe);
+ u32 c = mesh->getMeshBufferCount();
+ for (u32 i = 0; i < c; i++) {
+ scene::IMeshBuffer *buf = mesh->getMeshBuffer(i);
- const video::SMaterial& material = buf->getMaterial();
- video::IMaterialRenderer* rnd =
+ video::SMaterial& material = buf->getMaterial();
+ video::IMaterialRenderer* rnd =
driver->getMaterialRenderer(material.MaterialType);
- bool transparent = (rnd && rnd->isTransparent());
- if (transparent == is_transparent_pass) {
- if (buf->getVertexCount() == 0)
- errorstream << "Block [" << analyze_block(block)
- << "] contains an empty meshbuf" << std::endl;
- drawbufs.add(buf);
+ bool transparent = (rnd && rnd->isTransparent());
+ if (transparent == is_transparent_pass) {
+ if (buf->getVertexCount() == 0)
+ errorstream << "Block [" << analyze_block(block)
+ << "] contains an empty meshbuf" << std::endl;
+
+ material.setFlag(video::EMF_TRILINEAR_FILTER,
+ m_cache_trilinear_filter);
+ material.setFlag(video::EMF_BILINEAR_FILTER,
+ m_cache_bilinear_filter);
+ material.setFlag(video::EMF_ANISOTROPIC_FILTER,
+ m_cache_anistropic_filter);
+ material.setFlag(video::EMF_WIREFRAME,
+ m_control.show_wireframe);
+
+ drawbufs.add(buf, layer);
+ }
}
}
}
}
- std::vector<MeshBufList> &lists = drawbufs.lists;
-
- int timecheck_counter = 0;
- for (std::vector<MeshBufList>::iterator i = lists.begin();
- i != lists.end(); ++i) {
- timecheck_counter++;
- if (timecheck_counter > 50) {
- timecheck_counter = 0;
- int time2 = time(0);
- if (time2 > time1 + 4) {
- infostream << "ClientMap::renderMap(): "
- "Rendering takes ages, returning."
- << std::endl;
- return;
+ // Render all layers in order
+ for (int layer = 0; layer < MAX_TILE_LAYERS; layer++) {
+ std::vector<MeshBufList> &lists = drawbufs.lists[layer];
+
+ int timecheck_counter = 0;
+ for (MeshBufList &list : lists) {
+ timecheck_counter++;
+ if (timecheck_counter > 50) {
+ timecheck_counter = 0;
+ std::time_t time2 = time(0);
+ if (time2 > time1 + 4) {
+ infostream << "ClientMap::renderMap(): "
+ "Rendering takes ages, returning."
+ << std::endl;
+ return;
+ }
}
- }
-
- MeshBufList &list = *i;
- driver->setMaterial(list.m);
+ driver->setMaterial(list.m);
- for (std::vector<scene::IMeshBuffer*>::iterator j = list.bufs.begin();
- j != list.bufs.end(); ++j) {
- scene::IMeshBuffer *buf = *j;
- driver->drawMeshBuffer(buf);
- vertex_count += buf->getVertexCount();
- meshbuffer_count++;
+ for (scene::IMeshBuffer *buf : list.bufs) {
+ driver->drawMeshBuffer(buf);
+ vertex_count += buf->getVertexCount();
+ meshbuffer_count++;
+ }
}
-
}
} // ScopeProfiler
};
if(z_directions[0].X < -99){
for(u32 i=0; i<sizeof(z_directions)/sizeof(*z_directions); i++){
+ // Assumes FOV of 72 and 16/9 aspect ratio
z_directions[i] = v3f(
- 0.01 * myrand_range(-100, 100),
+ 0.02 * myrand_range(-100, 100),
1.0,
0.01 * myrand_range(-100, 100)
- );
+ ).normalize();
z_offsets[i] = 0.01 * myrand_range(0,100);
}
}
std::vector<int> values;
for(u32 i=0; i<sizeof(z_directions)/sizeof(*z_directions); i++){
v3f z_dir = z_directions[i];
- z_dir.normalize();
core::CMatrix4<f32> a;
a.buildRotateFromTo(v3f(0,1,0), z_dir);
v3f dir = m_camera_direction;
const ContentFeatures& features = m_nodedef->get(n);
video::SColor post_effect_color = features.post_effect_color;
if(features.solidness == 2 && !(g_settings->getBool("noclip") &&
- m_gamedef->checkLocalPrivilege("noclip")) &&
+ m_client->checkLocalPrivilege("noclip")) &&
cam_mode == CAMERA_MODE_FIRST)
{
post_effect_color = video::SColor(255, 0, 0, 0);