Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

chunk visibility set management works well now. when lots of updates …

…happen it's still sloppy... butthe updates should be less of a strain probably... constant recompilation is hard on the memory=>gpu transfer...
  • Loading branch information...
commit b748ea97135b4edd747d36d319da9b696618e4b4 1 parent b072b6c
@elmex authored
View
15 Construder.xs
@@ -170,10 +170,12 @@ void ctr_render_draw_geom (void *c);
void ctr_render_free_geom (void *c);
-void ctr_render_chunk (int x, int y, int z, void *geom)
+int ctr_render_chunk (int x, int y, int z, void *geom)
CODE:
ctr_render_clear_geom (geom);
- ctr_render_chunk (x, y, z, geom);
+ RETVAL = ctr_render_chunk (x, y, z, geom);
+ OUTPUT:
+ RETVAL
void
ctr_render_model (unsigned int type, double light, unsigned int xo, unsigned int yo, unsigned int zo, void *geom, int skip, int force_model)
@@ -198,6 +200,15 @@ void ctr_world_init (SV *change_cb, SV *cell_change_cb)
SvREFCNT_inc (cell_change_cb);
WORLD.active_cell_change_cb = cell_change_cb;
+
+int
+ctr_world_has_chunk (int x, int y, int z)
+ CODE:
+ ctr_chunk *chnk = ctr_world_chunk (x, y, z, 0);
+ RETVAL = chnk ? 1 : 0;
+ OUTPUT:
+ RETVAL
+
SV *
ctr_world_get_chunk_data (int x, int y, int z)
CODE:
View
7 lib/Games/Construder/Client.pm
@@ -63,9 +63,9 @@ sub new {
$self->send_server ({ cmd => "visibility_radius", radius => $radius });
},
visible_chunks_changed => sub {
- my ($front, $new, $old) = @_;
+ my ($front, $new, $old, $req) = @_;
# warn "NEW: @$new, OLD @$old\n";
- $self->send_server ({ cmd => "vis_chunks", old => $old, new => $new });
+ $self->send_server ({ cmd => "vis_chunks", old => $old, new => $new, req => $req });
}
);
@@ -202,6 +202,9 @@ sub handle_packet : event_cb {
$self->{front}->remove_highlight_model ($hdr->{id});
}
+ } elsif ($hdr->{cmd} eq 'dirty_chunks') {
+ $self->{front}->clear_chunk ($_) for @{$hdr->{chnks}}
+
} elsif ($hdr->{cmd} eq 'chunk') {
$body = decompress ($body);
# WARNING FIXME XXX: this data might not be freed up all chunks that
View
52 lib/Games/Construder/Client/Frontend.pm
@@ -228,7 +228,6 @@ sub set_ambient_light {
for my $id (keys %{$self->{compiled_chunks}}) {
$self->compile_chunk (@{world_id2pos ($_)});
}
-
}
sub free_compiled_chunk {
@@ -255,7 +254,7 @@ sub compile_chunk {
}
delete $self->{dirty_chunks}->{$id};
- Games::Construder::Renderer::chunk ($cx, $cy, $cz, $geom);
+ return Games::Construder::Renderer::chunk ($cx, $cy, $cz, $geom);
}
sub step_animations {
@@ -284,6 +283,8 @@ sub set_player_pos {
my ($self, $pos) = @_;
warn "NEW PLAYER POS: @$pos\n";
$self->{phys_obj}->{player}->{pos} = $pos;
+ delete $self->{visible_chunks};
+ $self->calc_visibility;
}
sub get_visible_chunks {
@@ -325,6 +326,11 @@ sub dirty_chunk {
}
}
+sub clear_chunk {
+ my ($self, $chnk) = @_;
+ $self->free_compiled_chunk (@$chnk);
+}
+
sub remove_highlight_model {
my ($self, $id) = @_;
delete $self->{model_highlights}->{$id};
@@ -402,19 +408,24 @@ sub calc_visibility {
my $old_vis = $self->{visible_chunks};
my $new_vis = { };
- my (@newv, @oldv);
+ my (@newv, @oldv, @req);
for my $c (@chunks) {
my $cid = world_pos2id ($c);
if ($old_vis->{$cid}) {
delete $old_vis->{$cid};
- } elsif (!$new_vis->{$cid}) {
+
+ } elsif (not exists $new_vis->{$cid}) {
push @newv, $c;
}
$new_vis->{$cid} = $c;
+ unless (Games::Construder::World::has_chunk (@$c)) {
+ push @req, $c;
+ }
}
+ #d# print "VISIBLE CHUNKS: " . join (", ", keys %$new_vis) . " (NEW ".join (", ", map { world_pos2id ($_) } @newv).") (OLD " . join (", ", map { world_pos2id ($_) } @oldv).")\n";
(@oldv) = values %$old_vis;
- $self->visible_chunks_changed (\@newv, \@oldv)
- if @newv || @oldv;
+ $self->visible_chunks_changed (\@newv, \@oldv, \@req)
+ if @newv || @oldv || @req;
$self->{visible_chunks} = $new_vis;
}
@@ -489,20 +500,34 @@ sub render_scene {
vlength (vsub ($plchnk, $b))
} @compl_end;
my $tc = time;
- $tleft -= $tleft / 3; # lets don't overdo it
- my $ac = $tleft < 0 ? 0.001 : $tleft; # we MUST allow at least one per frame, otherwise on other machines maybe none are compiled...
+ $tleft -= $tleft / 2; # lets don't overdo it
+ # we MUST allow at least one per frame, otherwise on
+ # other machines maybe none are compiled...
+ my $ac = $tleft < 0 ? 0.001 : $tleft;
+
+ my @request;
my $cnt = 0;
- while ((time - $tc) < $ac) {
+ my $max = 4;
+ while ($max-- > 0 && (time - $tc) < $ac) {
my $chnk = shift @compl_end
or last;
- $self->compile_chunk (@$chnk);
+ unless ($self->compile_chunk (@$chnk)) {
+ push @request, $chnk;
+ }
$cnt++;
}
+ my $tok = time - $tc;
- warn "compiled $cnt chunks in $ac, but only had $tleft left, but " . scalar (@compl_end) . " chunks still to compile...\n";
+ warn "compiled $cnt chunks in $tok, but only had $tleft left, but "
+ . scalar (@compl_end) . " chunks still to compile...\n";
(@compl_end) = ();
+
+ if (@request) {
+ warn "requesting " . scalar (@request) . " chnks\n";
+ $self->visible_chunks_changed ([], [], \@request);
+ }
}
$render_time += time - $t1;
@@ -1293,7 +1318,10 @@ sub update_player_pos : event_cb {
}
sub visible_chunks_changed : event_cb {
- my ($self, $new, $old) = @_;
+ my ($self, $new, $old, $req) = @_;
+ # TODO: $req might be issued again and again with the same chunks,
+ # we should mabye rate limit that for more bandwidth friendly
+ # behaviour
}
sub visibility_radius : event_cb {
View
10 lib/Games/Construder/Server.pm
@@ -149,14 +149,6 @@ sub schedule_chunk_upd {
}
}
-sub check_players_uptodate {
- my ($self) = @_;
-
- for (values %{$self->{players}}) {
- $_->check_visible_chunks_uptodate;
- }
-}
-
sub players_near_pos {
my ($self, $pos) = @_;
my @p;
@@ -192,7 +184,7 @@ sub handle_player_packet : event_cb {
$player->set_vis_rad ($hdr->{radius});
} elsif ($hdr->{cmd} eq 'vis_chunks') {
- $player->set_visible_chunks ($hdr->{new}, $hdr->{old});
+ $player->set_visible_chunks ($hdr->{new}, $hdr->{old}, $hdr->{req});
} elsif ($hdr->{cmd} eq 'pos_action') {
if ($hdr->{action} == 1 && @{$hdr->{build_pos} || []}) {
View
65 lib/Games/Construder/Server/Player.pm
@@ -416,9 +416,7 @@ sub update_pos {
sub upd_visible_chunks {
my ($self) = @_;
$self->calc_visible_sectors;
- world_load_at_player ($self, sub {
- $self->check_visible_chunks_uptodate;
- });
+ world_load_at_player ($self, sub { });
}
sub get_pos_normalized {
@@ -442,23 +440,22 @@ sub set_vis_rad {
}
sub set_visible_chunks {
- my ($self, $new, $old) = @_;
+ my ($self, $new, $old, $req) = @_;
+
for (@$old) {
my $id = world_pos2id ($_);
delete $self->{visible_chunk_ids}->{$id};
}
+
for (@$new) {
my $id = world_pos2id ($_);
$self->{visible_chunk_ids}->{$id} = $_;
}
- my @chnks = values %{$self->{visible_chunk_ids}};
- $self->{visible_chunks} = \@chnks;
- for (keys %{$self->{chunk_uptodate}}) {
- unless ($self->{visible_chunk_ids}->{$_}) {
- delete $self->{chunk_uptodate}->{$_};
- }
+ for (@{$req || []}) {
+ $self->{to_send_chunks}->{world_pos2id ($_)} = $_;
}
+
}
sub calc_visible_sectors {
@@ -483,36 +480,27 @@ sub calc_visible_sectors {
sub chunk_updated {
my ($self, $chnk) = @_;
- delete $self->{chunk_uptodate}->{world_pos2id ($chnk)};
-}
+ my $id = world_pos2id ($chnk);
-sub check_visible_chunks_uptodate {
- my ($self) = @_;
+ #d#warn "TEST[$id] vs [" . join (", ", keys %{$self->{visible_chunk_ids}}) . "]\n";
+
+ if ($self->{visible_chunk_ids}->{$id}) {
+ $self->{to_send_chunks}->{$id} = $chnk;
-# my @upds;
-# for (keys %{$self->{visible_chunk_ids}}) {
-# unless ($self->{chunk_uptodate}->{$_}) {
-# push @upds, world_id2pos ($_);
-# }
-# }
-# push @{$self->{chunk_network_upd}}, @upds;
-
-# if (@upds) {
-# $self->send_client ({ cmd => "chunk_upd_start" });
-# $self->send_chunk ($_) for @upds;
-# warn "done sending " . scalar (@upds) . " chunk updates.\n";
-# $self->send_client ({ cmd => "chunk_upd_done" });
-# }
+ } else {
+ if ($self->{sent_chunks}->{$id}) {
+ $self->send_client ({ cmd => "dirty_chunks", chnks => [$chnk] });
+ delete $self->{sent_chunks}->{$id};
+ }
+ }
+ #delete $self->{chunk_uptodate}->{world_pos2id ($chnk)};
}
sub push_chunk_to_network {
my ($self) = @_;
- my @upds;
- for (keys %{$self->{visible_chunk_ids}}) {
- unless ($self->{chunk_uptodate}->{$_}) {
- push @upds, world_id2pos ($_);
- }
- }
+
+ my (@upds) = values %{$self->{to_send_chunks}};
+
my $plpos = $self->{data}->{pos};
my $plchnk = world_pos2chnkpos ($self->{data}->{pos});
(@upds) = sort {
@@ -533,21 +521,20 @@ sub push_chunk_to_network {
sub send_chunk {
my ($self, $chnk) = @_;
- # evenif the chunk is not allocated, it should be marked as "uptodate".
- # not allocated means: it either will be loaded (and then updated) or
- # wont be loaded anytime soon!
- $self->{chunk_uptodate}->{world_pos2id ($chnk)} = 1;
-
# only send chunk when allcoated, in all other cases the chunk will
# be sent by the chunk_changed-callback by the server (when it checks
# whether any player might be interested in that chunk).
+ my $id = world_pos2id ($chnk);
my $data = Games::Construder::World::get_chunk_data (@$chnk);
unless (defined $data) {
#d# warn "send_chunk: @$chnk was not yet allocated!\n";
+ delete $self->{to_send_chunks}->{$id};
return;
}
$self->send_client ({ cmd => "chunk", pos => $chnk }, compress ($data));
+ $self->{sent_chunks}->{$id} = $chnk;
+ delete $self->{to_send_chunks}->{$id};
}
sub msg {
View
22 lib/Games/Construder/Server/World.pm
@@ -62,8 +62,6 @@ our @SAVE_SECTORS_QUEUE;
our @LIGHTQUEUE;
our %LIGHTQUEUE;
-our $INHIBIT_CHUNK_UPTODATE_CHECK = 0;
-
our $SRV;
sub world_init {
@@ -74,8 +72,9 @@ sub world_init {
Games::Construder::World::init (
sub {
my ($x, $y, $z) = @_;
+ my $chnk = [$x, $y, $z];
- my $sec = world_chnkpos2secpos ([$x, $y, $z]);
+ my $sec = world_chnkpos2secpos ($chnk);
my $id = world_pos2id ($sec);
unless (exists $SECTORS{$id}) {
# this might happen either due to bugs or when sectors are loaded
@@ -87,12 +86,8 @@ sub world_init {
}
world_sector_dirty ($sec);
- my $chnk = [@_];
for (values %{$server->{players}}) {
$_->chunk_updated ($chnk);
- unless ($INHIBIT_CHUNK_UPTODATE_CHECK) {
- $_->check_visible_chunks_uptodate;
- }
}
},
sub {
@@ -222,7 +217,6 @@ sub _calc_some_lights {
my $calced;
{
- local $INHIBIT_CHUNK_UPTODATE_CHECK = 1;
while ((time - $t1) < $alloced_time) {
my $pos = shift @LIGHTQUEUE
or last;
@@ -242,10 +236,6 @@ sub _calc_some_lights {
printf "calclight step %0.4f, calced %d lights, %d lights to go\n",
time - $t1, $calced, scalar @LIGHTQUEUE;
}
- if ($light_upd_chunks_wait++ > 5) {
- $SRV->check_players_uptodate;
- $light_upd_chunks_wait = 0;
- }
}
sub _query_push_lightqueue {
@@ -348,13 +338,10 @@ sub _world_make_sector {
warn "created sector @$sec in $smeta->{creation_time} seconds\n";
{
- local $INHIBIT_CHUNK_UPTODATE_CHECK = 1;
Games::Construder::World::query_desetup (2);
}
warn "PLACED $cnt / $plcnt lights $type ($flot) in $tsum!\n";
-
- $SRV->check_players_uptodate;
}
sub _world_load_sector {
@@ -408,8 +395,6 @@ sub _world_load_sector {
$meta->{load_time} = time;
{
- local $INHIBIT_CHUNK_UPTODATE_CHECK = 1;
-
my $offs;
my $first_chnk = world_secpos2chnkpos ($sec);
my @chunks;
@@ -447,7 +432,6 @@ sub _world_load_sector {
. sprintf ("%.3f seconds", time - $t1)
. ".\n";
- $SRV->check_players_uptodate;
return 1;
} else {
@@ -737,10 +721,8 @@ sub world_mutate_at {
}
{
- local $INHIBIT_CHUNK_UPTODATE_CHECK = 1;
Games::Construder::World::query_desetup ();
}
- $SRV->check_players_uptodate;
}
sub world_find_free_spot {
View
6 render.c
@@ -526,12 +526,12 @@ double ctr_cell_light (ctr_cell *c)
return light;
}
-void
+int
ctr_render_chunk (int x, int y, int z, void *geom)
{
ctr_chunk *c = ctr_world_chunk (x, y, z, 0);
if (!c)
- return;
+ return 0;
LOAD_NEIGHBOUR_CHUNKS(x,y,z);
@@ -597,5 +597,5 @@ ctr_render_chunk (int x, int y, int z, void *geom)
}
ctr_render_compile_geom (geom);
- return;
+ return 1;
}
Please sign in to comment.
Something went wrong with that request. Please try again.