summaryrefslogtreecommitdiff
path: root/src/clientmap.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/clientmap.cpp')
-rw-r--r--src/clientmap.cpp193
1 files changed, 60 insertions, 133 deletions
diff --git a/src/clientmap.cpp b/src/clientmap.cpp
index faa1461f6..6cd24ffc6 100644
--- a/src/clientmap.cpp
+++ b/src/clientmap.cpp
@@ -29,20 +29,17 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "profiler.h"
#include "settings.h"
#include "camera.h" // CameraModes
-#include "util/mathconstants.h"
+#include "util/basic_macros.h"
#include <algorithm>
-#define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
-
ClientMap::ClientMap(
Client *client,
- IGameDef *gamedef,
MapDrawControl &control,
scene::ISceneNode* parent,
scene::ISceneManager* mgr,
s32 id
):
- Map(dout_client, gamedef),
+ Map(dout_client, client),
scene::ISceneNode(parent, mgr, id),
m_client(client),
m_control(control),
@@ -112,36 +109,7 @@ void ClientMap::OnRegisterSceneNode()
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);
@@ -173,8 +141,6 @@ void ClientMap::updateDrawList(video::IVideoDriver* driver)
ScopeProfiler sp(g_profiler, "CM::updateDrawList()", SPT_AVG);
g_profiler->add("CM::updateDrawList() count", 1);
- INodeDefManager *nodemgr = m_gamedef->ndef();
-
for (std::map<v3s16, MapBlock*>::iterator i = m_drawlist.begin();
i != m_drawlist.end(); ++i) {
MapBlock *block = i->second;
@@ -214,6 +180,16 @@ void ClientMap::updateDrawList(video::IVideoDriver* driver)
// Distance to farthest drawn block
float farthest_drawn = 0;
+ // No occlusion culling when free_move is on and camera is
+ // inside ground
+ bool occlusion_culling_enabled = true;
+ if (g_settings->getBool("free_move")) {
+ MapNode n = getNodeNoEx(cam_pos_nodes);
+ if (n.getContent() == CONTENT_IGNORE ||
+ m_nodedef->get(n).solidness == 2)
+ occlusion_culling_enabled = false;
+ }
+
for (std::map<v2s16, MapSector*>::iterator si = m_sectors.begin();
si != m_sectors.end(); ++si) {
MapSector *sector = si->second;
@@ -255,76 +231,20 @@ void ClientMap::updateDrawList(video::IVideoDriver* driver)
camera_direction, camera_fov, range, &d))
continue;
- // This is ugly (spherical distance limit?)
- /*if(m_control.range_all == false &&
- d - 0.5*BS*MAP_BLOCKSIZE > range)
- continue;*/
-
blocks_in_range++;
/*
Ignore if mesh doesn't exist
*/
- {
- //MutexAutoLock lock(block->mesh_mutex);
-
- if (block->mesh == NULL) {
- blocks_in_range_without_mesh++;
- continue;
- }
+ if (block->mesh == NULL) {
+ blocks_in_range_without_mesh++;
+ continue;
}
/*
Occlusion culling
*/
-
- // No occlusion culling when free_move is on and camera is
- // inside ground
- bool occlusion_culling_enabled = true;
- if (g_settings->getBool("free_move")) {
- MapNode n = getNodeNoEx(cam_pos_nodes);
- if (n.getContent() == CONTENT_IGNORE ||
- nodemgr->get(n).solidness == 2)
- occlusion_culling_enabled = false;
- }
-
- 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, nodemgr) &&
- isOccluded(this, spn, cpn + v3s16(bs2,bs2,bs2),
- step, stepfac, startoff, endoff, needed_count, nodemgr) &&
- isOccluded(this, spn, cpn + v3s16(bs2,bs2,-bs2),
- step, stepfac, startoff, endoff, needed_count, nodemgr) &&
- isOccluded(this, spn, cpn + v3s16(bs2,-bs2,bs2),
- step, stepfac, startoff, endoff, needed_count, nodemgr) &&
- isOccluded(this, spn, cpn + v3s16(bs2,-bs2,-bs2),
- step, stepfac, startoff, endoff, needed_count, nodemgr) &&
- isOccluded(this, spn, cpn + v3s16(-bs2,bs2,bs2),
- step, stepfac, startoff, endoff, needed_count, nodemgr) &&
- isOccluded(this, spn, cpn + v3s16(-bs2,bs2,-bs2),
- step, stepfac, startoff, endoff, needed_count, nodemgr) &&
- isOccluded(this, spn, cpn + v3s16(-bs2,-bs2,bs2),
- step, stepfac, startoff, endoff, needed_count, nodemgr) &&
- isOccluded(this, spn, cpn + v3s16(-bs2,-bs2,-bs2),
- step, stepfac, startoff, endoff, needed_count, nodemgr)) {
+ if (occlusion_culling_enabled && isBlockOccluded(block, cam_pos_nodes)) {
blocks_occlusion_culled++;
continue;
}
@@ -370,6 +290,11 @@ void ClientMap::updateDrawList(video::IVideoDriver* driver)
struct MeshBufList
{
+ /*!
+ * Specifies in which layer the list is.
+ * All lists which are in a lower layer are rendered before this list.
+ */
+ u8 layer;
video::SMaterial m;
std::vector<scene::IMeshBuffer*> bufs;
};
@@ -383,25 +308,29 @@ struct MeshBufListList
lists.clear();
}
- void add(scene::IMeshBuffer *buf)
+ void add(scene::IMeshBuffer *buf, u8 layer)
{
+ const video::SMaterial &m = buf->getMaterial();
for(std::vector<MeshBufList>::iterator i = lists.begin();
i != lists.end(); ++i){
MeshBufList &l = *i;
- video::SMaterial &m = buf->getMaterial();
// 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)
continue;
+ if(l.layer != layer)
+ continue;
+
if (l.m == m) {
l.bufs.push_back(buf);
return;
}
}
MeshBufList l;
- l.m = buf->getMaterial();
+ l.layer = layer;
+ l.m = m;
l.bufs.push_back(buf);
lists.push_back(l);
}
@@ -448,11 +377,6 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
Get all blocks and draw all visible ones
*/
- v3s16 cam_pos_nodes = floatToInt(camera_position, BS);
- v3s16 p_blocks_min;
- v3s16 p_blocks_max;
- getBlocksInViewRange(cam_pos_nodes, &p_blocks_min, &p_blocks_max);
-
u32 vertex_count = 0;
u32 meshbuffer_count = 0;
@@ -490,7 +414,7 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
continue;
// Mesh animation
- {
+ if (pass == scene::ESNRP_SOLID) {
//MutexAutoLock lock(block->mesh_mutex);
MapBlockMesh *mapBlockMesh = block->mesh;
assert(mapBlockMesh);
@@ -519,28 +443,34 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
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);
+ }
}
}
}
@@ -672,7 +602,6 @@ int ClientMap::getBackgroundBrightness(float max_d, u32 daylight_factor,
int oldvalue, bool *sunlight_seen_result)
{
const bool debugprint = false;
- INodeDefManager *ndef = m_gamedef->ndef();
static v3f z_directions[50] = {
v3f(-100, 0, 0)
};
@@ -710,7 +639,7 @@ int ClientMap::getBackgroundBrightness(float max_d, u32 daylight_factor,
float off = step * z_offsets[i];
bool sunlight_seen_now = false;
bool ok = getVisibleBrightness(this, m_camera_position, dir,
- step, 1.0, max_d*0.6+off, max_d, ndef, daylight_factor,
+ step, 1.0, max_d*0.6+off, max_d, m_nodedef, daylight_factor,
sunlight_min_d,
&br, &sunlight_seen_now);
if(sunlight_seen_now)
@@ -750,8 +679,8 @@ int ClientMap::getBackgroundBrightness(float max_d, u32 daylight_factor,
int ret = 0;
if(brightness_count == 0){
MapNode n = getNodeNoEx(floatToInt(m_camera_position, BS));
- if(ndef->get(n).param_type == CPT_LIGHT){
- ret = decode_light(n.getLightBlend(daylight_factor, ndef));
+ if(m_nodedef->get(n).param_type == CPT_LIGHT){
+ ret = decode_light(n.getLightBlend(daylight_factor, m_nodedef));
} else {
ret = oldvalue;
}
@@ -774,8 +703,6 @@ int ClientMap::getBackgroundBrightness(float max_d, u32 daylight_factor,
void ClientMap::renderPostFx(CameraMode cam_mode)
{
- INodeDefManager *nodemgr = m_gamedef->ndef();
-
// Sadly ISceneManager has no "post effects" render pass, in that case we
// could just register for that and handle it in renderMap().
@@ -784,10 +711,10 @@ void ClientMap::renderPostFx(CameraMode cam_mode)
// - If the player is in a solid node, make everything black.
// - If the player is in liquid, draw a semi-transparent overlay.
// - Do not if player is in third person mode
- const ContentFeatures& features = nodemgr->get(n);
+ 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);