Skip to content
Permalink
Browse files

Fix rendering glitches when far from the center of the map

  • Loading branch information
Ekdohibs committed Mar 4, 2014
1 parent 8e15179 commit 062de11b4cff30861dd4e9eb56f131d821f34b51
Showing with 112 additions and 35 deletions.
  1. +14 −2 src/camera.cpp
  2. +8 −0 src/camera.h
  3. +1 −1 src/client.cpp
  4. +4 −0 src/client.h
  5. +4 −0 src/clientmap.cpp
  6. +3 −1 src/clientmap.h
  7. +1 −0 src/clientobject.h
  8. +3 −1 src/clouds.cpp
  9. +6 −0 src/clouds.h
  10. +5 −4 src/content_cao.cpp
  11. +5 −0 src/environment.h
  12. +21 −7 src/game.cpp
  13. +1 −1 src/itemdef.cpp
  14. +12 −2 src/mapblock_mesh.cpp
  15. +6 −1 src/mapblock_mesh.h
  16. +13 −12 src/particles.cpp
  17. +5 −3 src/particles.h
@@ -36,6 +36,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "profiler.h"
#include "util/numeric.h"
#include "util/mathconstants.h"
#include "constants.h"

#define CAMERA_OFFSET_STEP 200

Camera::Camera(scene::ISceneManager* smgr, MapDrawControl& draw_control,
IGameDef *gamedef):
@@ -53,6 +56,7 @@ Camera::Camera(scene::ISceneManager* smgr, MapDrawControl& draw_control,

m_camera_position(0,0,0),
m_camera_direction(0,0,0),
m_camera_offset(0,0,0),

m_aspect(1.0),
m_fov_x(1.0),
@@ -348,11 +352,19 @@ void Camera::update(LocalPlayer* player, f32 frametime, f32 busytime,
v3f abs_cam_up;
m_headnode->getAbsoluteTransformation().rotateVect(abs_cam_up, rel_cam_up);

// Update offset if too far away from the center of the map
m_camera_offset.X += CAMERA_OFFSET_STEP*
(((s16)(m_camera_position.X/BS) - m_camera_offset.X)/CAMERA_OFFSET_STEP);
m_camera_offset.Y += CAMERA_OFFSET_STEP*
(((s16)(m_camera_position.Y/BS) - m_camera_offset.Y)/CAMERA_OFFSET_STEP);
m_camera_offset.Z += CAMERA_OFFSET_STEP*
(((s16)(m_camera_position.Z/BS) - m_camera_offset.Z)/CAMERA_OFFSET_STEP);

// Set camera node transformation
m_cameranode->setPosition(m_camera_position);
m_cameranode->setPosition(m_camera_position-intToFloat(m_camera_offset, BS));
m_cameranode->setUpVector(abs_cam_up);
// *100.0 helps in large map coordinates
m_cameranode->setTarget(m_camera_position + 100 * m_camera_direction);
m_cameranode->setTarget(m_camera_position-intToFloat(m_camera_offset, BS) + 100 * m_camera_direction);

// Get FOV setting
f32 fov_degrees = g_settings->getFloat("fov");
@@ -79,6 +79,12 @@ class Camera
{
return m_camera_direction;
}

// Get the camera offset
inline v3s16 getOffset() const
{
return m_camera_offset;
}

// Horizontal field of view
inline f32 getFovX() const
@@ -144,6 +150,8 @@ class Camera
v3f m_camera_position;
// Absolute camera direction
v3f m_camera_direction;
// Camera offset
v3s16 m_camera_offset;

// Field of view and aspect ratio stuff
f32 m_aspect;
@@ -179,7 +179,7 @@ void * MeshUpdateThread::Thread()

ScopeProfiler sp(g_profiler, "Client: Mesh making");

MapBlockMesh *mesh_new = new MapBlockMesh(q->data);
MapBlockMesh *mesh_new = new MapBlockMesh(q->data, m_camera_offset);
if(mesh_new->getMesh()->getMeshBufferCount() == 0)
{
delete mesh_new;
@@ -119,6 +119,8 @@ class MeshUpdateThread : public JThread
MutexedQueue<MeshUpdateResult> m_queue_out;

IGameDef *m_gamedef;

v3s16 m_camera_offset;
};

enum ClientEventType
@@ -406,6 +408,8 @@ class Client : public con::PeerHandler, public InventoryManager, public IGameDef
// Including blocks at appropriate edges
void addUpdateMeshTaskWithEdge(v3s16 blockpos, bool ack_to_server=false, bool urgent=false);
void addUpdateMeshTaskForNode(v3s16 nodepos, bool ack_to_server=false, bool urgent=false);

void updateCameraOffset(v3s16 camera_offset){ m_mesh_update_thread.m_camera_offset = camera_offset; }

// Get event from queue. CE_NONE is returned if queue is empty.
ClientEvent getClientEvent();
@@ -175,6 +175,7 @@ void ClientMap::updateDrawList(video::IVideoDriver* driver)
v3f camera_position = m_camera_position;
v3f camera_direction = m_camera_direction;
f32 camera_fov = m_camera_fov;
v3s16 camera_offset = m_camera_offset;
m_camera_mutex.Unlock();

// Use a higher fov to accomodate faster camera movements.
@@ -250,6 +251,9 @@ void ClientMap::updateDrawList(video::IVideoDriver* driver)
if not seen on display
*/

if (block->mesh != NULL)
block->mesh->updateCameraOffset(m_camera_offset);

float range = 100000 * BS;
if(m_control.range_all == false)
range = m_control.wanted_range * BS;
@@ -86,12 +86,13 @@ class ClientMap : public Map, public scene::ISceneNode
ISceneNode::drop();
}

void updateCamera(v3f pos, v3f dir, f32 fov)
void updateCamera(v3f pos, v3f dir, f32 fov, v3s16 offset)
{
JMutexAutoLock lock(m_camera_mutex);
m_camera_position = pos;
m_camera_direction = dir;
m_camera_fov = fov;
m_camera_offset = offset;
}

/*
@@ -146,6 +147,7 @@ class ClientMap : public Map, public scene::ISceneNode
v3f m_camera_position;
v3f m_camera_direction;
f32 m_camera_fov;
v3s16 m_camera_offset;
JMutex m_camera_mutex;

std::map<v3s16, MapBlock*> m_drawlist;
@@ -65,6 +65,7 @@ class ClientActiveObject : public ActiveObject
virtual bool isLocalPlayer(){return false;}
virtual void setAttachments(){}
virtual bool doShowSelectionBox(){return true;}
virtual void updateCameraOffset(v3s16 camera_offset){};

// Step object in time
virtual void step(float dtime, ClientEnvironment *env){}
@@ -35,7 +35,8 @@ Clouds::Clouds(
scene::ISceneNode(parent, mgr, id),
m_seed(seed),
m_camera_pos(0,0),
m_time(0)
m_time(0),
m_camera_offset(0,0,0)
{
m_material.setFlag(video::EMF_LIGHTING, false);
//m_material.setFlag(video::EMF_BACK_FACE_CULLING, false);
@@ -318,6 +319,7 @@ void Clouds::render()
}

v3f pos(p0.X, m_cloud_y, p0.Y);
pos -= intToFloat(m_camera_offset, BS);

for(u16 i=0; i<4; i++)
v[i].Pos += pos;
@@ -66,6 +66,11 @@ class Clouds : public scene::ISceneNode
void step(float dtime);

void update(v2f camera_p, video::SColorf color);

void updateCameraOffset(v3s16 camera_offset)
{
m_camera_offset = camera_offset;
}

private:
video::SMaterial m_material;
@@ -76,6 +81,7 @@ class Clouds : public scene::ISceneNode
u32 m_seed;
v2f m_camera_pos;
float m_time;
v3s16 m_camera_offset;
};


@@ -1058,23 +1058,24 @@ class GenericCAO : public ClientActiveObject
if(getParent() != NULL)
return;

v3s16 camera_offset = m_env->getCameraOffset();
if(m_meshnode){
m_meshnode->setPosition(pos_translator.vect_show);
m_meshnode->setPosition(pos_translator.vect_show-intToFloat(camera_offset, BS));
v3f rot = m_meshnode->getRotation();
rot.Y = -m_yaw;
m_meshnode->setRotation(rot);
}
if(m_animated_meshnode){
m_animated_meshnode->setPosition(pos_translator.vect_show);
m_animated_meshnode->setPosition(pos_translator.vect_show-intToFloat(camera_offset, BS));
v3f rot = m_animated_meshnode->getRotation();
rot.Y = -m_yaw;
m_animated_meshnode->setRotation(rot);
}
if(m_spritenode){
m_spritenode->setPosition(pos_translator.vect_show);
m_spritenode->setPosition(pos_translator.vect_show-intToFloat(camera_offset, BS));
}
}

void step(float dtime, ClientEnvironment *env)
{
if(m_visuals_expired && m_smgr && m_irr){
@@ -500,6 +500,10 @@ class ClientEnvironment : public Environment
{ m_player_names.push_back(name); }
void removePlayerName(std::string name)
{ m_player_names.remove(name); }
void updateCameraOffset(v3s16 camera_offset)
{ m_camera_offset = camera_offset; }
v3s16 getCameraOffset()
{ return m_camera_offset; }

private:
ClientMap *m_map;
@@ -515,6 +519,7 @@ class ClientEnvironment : public Environment
IntervalLimiter m_drowning_interval;
IntervalLimiter m_breathing_interval;
std::list<std::string> m_player_names;
v3s16 m_camera_offset;
};

#endif
@@ -228,6 +228,7 @@ PointedThing getPointedThing(Client *client, v3f player_position,
core::line3d<f32> shootline, f32 d,
bool liquids_pointable,
bool look_for_object,
v3s16 camera_offset,
std::vector<aabb3f> &hilightboxes,
ClientActiveObject *&selected_object)
{
@@ -258,8 +259,8 @@ PointedThing getPointedThing(Client *client, v3f player_position,

v3f pos = selected_object->getPosition();
hilightboxes.push_back(aabb3f(
selection_box->MinEdge + pos,
selection_box->MaxEdge + pos));
selection_box->MinEdge + pos - intToFloat(camera_offset, BS),
selection_box->MaxEdge + pos - intToFloat(camera_offset, BS)));
}

mindistance = (selected_object->getPosition() - camera_position).getLength();
@@ -361,8 +362,8 @@ PointedThing getPointedThing(Client *client, v3f player_position,
i2 != boxes.end(); i2++)
{
aabb3f box = *i2;
box.MinEdge += npf + v3f(-d,-d,-d);
box.MaxEdge += npf + v3f(d,d,d);
box.MinEdge += npf + v3f(-d,-d,-d) - intToFloat(camera_offset, BS);
box.MaxEdge += npf + v3f(d,d,d) - intToFloat(camera_offset, BS);
hilightboxes.push_back(box);
}
}
@@ -2541,6 +2542,8 @@ void the_game(
Update camera
*/

v3s16 old_camera_offset = camera.getOffset();

LocalPlayer* player = client.getEnv().getLocalPlayer();
float full_punch_interval = playeritem_toolcap.full_punch_interval;
float tool_reload_ratio = time_from_last_punch / full_punch_interval;
@@ -2554,10 +2557,19 @@ void the_game(
v3f camera_position = camera.getPosition();
v3f camera_direction = camera.getDirection();
f32 camera_fov = camera.getFovMax();
v3s16 camera_offset = camera.getOffset();

bool camera_offset_changed = (camera_offset != old_camera_offset);

if(!disable_camera_update){
client.getEnv().getClientMap().updateCamera(camera_position,
camera_direction, camera_fov);
camera_direction, camera_fov, camera_offset);
if (camera_offset_changed){
client.updateCameraOffset(camera_offset);
client.getEnv().updateCameraOffset(camera_offset);
if (clouds)
clouds->updateCameraOffset(camera_offset);
}
}

// Update sound listener
@@ -2600,6 +2612,7 @@ void the_game(
&client, player_position, camera_direction,
camera_position, shootline, d,
playeritem_def.liquids_pointable, !ldown_for_dig,
camera_offset,
// output
hilightboxes,
selected_object);
@@ -3030,7 +3043,7 @@ void the_game(
Update particles
*/

allparticles_step(dtime, client.getEnv());
allparticles_step(dtime);
allparticlespawners_step(dtime, client.getEnv());

/*
@@ -3249,7 +3262,8 @@ void the_game(
*/
update_draw_list_timer += dtime;
if(update_draw_list_timer >= 0.2 ||
update_draw_list_last_cam_dir.getDistanceFrom(camera_direction) > 0.2){
update_draw_list_last_cam_dir.getDistanceFrom(camera_direction) > 0.2 ||
camera_offset_changed){
update_draw_list_timer = 0;
client.getEnv().getClientMap().updateDrawList(driver);
update_draw_list_last_cam_dir = camera_direction;
@@ -398,7 +398,7 @@ class CItemDefManager: public IWritableItemDefManager
MeshMakeData mesh_make_data(gamedef);
MapNode mesh_make_node(id, param1, 0);
mesh_make_data.fillSingleNode(&mesh_make_node);
MapBlockMesh mapblock_mesh(&mesh_make_data);
MapBlockMesh mapblock_mesh(&mesh_make_data, v3s16(0, 0, 0));
scene::IMesh *node_mesh = mapblock_mesh.getMesh();
assert(node_mesh);
video::SColor c(255, 255, 255, 255);
@@ -1030,7 +1030,7 @@ static void updateAllFastFaceRows(MeshMakeData *data,
MapBlockMesh
*/

MapBlockMesh::MapBlockMesh(MeshMakeData *data):
MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset):
m_mesh(new scene::SMesh()),
m_gamedef(data->m_gamedef),
m_animation_force_timer(0), // force initial animation
@@ -1248,11 +1248,13 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data):
&p.indices[0], p.indices.size());
}

m_camera_offset = camera_offset;

/*
Do some stuff to the mesh
*/

translateMesh(m_mesh, intToFloat(data->m_blockpos * MAP_BLOCKSIZE, BS));
translateMesh(m_mesh, intToFloat(data->m_blockpos * MAP_BLOCKSIZE - camera_offset, BS));

if(m_mesh)
{
@@ -1415,6 +1417,14 @@ bool MapBlockMesh::animate(bool faraway, float time, int crack, u32 daynight_rat
return true;
}

void MapBlockMesh::updateCameraOffset(v3s16 camera_offset)
{
if (camera_offset != m_camera_offset) {
translateMesh(m_mesh, intToFloat(m_camera_offset-camera_offset, BS));
m_camera_offset = camera_offset;
}
}

/*
MeshCollector
*/
@@ -81,7 +81,7 @@ class MapBlockMesh
{
public:
// Builds the mesh given
MapBlockMesh(MeshMakeData *data);
MapBlockMesh(MeshMakeData *data, v3s16 camera_offset);
~MapBlockMesh();

// Main animation function, parameters:
@@ -107,6 +107,8 @@ class MapBlockMesh
if(m_animation_force_timer > 0)
m_animation_force_timer--;
}

void updateCameraOffset(v3s16 camera_offset);

private:
scene::SMesh *m_mesh;
@@ -133,6 +135,9 @@ class MapBlockMesh
u32 m_last_daynight_ratio;
// For each meshbuffer, maps vertex indices to (day,night) pairs
std::map<u32, std::map<u32, std::pair<u8, u8> > > m_daynight_diffs;

// Camera offset info -> do we have to translate the mesh?
v3s16 m_camera_offset;
};


0 comments on commit 062de11

Please sign in to comment.
You can’t perform that action at this time.