--- deliantra/Deliantra-Client/Client.xs 2018/11/18 01:48:39 1.323 +++ deliantra/Deliantra-Client/Client.xs 2018/11/18 12:01:50 1.327 @@ -34,6 +34,7 @@ #include #include +#include #define USE_RWOPS 1 // for SDL_mixer:LoadMUS_RW @@ -206,7 +207,7 @@ float r, g, b, a; // default color for rgba mode int base_height; DC__Font font; - rc_t *rc; + rc_t rc; }; typedef cf_layout *DC__Layout; @@ -288,11 +289,18 @@ struct mapgrid { int x, y, w, h; int ox, oy; /* offset to virtual global coordinate system */ - int faces; tileid *face2tile; // [faceid] - int texs; maptex *tex; // [tileid] + std::vector tile; + std::vector tex; int32_t rows; maprow *row; + + ~mapgrid () + { + clear_cells (); + } + + void clear_cells (); }; typedef mapgrid *DC__Map; @@ -322,26 +330,6 @@ #define Append(type,ptr,sze,inc) (ptr) = (type *)append ((char *)ptr, (sze) * sizeof (type), (inc) * sizeof (type)) #define Prepend(type,ptr,sze,inc) (ptr) = (type *)prepend ((char *)ptr, (sze) * sizeof (type), (inc) * sizeof (type)) -static void -need_facenum (struct mapgrid *self, faceid face) -{ - while (self->faces <= face) - { - Append (tileid, self->face2tile, self->faces, self->faces); - self->faces *= 2; - } -} - -static void -need_texid (struct mapgrid *self, int texid) -{ - while (self->texs <= texid) - { - Append (maptex, self->tex, self->texs, self->texs); - self->texs *= 2; - } -} - static maprow * map_get_row (mapgrid *self, int y) { @@ -396,22 +384,21 @@ return row_get_cell (map_get_row (self, y), x); } -static void -map_clear (mapgrid *self) +void mapgrid::clear_cells () { int r; - for (r = 0; r < self->rows; r++) - Safefree (self->row[r].col); + for (r = 0; r < rows; r++) + Safefree (row[r].col); - Safefree (self->row); + Safefree (row); - self->x = 0; - self->y = 0; - self->ox = 0; - self->oy = 0; - self->row = 0; - self->rows = 0; + x = 0; + y = 0; + ox = 0; + oy = 0; + row = 0; + rows = 0; } #define CELL_CLEAR(cell) \ @@ -1370,7 +1357,7 @@ DC::Layout new (SV *klass) CODE: - New (0, RETVAL, 1, struct cf_layout); + RETVAL = new cf_layout; RETVAL->pl = pango_layout_new (opengl_context); RETVAL->r = 1.; @@ -1379,7 +1366,6 @@ RETVAL->a = 1.; RETVAL->base_height = MIN_FONT_HEIGHT; RETVAL->font = 0; - RETVAL->rc = rc_alloc (); pango_layout_set_wrap (RETVAL->pl, PANGO_WRAP_WORD_CHAR); layout_update_font (RETVAL); @@ -1390,8 +1376,7 @@ DESTROY (DC::Layout self) CODE: g_object_unref (self->pl); - rc_free (self->rc); - Safefree (self); + delete self; void set_text (DC::Layout self, SV *text_) @@ -1655,10 +1640,10 @@ void render (DC::Layout self, float x, float y, int flags = 0) CODE: - rc_clear (self->rc); + self->rc.clear (); pango_opengl_render_layout_subpixel ( self->pl, - self->rc, + &self->rc, x * PANGO_SCALE, y * PANGO_SCALE, self->r, self->g, self->b, self->a, flags @@ -1679,7 +1664,7 @@ glEnable (GL_ALPHA_TEST); glAlphaFunc (GL_GREATER, 7.f / 255.f); - rc_draw (self->rc); + self->rc.draw (); glDisable (GL_ALPHA_TEST); glDisable (GL_BLEND); @@ -1903,15 +1888,13 @@ DC::Map new (SV *klass) CODE: - New (0, RETVAL, 1, mapgrid); + RETVAL = new mapgrid; RETVAL->x = 0; RETVAL->y = 0; RETVAL->w = 0; RETVAL->h = 0; RETVAL->ox = 0; RETVAL->oy = 0; - RETVAL->faces = 8192; Newz (0, RETVAL->face2tile, RETVAL->faces, tileid); - RETVAL->texs = 8192; Newz (0, RETVAL->tex , RETVAL->texs , maptex); RETVAL->rows = 0; RETVAL->row = 0; OUTPUT: @@ -1921,10 +1904,7 @@ DESTROY (DC::Map self) CODE: { - map_clear (self); - Safefree (self->face2tile); - Safefree (self->tex); - Safefree (self); + delete self; } void @@ -1936,57 +1916,55 @@ void clear (DC::Map self) CODE: - map_clear (self); + self->clear_cells (); void set_tileid (DC::Map self, int face, int tile) CODE: { - need_facenum (self, face); self->face2tile [face] = tile; - need_texid (self, tile); + if (self->tile.size () <= face) self->tile.resize (face + 1); + self->tile[face] = tile; + if (self->tex.size () <= tile) self->tex .resize (tile + 1); } void set_smooth (DC::Map self, int face, int smooth, int level) CODE: { - tileid texid; - maptex *tex; - - if (face < 0 || face >= self->faces) + if (face < 0 || face >= self->tile.size ()) return; - if (smooth < 0 || smooth >= self->faces) + if (smooth < 0 || smooth >= self->tile.size ()) return; - texid = self->face2tile [face]; + tileid texid = self->tile[face]; if (!texid) return; - tex = self->tex + texid; - tex->smoothtile = self->face2tile [smooth]; - tex->smoothlevel = level; + maptex &tex = self->tex[texid]; + tex.smoothtile = self->tile[smooth]; + tex.smoothlevel = level; } void set_texture (DC::Map self, int texid, int name, int w, int h, float s, float t, int r, int g, int b, int a) CODE: { - need_texid (self, texid); + if (self->tex.size () < texid) self->tex.resize (texid + 1); { - maptex *tex = self->tex + texid; + maptex &tex = self->tex[texid]; - tex->name = name; - tex->w = w; - tex->h = h; - tex->s = s; - tex->t = t; - tex->r = r; - tex->g = g; - tex->b = b; - tex->a = a; + tex.name = name; + tex.w = w; + tex.h = h; + tex.s = s; + tex.t = t; + tex.r = r; + tex.g = g; + tex.b = b; + tex.a = a; } // somewhat hackish, but for textures that require it, it really @@ -2002,20 +1980,20 @@ void expire_textures (DC::Map self, int texid, int count) PPCODE: - for (; texid < self->texs && count; ++texid, --count) + for (; texid < self->tex.size () && count; ++texid, --count) { - maptex *tex = self->tex + texid; + maptex &tex = self->tex[texid]; - if (tex->name) + if (tex.name) { - if (tex->unused) + if (tex.unused) { - tex->name = 0; - tex->unused = 0; + tex.name = 0; + tex.unused = 0; XPUSHs (sv_2mortal (newSViv (texid))); } else - tex->unused = 1; + tex.unused = 1; } } @@ -2136,23 +2114,23 @@ for (z = 0; z <= 2; ++z) if (flags & (4 >> z)) { - faceid face = (data [0] << 8) + data [1]; data += 2; - need_facenum (self, face); - cell->tile [z] = self->face2tile [face]; + faceid face = (data[0] << 8) + data[1]; data += 2; + if (self->tile.size () <= face) self->tile.resize (face + 1); + cell->tile[z] = self->tile[face]; - if (cell->tile [z]) + if (cell->tile[z]) { - maptex *tex = self->tex + cell->tile [z]; - tex->unused = 0; - if (!tex->name) + maptex &tex = self->tex[cell->tile[z]]; + tex.unused = 0; + if (!tex.name) av_push (missing, newSViv (cell->tile [z])); - if (tex->smoothtile) + if (tex.smoothtile) { - maptex *smooth = self->tex + tex->smoothtile; - smooth->unused = 0; - if (!smooth->name) - av_push (missing, newSViv (tex->smoothtile)); + maptex &smooth = self->tex[tex.smoothtile]; + smooth.unused = 0; + if (!smooth.name) + av_push (missing, newSViv (tex.smoothtile)); } } } @@ -2225,15 +2203,13 @@ { int x, y, z; - uint32_t smooth_level[256 / 32]; // one bit for every possible smooth level - static uint8_t smooth_max[256][256]; // egad, fast and wasteful on memory (64k) - smooth_key skey; + static uint8_t smooth_max[256][256]; // egad, fast and wasteful on memory (64k), also, static! int pl_x, pl_y; maptex pl_tex; - rc_t *rc = rc_alloc (); - rc_t *rc_ov = rc_alloc (); + rc_t rc; + rc_t rc_ov; rc_key_t key; - rc_array_t *arr; + rc_t::array_t *arr; pl_tex.name = 0; @@ -2241,9 +2217,6 @@ if (sw > 255) sw = 255; if (sh > 255) sh = 255; - // clear key, in case of extra padding - memset (&skey, 0, sizeof (skey)); - memset (&key, 0, sizeof (key)); key.r = 255; key.g = 255; @@ -2258,7 +2231,7 @@ // first pass: determine smooth_max // rather ugly, if you ask me // could also be stored inside mapcell and updated on change - memset (smooth_max, 0, sizeof (smooth_max)); + memset (smooth_max, 0, sizeof (smooth_max[0]) * (sh + 1)); for (y = 0; y < sh; y++) if (0 <= y + my && y + my < self->rows) @@ -2283,8 +2256,9 @@ for (z = 0; z <= 2; z++) { + std::bitset<256> smooth_level; // one bit for every possible smooth level + smooth_key skey; smooth_hash smooth; - memset (smooth_level, 0, sizeof (smooth_level)); key.texname = -1; for (y = 0; y < sh; y++) @@ -2311,7 +2285,7 @@ tex = self->tex [TEXID_NOFACE]; /* missing, replace by noface */ key.texname = tex.name; - arr = rc_array (rc, &key); + arr = &rc.array (key); } px = (x + 1) * Th - tex.w; @@ -2325,10 +2299,10 @@ continue; } - rc_t2f_v3f (arr, 0 , 0 , px , py , 0); - rc_t2f_v3f (arr, 0 , tex.t, px , py + tex.h, 0); - rc_t2f_v3f (arr, tex.s, tex.t, px + tex.w, py + tex.h, 0); - rc_t2f_v3f (arr, tex.s, 0 , px + tex.w, py , 0); + arr->t2f_v3f (0 , 0 , px , py , 0); + arr->t2f_v3f (0 , tex.t, px , py + tex.h, 0); + arr->t2f_v3f (tex.s, tex.t, px + tex.w, py + tex.h, 0); + arr->t2f_v3f (tex.s, 0 , px + tex.w, py , 0); // update smooth hash if (tex.smoothtile) @@ -2336,7 +2310,7 @@ skey.tile = tex.smoothtile; skey.level = tex.smoothlevel; - smooth_level [tex.smoothlevel >> 5] |= ((uint32_t)1) << (tex.smoothlevel & 31); + smooth_level[tex.smoothlevel] = 1; // add bits to current tile and all neighbours. skey.x|y is // shifted +1|+1 so we always stay positive. @@ -2376,25 +2350,24 @@ if (cell->flags & 1) { rc_key_t key_ov = key; - maptex tex = self->tex [TEXID_SPEECH]; - rc_array_t *arr; + maptex tex = self->tex[TEXID_SPEECH]; int px = x * Tw + Tw * 2 / 32; int py = y * Th - Th * 6 / 32; key_ov.texname = tex.name; - arr = rc_array (rc_ov, &key_ov); + rc_t::array_t &arr = rc_ov.array (key_ov); - rc_t2f_v3f (arr, 0 , 0 , px , py , 0); - rc_t2f_v3f (arr, 0 , tex.t, px , py + Th, 0); - rc_t2f_v3f (arr, tex.s, tex.t, px + Tw, py + Th, 0); - rc_t2f_v3f (arr, tex.s, 0 , px + Tw, py , 0); + arr.t2f_v3f (0 , 0 , px , py , 0); + arr.t2f_v3f (0 , tex.t, px , py + Th, 0); + arr.t2f_v3f (tex.s, tex.t, px + Tw, py + Th, 0); + arr.t2f_v3f (tex.s, 0 , px + Tw, py , 0); } } } } - rc_draw (rc); - rc_clear (rc); + rc.draw (); + rc.clear (); // go through all smoothlevels, lowest to highest, then draw. // this is basically counting sort @@ -2403,70 +2376,60 @@ glEnable (GL_TEXTURE_2D); glBegin (GL_QUADS); - for (w = 0; w < 256 / 32; ++w) - { - uint32_t smask = smooth_level [w]; - if (smask) - for (b = 0; b < 32; ++b) - if (smask & (((uint32_t)1) << b)) + for (int level = 0; level < smooth_level.size (); ++level) + if (smooth_level[level]) + for (auto &&it = smooth.begin (); it != smooth.end (); ++it) + { + smooth_key &skey = it->first; + IV bits = it->second; + + if (!(bits & 0x1000) + && skey.level == level + && level > smooth_max [skey.x][skey.y]) { - int level = (w << 5) | b; - HE *he; + maptex tex = self->tex [skey.tile]; + int px = (((int)skey.x) - 1) * Tw; + int py = (((int)skey.y) - 1) * Th; + int border = bits & 15; + int corner = (bits >> 8) & ~(bits >> 4) & 15; + float dx = tex.s * .0625f; // 16 images/row + float dy = tex.t * .5f ; // 2 images/column - for (auto &&it = smooth.begin (); it != smooth.end (); ++it) + if (tex.name) { - smooth_key &skey = it->first; - IV bits = it->second; + // this time avoiding texture state changes + // save gobs of state changes. + if (key.texname != tex.name) + { + self->tex [skey.tile].unused = 0; + + glEnd (); + glBindTexture (GL_TEXTURE_2D, key.texname = tex.name); + glBegin (GL_QUADS); + } + + if (border) + { + float ox = border * dx; + + glTexCoord2f (ox , 0.f ); glVertex2i (px , py ); + glTexCoord2f (ox , dy ); glVertex2i (px , py + Th); + glTexCoord2f (ox + dx, dy ); glVertex2i (px + Tw, py + Th); + glTexCoord2f (ox + dx, 0.f ); glVertex2i (px + Tw, py ); + } - if (!(bits & 0x1000) - && skey.level == level - && level > smooth_max [skey.x][skey.y]) + if (corner) { - maptex tex = self->tex [skey.tile]; - int px = (((int)skey.x) - 1) * Tw; - int py = (((int)skey.y) - 1) * Th; - int border = bits & 15; - int corner = (bits >> 8) & ~(bits >> 4) & 15; - float dx = tex.s * .0625f; // 16 images/row - float dy = tex.t * .5f ; // 2 images/column - - if (tex.name) - { - // this time avoiding texture state changes - // save gobs of state changes. - if (key.texname != tex.name) - { - self->tex [skey.tile].unused = 0; - - glEnd (); - glBindTexture (GL_TEXTURE_2D, key.texname = tex.name); - glBegin (GL_QUADS); - } - - if (border) - { - float ox = border * dx; - - glTexCoord2f (ox , 0.f ); glVertex2i (px , py ); - glTexCoord2f (ox , dy ); glVertex2i (px , py + Th); - glTexCoord2f (ox + dx, dy ); glVertex2i (px + Tw, py + Th); - glTexCoord2f (ox + dx, 0.f ); glVertex2i (px + Tw, py ); - } - - if (corner) - { - float ox = corner * dx; - - glTexCoord2f (ox , dy ); glVertex2i (px , py ); - glTexCoord2f (ox , dy * 2.f); glVertex2i (px , py + Th); - glTexCoord2f (ox + dx, dy * 2.f); glVertex2i (px + Tw, py + Th); - glTexCoord2f (ox + dx, dy ); glVertex2i (px + Tw, py ); - } - } + float ox = corner * dx; + + glTexCoord2f (ox , dy ); glVertex2i (px , py ); + glTexCoord2f (ox , dy * 2.f); glVertex2i (px , py + Th); + glTexCoord2f (ox + dx, dy * 2.f); glVertex2i (px + Tw, py + Th); + glTexCoord2f (ox + dx, dy ); glVertex2i (px + Tw, py ); } } } - } + } glEnd (); glDisable (GL_TEXTURE_2D); @@ -2481,22 +2444,20 @@ int py = pl_y + sdy; key.texname = tex.name; - arr = rc_array (rc, &key); + rc_t::array_t &arr = rc.array (key); - rc_t2f_v3f (arr, 0 , 0 , px , py , 0); - rc_t2f_v3f (arr, 0 , tex.t, px , py + tex.h, 0); - rc_t2f_v3f (arr, tex.s, tex.t, px + tex.w, py + tex.h, 0); - rc_t2f_v3f (arr, tex.s, 0 , px + tex.w, py , 0); + arr.t2f_v3f (0 , 0 , px , py , 0); + arr.t2f_v3f (0 , tex.t, px , py + tex.h, 0); + arr.t2f_v3f (tex.s, tex.t, px + tex.w, py + tex.h, 0); + arr.t2f_v3f (tex.s, 0 , px + tex.w, py , 0); - rc_draw (rc); + rc.draw (); } - rc_draw (rc_ov); - rc_clear (rc_ov); + rc_ov.draw (); + rc_ov.clear (); glDisable (GL_BLEND); - rc_free (rc); - rc_free (rc_ov); // top layer: overlays such as the health bar for (y = 0; y < sh; y++) @@ -2828,13 +2789,13 @@ { tileid t = tile [z]; - if (t >= self->texs || (t && !self->tex [t].name)) + if (t >= self->tex.size () || (t && !self->tex[t].name)) { PUSHs (sv_2mortal (newSViv (t))); - need_texid (self, t); + if (self->tex.size () <= t) self->tex.resize (t + 1); } - cell->tile [z] = t; + cell->tile[z] = t; } } }