Skip to content

Commit 062de11

Browse files
committedMar 4, 2014
Fix rendering glitches when far from the center of the map
1 parent 8e15179 commit 062de11

17 files changed

+112
-35
lines changed
 

‎src/camera.cpp

+14-2
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
3636
#include "profiler.h"
3737
#include "util/numeric.h"
3838
#include "util/mathconstants.h"
39+
#include "constants.h"
40+
41+
#define CAMERA_OFFSET_STEP 200
3942

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

5457
m_camera_position(0,0,0),
5558
m_camera_direction(0,0,0),
59+
m_camera_offset(0,0,0),
5660

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

355+
// Update offset if too far away from the center of the map
356+
m_camera_offset.X += CAMERA_OFFSET_STEP*
357+
(((s16)(m_camera_position.X/BS) - m_camera_offset.X)/CAMERA_OFFSET_STEP);
358+
m_camera_offset.Y += CAMERA_OFFSET_STEP*
359+
(((s16)(m_camera_position.Y/BS) - m_camera_offset.Y)/CAMERA_OFFSET_STEP);
360+
m_camera_offset.Z += CAMERA_OFFSET_STEP*
361+
(((s16)(m_camera_position.Z/BS) - m_camera_offset.Z)/CAMERA_OFFSET_STEP);
362+
351363
// Set camera node transformation
352-
m_cameranode->setPosition(m_camera_position);
364+
m_cameranode->setPosition(m_camera_position-intToFloat(m_camera_offset, BS));
353365
m_cameranode->setUpVector(abs_cam_up);
354366
// *100.0 helps in large map coordinates
355-
m_cameranode->setTarget(m_camera_position + 100 * m_camera_direction);
367+
m_cameranode->setTarget(m_camera_position-intToFloat(m_camera_offset, BS) + 100 * m_camera_direction);
356368

357369
// Get FOV setting
358370
f32 fov_degrees = g_settings->getFloat("fov");

‎src/camera.h

+8
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,12 @@ class Camera
7979
{
8080
return m_camera_direction;
8181
}
82+
83+
// Get the camera offset
84+
inline v3s16 getOffset() const
85+
{
86+
return m_camera_offset;
87+
}
8288

8389
// Horizontal field of view
8490
inline f32 getFovX() const
@@ -144,6 +150,8 @@ class Camera
144150
v3f m_camera_position;
145151
// Absolute camera direction
146152
v3f m_camera_direction;
153+
// Camera offset
154+
v3s16 m_camera_offset;
147155

148156
// Field of view and aspect ratio stuff
149157
f32 m_aspect;

‎src/client.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ void * MeshUpdateThread::Thread()
179179

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

182-
MapBlockMesh *mesh_new = new MapBlockMesh(q->data);
182+
MapBlockMesh *mesh_new = new MapBlockMesh(q->data, m_camera_offset);
183183
if(mesh_new->getMesh()->getMeshBufferCount() == 0)
184184
{
185185
delete mesh_new;

‎src/client.h

+4
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,8 @@ class MeshUpdateThread : public JThread
119119
MutexedQueue<MeshUpdateResult> m_queue_out;
120120

121121
IGameDef *m_gamedef;
122+
123+
v3s16 m_camera_offset;
122124
};
123125

124126
enum ClientEventType
@@ -406,6 +408,8 @@ class Client : public con::PeerHandler, public InventoryManager, public IGameDef
406408
// Including blocks at appropriate edges
407409
void addUpdateMeshTaskWithEdge(v3s16 blockpos, bool ack_to_server=false, bool urgent=false);
408410
void addUpdateMeshTaskForNode(v3s16 nodepos, bool ack_to_server=false, bool urgent=false);
411+
412+
void updateCameraOffset(v3s16 camera_offset){ m_mesh_update_thread.m_camera_offset = camera_offset; }
409413

410414
// Get event from queue. CE_NONE is returned if queue is empty.
411415
ClientEvent getClientEvent();

‎src/clientmap.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ void ClientMap::updateDrawList(video::IVideoDriver* driver)
175175
v3f camera_position = m_camera_position;
176176
v3f camera_direction = m_camera_direction;
177177
f32 camera_fov = m_camera_fov;
178+
v3s16 camera_offset = m_camera_offset;
178179
m_camera_mutex.Unlock();
179180

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

254+
if (block->mesh != NULL)
255+
block->mesh->updateCameraOffset(m_camera_offset);
256+
253257
float range = 100000 * BS;
254258
if(m_control.range_all == false)
255259
range = m_control.wanted_range * BS;

‎src/clientmap.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -86,12 +86,13 @@ class ClientMap : public Map, public scene::ISceneNode
8686
ISceneNode::drop();
8787
}
8888

89-
void updateCamera(v3f pos, v3f dir, f32 fov)
89+
void updateCamera(v3f pos, v3f dir, f32 fov, v3s16 offset)
9090
{
9191
JMutexAutoLock lock(m_camera_mutex);
9292
m_camera_position = pos;
9393
m_camera_direction = dir;
9494
m_camera_fov = fov;
95+
m_camera_offset = offset;
9596
}
9697

9798
/*
@@ -146,6 +147,7 @@ class ClientMap : public Map, public scene::ISceneNode
146147
v3f m_camera_position;
147148
v3f m_camera_direction;
148149
f32 m_camera_fov;
150+
v3s16 m_camera_offset;
149151
JMutex m_camera_mutex;
150152

151153
std::map<v3s16, MapBlock*> m_drawlist;

‎src/clientobject.h

+1
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ class ClientActiveObject : public ActiveObject
6565
virtual bool isLocalPlayer(){return false;}
6666
virtual void setAttachments(){}
6767
virtual bool doShowSelectionBox(){return true;}
68+
virtual void updateCameraOffset(v3s16 camera_offset){};
6869

6970
// Step object in time
7071
virtual void step(float dtime, ClientEnvironment *env){}

‎src/clouds.cpp

+3-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ Clouds::Clouds(
3535
scene::ISceneNode(parent, mgr, id),
3636
m_seed(seed),
3737
m_camera_pos(0,0),
38-
m_time(0)
38+
m_time(0),
39+
m_camera_offset(0,0,0)
3940
{
4041
m_material.setFlag(video::EMF_LIGHTING, false);
4142
//m_material.setFlag(video::EMF_BACK_FACE_CULLING, false);
@@ -318,6 +319,7 @@ void Clouds::render()
318319
}
319320

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

322324
for(u16 i=0; i<4; i++)
323325
v[i].Pos += pos;

‎src/clouds.h

+6
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,11 @@ class Clouds : public scene::ISceneNode
6666
void step(float dtime);
6767

6868
void update(v2f camera_p, video::SColorf color);
69+
70+
void updateCameraOffset(v3s16 camera_offset)
71+
{
72+
m_camera_offset = camera_offset;
73+
}
6974

7075
private:
7176
video::SMaterial m_material;
@@ -76,6 +81,7 @@ class Clouds : public scene::ISceneNode
7681
u32 m_seed;
7782
v2f m_camera_pos;
7883
float m_time;
84+
v3s16 m_camera_offset;
7985
};
8086

8187

‎src/content_cao.cpp

+5-4
Original file line numberDiff line numberDiff line change
@@ -1058,23 +1058,24 @@ class GenericCAO : public ClientActiveObject
10581058
if(getParent() != NULL)
10591059
return;
10601060

1061+
v3s16 camera_offset = m_env->getCameraOffset();
10611062
if(m_meshnode){
1062-
m_meshnode->setPosition(pos_translator.vect_show);
1063+
m_meshnode->setPosition(pos_translator.vect_show-intToFloat(camera_offset, BS));
10631064
v3f rot = m_meshnode->getRotation();
10641065
rot.Y = -m_yaw;
10651066
m_meshnode->setRotation(rot);
10661067
}
10671068
if(m_animated_meshnode){
1068-
m_animated_meshnode->setPosition(pos_translator.vect_show);
1069+
m_animated_meshnode->setPosition(pos_translator.vect_show-intToFloat(camera_offset, BS));
10691070
v3f rot = m_animated_meshnode->getRotation();
10701071
rot.Y = -m_yaw;
10711072
m_animated_meshnode->setRotation(rot);
10721073
}
10731074
if(m_spritenode){
1074-
m_spritenode->setPosition(pos_translator.vect_show);
1075+
m_spritenode->setPosition(pos_translator.vect_show-intToFloat(camera_offset, BS));
10751076
}
10761077
}
1077-
1078+
10781079
void step(float dtime, ClientEnvironment *env)
10791080
{
10801081
if(m_visuals_expired && m_smgr && m_irr){

‎src/environment.h

+5
Original file line numberDiff line numberDiff line change
@@ -500,6 +500,10 @@ class ClientEnvironment : public Environment
500500
{ m_player_names.push_back(name); }
501501
void removePlayerName(std::string name)
502502
{ m_player_names.remove(name); }
503+
void updateCameraOffset(v3s16 camera_offset)
504+
{ m_camera_offset = camera_offset; }
505+
v3s16 getCameraOffset()
506+
{ return m_camera_offset; }
503507

504508
private:
505509
ClientMap *m_map;
@@ -515,6 +519,7 @@ class ClientEnvironment : public Environment
515519
IntervalLimiter m_drowning_interval;
516520
IntervalLimiter m_breathing_interval;
517521
std::list<std::string> m_player_names;
522+
v3s16 m_camera_offset;
518523
};
519524

520525
#endif

‎src/game.cpp

+21-7
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,7 @@ PointedThing getPointedThing(Client *client, v3f player_position,
228228
core::line3d<f32> shootline, f32 d,
229229
bool liquids_pointable,
230230
bool look_for_object,
231+
v3s16 camera_offset,
231232
std::vector<aabb3f> &hilightboxes,
232233
ClientActiveObject *&selected_object)
233234
{
@@ -258,8 +259,8 @@ PointedThing getPointedThing(Client *client, v3f player_position,
258259

259260
v3f pos = selected_object->getPosition();
260261
hilightboxes.push_back(aabb3f(
261-
selection_box->MinEdge + pos,
262-
selection_box->MaxEdge + pos));
262+
selection_box->MinEdge + pos - intToFloat(camera_offset, BS),
263+
selection_box->MaxEdge + pos - intToFloat(camera_offset, BS)));
263264
}
264265

265266
mindistance = (selected_object->getPosition() - camera_position).getLength();
@@ -361,8 +362,8 @@ PointedThing getPointedThing(Client *client, v3f player_position,
361362
i2 != boxes.end(); i2++)
362363
{
363364
aabb3f box = *i2;
364-
box.MinEdge += npf + v3f(-d,-d,-d);
365-
box.MaxEdge += npf + v3f(d,d,d);
365+
box.MinEdge += npf + v3f(-d,-d,-d) - intToFloat(camera_offset, BS);
366+
box.MaxEdge += npf + v3f(d,d,d) - intToFloat(camera_offset, BS);
366367
hilightboxes.push_back(box);
367368
}
368369
}
@@ -2541,6 +2542,8 @@ void the_game(
25412542
Update camera
25422543
*/
25432544

2545+
v3s16 old_camera_offset = camera.getOffset();
2546+
25442547
LocalPlayer* player = client.getEnv().getLocalPlayer();
25452548
float full_punch_interval = playeritem_toolcap.full_punch_interval;
25462549
float tool_reload_ratio = time_from_last_punch / full_punch_interval;
@@ -2554,10 +2557,19 @@ void the_game(
25542557
v3f camera_position = camera.getPosition();
25552558
v3f camera_direction = camera.getDirection();
25562559
f32 camera_fov = camera.getFovMax();
2560+
v3s16 camera_offset = camera.getOffset();
2561+
2562+
bool camera_offset_changed = (camera_offset != old_camera_offset);
25572563

25582564
if(!disable_camera_update){
25592565
client.getEnv().getClientMap().updateCamera(camera_position,
2560-
camera_direction, camera_fov);
2566+
camera_direction, camera_fov, camera_offset);
2567+
if (camera_offset_changed){
2568+
client.updateCameraOffset(camera_offset);
2569+
client.getEnv().updateCameraOffset(camera_offset);
2570+
if (clouds)
2571+
clouds->updateCameraOffset(camera_offset);
2572+
}
25612573
}
25622574

25632575
// Update sound listener
@@ -2600,6 +2612,7 @@ void the_game(
26002612
&client, player_position, camera_direction,
26012613
camera_position, shootline, d,
26022614
playeritem_def.liquids_pointable, !ldown_for_dig,
2615+
camera_offset,
26032616
// output
26042617
hilightboxes,
26052618
selected_object);
@@ -3030,7 +3043,7 @@ void the_game(
30303043
Update particles
30313044
*/
30323045

3033-
allparticles_step(dtime, client.getEnv());
3046+
allparticles_step(dtime);
30343047
allparticlespawners_step(dtime, client.getEnv());
30353048

30363049
/*
@@ -3249,7 +3262,8 @@ void the_game(
32493262
*/
32503263
update_draw_list_timer += dtime;
32513264
if(update_draw_list_timer >= 0.2 ||
3252-
update_draw_list_last_cam_dir.getDistanceFrom(camera_direction) > 0.2){
3265+
update_draw_list_last_cam_dir.getDistanceFrom(camera_direction) > 0.2 ||
3266+
camera_offset_changed){
32533267
update_draw_list_timer = 0;
32543268
client.getEnv().getClientMap().updateDrawList(driver);
32553269
update_draw_list_last_cam_dir = camera_direction;

‎src/itemdef.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -398,7 +398,7 @@ class CItemDefManager: public IWritableItemDefManager
398398
MeshMakeData mesh_make_data(gamedef);
399399
MapNode mesh_make_node(id, param1, 0);
400400
mesh_make_data.fillSingleNode(&mesh_make_node);
401-
MapBlockMesh mapblock_mesh(&mesh_make_data);
401+
MapBlockMesh mapblock_mesh(&mesh_make_data, v3s16(0, 0, 0));
402402
scene::IMesh *node_mesh = mapblock_mesh.getMesh();
403403
assert(node_mesh);
404404
video::SColor c(255, 255, 255, 255);

‎src/mapblock_mesh.cpp

+12-2
Original file line numberDiff line numberDiff line change
@@ -1030,7 +1030,7 @@ static void updateAllFastFaceRows(MeshMakeData *data,
10301030
MapBlockMesh
10311031
*/
10321032

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

1251+
m_camera_offset = camera_offset;
1252+
12511253
/*
12521254
Do some stuff to the mesh
12531255
*/
12541256

1255-
translateMesh(m_mesh, intToFloat(data->m_blockpos * MAP_BLOCKSIZE, BS));
1257+
translateMesh(m_mesh, intToFloat(data->m_blockpos * MAP_BLOCKSIZE - camera_offset, BS));
12561258

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

1420+
void MapBlockMesh::updateCameraOffset(v3s16 camera_offset)
1421+
{
1422+
if (camera_offset != m_camera_offset) {
1423+
translateMesh(m_mesh, intToFloat(m_camera_offset-camera_offset, BS));
1424+
m_camera_offset = camera_offset;
1425+
}
1426+
}
1427+
14181428
/*
14191429
MeshCollector
14201430
*/

‎src/mapblock_mesh.h

+6-1
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ class MapBlockMesh
8181
{
8282
public:
8383
// Builds the mesh given
84-
MapBlockMesh(MeshMakeData *data);
84+
MapBlockMesh(MeshMakeData *data, v3s16 camera_offset);
8585
~MapBlockMesh();
8686

8787
// Main animation function, parameters:
@@ -107,6 +107,8 @@ class MapBlockMesh
107107
if(m_animation_force_timer > 0)
108108
m_animation_force_timer--;
109109
}
110+
111+
void updateCameraOffset(v3s16 camera_offset);
110112

111113
private:
112114
scene::SMesh *m_mesh;
@@ -133,6 +135,9 @@ class MapBlockMesh
133135
u32 m_last_daynight_ratio;
134136
// For each meshbuffer, maps vertex indices to (day,night) pairs
135137
std::map<u32, std::map<u32, std::pair<u8, u8> > > m_daynight_diffs;
138+
139+
// Camera offset info -> do we have to translate the mesh?
140+
v3s16 m_camera_offset;
136141
};
137142

138143

‎src/particles.cpp

+13-12
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ Particle::Particle(
6666
{
6767
// Misc
6868
m_gamedef = gamedef;
69+
m_env = &env;
6970

7071
// Texture
7172
m_material.setFlag(video::EMF_LIGHTING, false);
@@ -95,7 +96,7 @@ Particle::Particle(
9596
this->setAutomaticCulling(scene::EAC_OFF);
9697

9798
// Init lighting
98-
updateLight(env);
99+
updateLight();
99100

100101
// Init model
101102
updateVertices();
@@ -134,7 +135,7 @@ void Particle::render()
134135
scene::EPT_TRIANGLES, video::EIT_16BIT);
135136
}
136137

137-
void Particle::step(float dtime, ClientEnvironment &env)
138+
void Particle::step(float dtime)
138139
{
139140
m_time += dtime;
140141
if (m_collisiondetection)
@@ -143,7 +144,7 @@ void Particle::step(float dtime, ClientEnvironment &env)
143144
v3f p_pos = m_pos*BS;
144145
v3f p_velocity = m_velocity*BS;
145146
v3f p_acceleration = m_acceleration*BS;
146-
collisionMoveSimple(&env, m_gamedef,
147+
collisionMoveSimple(m_env, m_gamedef,
147148
BS*0.5, box,
148149
0, dtime,
149150
p_pos, p_velocity, p_acceleration);
@@ -158,13 +159,13 @@ void Particle::step(float dtime, ClientEnvironment &env)
158159
}
159160

160161
// Update lighting
161-
updateLight(env);
162+
updateLight();
162163

163164
// Update model
164165
updateVertices();
165166
}
166167

167-
void Particle::updateLight(ClientEnvironment &env)
168+
void Particle::updateLight()
168169
{
169170
u8 light = 0;
170171
try{
@@ -173,11 +174,11 @@ void Particle::updateLight(ClientEnvironment &env)
173174
floor(m_pos.Y+0.5),
174175
floor(m_pos.Z+0.5)
175176
);
176-
MapNode n = env.getClientMap().getNode(p);
177-
light = n.getLightBlend(env.getDayNightRatio(), m_gamedef->ndef());
177+
MapNode n = m_env->getClientMap().getNode(p);
178+
light = n.getLightBlend(m_env->getDayNightRatio(), m_gamedef->ndef());
178179
}
179180
catch(InvalidPositionException &e){
180-
light = blend_light(env.getDayNightRatio(), LIGHT_SUN, 0);
181+
light = blend_light(m_env->getDayNightRatio(), LIGHT_SUN, 0);
181182
}
182183
m_light = decode_light(light);
183184
}
@@ -199,6 +200,7 @@ void Particle::updateVertices()
199200
m_vertices[3] = video::S3DVertex(-m_size/2,m_size/2,0, 0,0,0,
200201
c, tx0, ty0);
201202

203+
v3s16 camera_offset = m_env->getCameraOffset();
202204
for(u16 i=0; i<4; i++)
203205
{
204206
if (m_vertical) {
@@ -209,17 +211,16 @@ void Particle::updateVertices()
209211
m_vertices[i].Pos.rotateXZBy(m_player->getYaw());
210212
}
211213
m_box.addInternalPoint(m_vertices[i].Pos);
212-
m_vertices[i].Pos += m_pos*BS;
214+
m_vertices[i].Pos += m_pos*BS - intToFloat(camera_offset, BS);
213215
}
214216
}
215217

216-
217218
/*
218219
Helpers
219220
*/
220221

221222

222-
void allparticles_step (float dtime, ClientEnvironment &env)
223+
void allparticles_step (float dtime)
223224
{
224225
for(std::vector<Particle*>::iterator i = all_particles.begin();
225226
i != all_particles.end();)
@@ -232,7 +233,7 @@ void allparticles_step (float dtime, ClientEnvironment &env)
232233
}
233234
else
234235
{
235-
(*i)->step(dtime, env);
236+
(*i)->step(dtime);
236237
i++;
237238
}
238239
}

‎src/particles.h

+5-3
Original file line numberDiff line numberDiff line change
@@ -67,19 +67,20 @@ class Particle : public scene::ISceneNode
6767
virtual void OnRegisterSceneNode();
6868
virtual void render();
6969

70-
void step(float dtime, ClientEnvironment &env);
70+
void step(float dtime);
7171

7272
bool get_expired ()
7373
{ return m_expiration < m_time; }
7474

7575
private:
76-
void updateLight(ClientEnvironment &env);
76+
void updateLight();
7777
void updateVertices();
7878

7979
video::S3DVertex m_vertices[4];
8080
float m_time;
8181
float m_expiration;
8282

83+
ClientEnvironment *m_env;
8384
IGameDef *m_gamedef;
8485
core::aabbox3d<f32> m_box;
8586
core::aabbox3d<f32> m_collisionbox;
@@ -94,6 +95,7 @@ class Particle : public scene::ISceneNode
9495
u8 m_light;
9596
bool m_collisiondetection;
9697
bool m_vertical;
98+
v3s16 m_camera_offset;
9799
};
98100

99101
class ParticleSpawner
@@ -144,7 +146,7 @@ class ParticleSpawner
144146
bool m_vertical;
145147
};
146148

147-
void allparticles_step (float dtime, ClientEnvironment &env);
149+
void allparticles_step (float dtime);
148150
void allparticlespawners_step (float dtime, ClientEnvironment &env);
149151

150152
void delete_particlespawner (u32 id);

0 commit comments

Comments
 (0)
Please sign in to comment.