ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/Client.xs
(Generate patch)

Comparing deliantra/Deliantra-Client/Client.xs (file contents):
Revision 1.174 by root, Fri Apr 6 07:45:34 2007 UTC vs.
Revision 1.178 by root, Tue Apr 10 11:12:53 2007 UTC

163typedef struct { 163typedef struct {
164 int name; 164 int name;
165 int w, h; 165 int w, h;
166 float s, t; 166 float s, t;
167 uint8_t r, g, b, a; 167 uint8_t r, g, b, a;
168 tileid smoothtile;
169 uint8_t smoothlevel;
168} maptex; 170} maptex;
169 171
170typedef struct { 172typedef struct {
171 uint32_t player; 173 uint32_t player;
172 tileid tile[3]; 174 tileid tile[3];
173 uint16_t darkness; 175 uint16_t darkness;
174 uint8_t stat_width, stat_hp, flags; 176 uint8_t stat_width, stat_hp, flags, smoothmax;
175} mapcell; 177} mapcell;
176 178
177typedef struct { 179typedef struct {
178 int32_t c0, c1; 180 int32_t c0, c1;
179 mapcell *col; 181 mapcell *col;
333 cell->stat_hp = 0; 335 cell->stat_hp = 0;
334 cell->flags = 0; 336 cell->flags = 0;
335 cell->player = 0; 337 cell->player = 0;
336 } 338 }
337 } 339 }
340}
341
342typedef struct {
343 tileid tile;
344 uint8_t x, y, level;
345} smooth_key;
346
347static void
348smooth_or_bits (HV *hv, smooth_key *key, IV bits)
349{
350 SV **sv = hv_fetch (hv, (char *)key, sizeof (key), 1);
351
352 if (SvIOK (*sv))
353 SvIV_set (*sv, SvIVX (*sv) | bits);
354 else
355 sv_setiv (*sv, bits);
338} 356}
339 357
340static void 358static void
341music_finished (void) 359music_finished (void)
342{ 360{
1295 need_facenum (self, face); self->face2tile [face] = tile; 1313 need_facenum (self, face); self->face2tile [face] = tile;
1296 need_texid (self, tile); 1314 need_texid (self, tile);
1297} 1315}
1298 1316
1299void 1317void
1318set_smooth (CFPlus::Map self, int face, int smooth, int level)
1319 CODE:
1320{
1321 tileid texid;
1322 maptex *tex;
1323
1324 if (face < 0 || face >= self->faces)
1325 return;
1326
1327 if (smooth < 0 || smooth >= self->faces)
1328 return;
1329
1330 texid = self->face2tile [face];
1331
1332 if (!texid)
1333 return;
1334
1335 tex = self->tex + texid;
1336 tex->smoothtile = self->face2tile [smooth];
1337 tex->smoothlevel = level;
1338}
1339
1340void
1300set_texture (CFPlus::Map self, int texid, int name, int w, int h, float s, float t, int r, int g, int b, int a) 1341set_texture (CFPlus::Map self, int texid, int name, int w, int h, float s, float t, int r, int g, int b, int a)
1301 CODE: 1342 CODE:
1302{ 1343{
1303 need_texid (self, texid); 1344 need_texid (self, texid);
1304 1345
1524 1565
1525void 1566void
1526draw (CFPlus::Map self, int mx, int my, int sw, int sh, int T) 1567draw (CFPlus::Map self, int mx, int my, int sw, int sh, int T)
1527 CODE: 1568 CODE:
1528{ 1569{
1570 HV *smooth = (HV *)sv_2mortal ((SV *)newHV ());
1571 uint32_t smooth_level[256 / 32]; // one bit for every possible smooth level
1572 static uint8_t smooth_max[256][256]; // egad, fats and wasteful on memory (64k)
1573 smooth_key skey;
1529 int x, y, z; 1574 int x, y, z;
1530 int last_name; 1575 int last_name;
1576
1577 // thats current max. sorry.
1578 if (sw > 255) sw = 255;
1579 if (sh > 255) sh = 255;
1580
1581 // clear key, in case of extra padding
1582 memset (&skey, 0, sizeof (skey));
1531 1583
1532 glColor4ub (255, 255, 255, 255); 1584 glColor4ub (255, 255, 255, 255);
1533 1585
1534 glEnable (GL_BLEND); 1586 glEnable (GL_BLEND);
1535 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 1587 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1541 last_name = 0; 1593 last_name = 0;
1542 1594
1543 mx += self->x; 1595 mx += self->x;
1544 my += self->y; 1596 my += self->y;
1545 1597
1598 // first pass: determine smooth_max
1599 // rather ugly, if you ask me
1600 // could also be stored inside mapcell and updated on change
1601 memset (smooth_max, 0, sizeof (smooth_max));
1602
1603 for (y = 0; y < sh; y++)
1604 if (0 <= y + my && y + my < self->rows)
1605 {
1606 maprow *row = self->row + (y + my);
1607
1608 for (x = 0; x < sw; x++)
1609 if (row->c0 <= x + mx && x + mx < row->c1)
1610 {
1611 mapcell *cell = row->col + (x + mx - row->c0);
1612
1613 smooth_max[x + 1][y + 1] =
1614 MAX (self->tex [cell->tile [0]].smoothlevel,
1615 MAX (self->tex [cell->tile [1]].smoothlevel,
1616 self->tex [cell->tile [2]].smoothlevel));
1617 }
1618 }
1619
1546 for (z = 0; z < 3; z++) 1620 for (z = 0; z <= 2; z++)
1621 {
1622 memset (smooth_level, 0, sizeof (smooth_level));
1623
1547 for (y = 0; y < sh; y++) 1624 for (y = 0; y < sh; y++)
1548 if (0 <= y + my && y + my < self->rows) 1625 if (0 <= y + my && y + my < self->rows)
1549 { 1626 {
1550 maprow *row = self->row + (y + my); 1627 maprow *row = self->row + (y + my);
1551 1628
1552 for (x = 0; x < sw; x++) 1629 for (x = 0; x < sw; x++)
1553 if (row->c0 <= x + mx && x + mx < row->c1) 1630 if (row->c0 <= x + mx && x + mx < row->c1)
1554 { 1631 {
1555 mapcell *cell = row->col + (x + mx - row->c0); 1632 mapcell *cell = row->col + (x + mx - row->c0);
1556 tileid tile = cell->tile [z]; 1633 tileid tile = cell->tile [z];
1634
1635 if (tile)
1636 {
1637 maptex tex = self->tex [tile];
1638 int px = (x + 1) * T - tex.w;
1639 int py = (y + 1) * T - tex.h;
1640
1641 // suppressing texture state switches here
1642 // is only moderately effective, but worth the extra effort
1643 if (last_name != tex.name)
1644 {
1645 if (!tex.name)
1646 tex = self->tex [2]; /* missing, replace by noface */
1647
1648 glEnd ();
1649 glBindTexture (GL_TEXTURE_2D, last_name = tex.name);
1650 glBegin (GL_QUADS);
1651 }
1652
1653 glTexCoord2f (0 , 0 ); glVertex2f (px , py );
1654 glTexCoord2f (0 , tex.t); glVertex2f (px , py + tex.h);
1655 glTexCoord2f (tex.s, tex.t); glVertex2f (px + tex.w, py + tex.h);
1656 glTexCoord2f (tex.s, 0 ); glVertex2f (px + tex.w, py );
1657
1658 if (cell->flags && z == 2)
1659 {
1660 if (cell->flags & 1)
1661 {
1662 maptex tex = self->tex [1];
1663 int px = x * T + T * 2 / 32;
1664 int py = y * T - T * 6 / 32;
1665
1666 glEnd ();
1667 glBindTexture (GL_TEXTURE_2D, last_name = tex.name);
1668 glBegin (GL_QUADS);
1669
1670 glTexCoord2f (0 , 0 ); glVertex2f (px , py );
1671 glTexCoord2f (0 , tex.t); glVertex2f (px , py + T);
1672 glTexCoord2f (tex.s, tex.t); glVertex2f (px + T, py + T);
1673 glTexCoord2f (tex.s, 0 ); glVertex2f (px + T, py );
1674 }
1675 }
1676
1677 // update smooth hash
1678 if (tex.smoothtile)
1679 {
1680 skey.tile = tex.smoothtile;
1681 skey.level = tex.smoothlevel;
1682
1683 smooth_level [tex.smoothlevel >> 5] |= ((uint32_t)1) << (tex.smoothlevel & 31);
1684
1685 // add bits to current tile and all neighbours. skey.x|y is
1686 // shifted +1|+1 so we always stay positive.
1687
1688 // full tile
1689 skey.x = x + 1; skey.y = y + 1; smooth_or_bits (smooth, &skey, 0x1000);
1690
1691 // borders
1692 skey.x = x + 2; skey.y = y + 1; smooth_or_bits (smooth, &skey, 0x0031);
1693 skey.x = x + 1; skey.y = y + 2; smooth_or_bits (smooth, &skey, 0x0092);
1694 skey.x = x ; skey.y = y + 1; smooth_or_bits (smooth, &skey, 0x0064);
1695 skey.x = x + 1; skey.y = y ; smooth_or_bits (smooth, &skey, 0x00c8);
1696
1697 // corners
1698 skey.x = x + 2; skey.y = y + 2; smooth_or_bits (smooth, &skey, 0x0100);
1699 skey.x = x ; skey.y = y + 2; smooth_or_bits (smooth, &skey, 0x0200);
1700 skey.x = x ; skey.y = y ; smooth_or_bits (smooth, &skey, 0x0400);
1701 skey.x = x + 2; skey.y = y ; smooth_or_bits (smooth, &skey, 0x0800);
1702 }
1703 }
1557 1704 }
1705 }
1706
1707 // go through all smoothlevels, lowest to highest, then draw
1708 // this is basically counting sort
1709 {
1710 int w, b;
1711
1712 for (w = 0; w < 256 / 32; ++w)
1713 {
1714 uint32_t smask = smooth_level [w];
1558 if (tile) 1715 if (smask)
1716 for (b = 0; b < 32; ++b)
1717 if (smask & (((uint32_t)1) << b))
1559 { 1718 {
1560 maptex tex = self->tex [tile]; 1719 int level = (w << 5) | b;
1561 int px = (x + 1) * T - tex.w; 1720 HE *he;
1562 int py = (y + 1) * T - tex.h;
1563 1721
1564 if (last_name != tex.name) 1722 hv_iterinit (smooth);
1723 while ((he = hv_iternext (smooth)))
1565 { 1724 {
1725 smooth_key *skey = (smooth_key *)HeKEY (he);
1726 IV bits = SvIVX (HeVAL (he));
1727
1728 // bits is ___n cccc CCCC bbbb
1729 // n do not draw borders&corners
1730 // c draw these corners, but...
1731 // C ... not these
1732 // b draw these borders
1733
1566 if (!tex.name) 1734 if (!(bits & 0x1000)
1567 tex = self->tex [2]; /* missing, replace by noface */ 1735 && skey->level == level
1568 1736 && level >= smooth_max [skey->x][skey->y])
1569 glEnd ();
1570 glBindTexture (GL_TEXTURE_2D, last_name = tex.name);
1571 glBegin (GL_QUADS);
1572 }
1573
1574 glTexCoord2f (0 , 0 ); glVertex2f (px , py );
1575 glTexCoord2f (0 , tex.t); glVertex2f (px , py + tex.h);
1576 glTexCoord2f (tex.s, tex.t); glVertex2f (px + tex.w, py + tex.h);
1577 glTexCoord2f (tex.s, 0 ); glVertex2f (px + tex.w, py );
1578
1579 if (cell->flags && z == 2)
1580 {
1581 if (cell->flags & 1)
1582 { 1737 {
1583 maptex tex = self->tex [1]; 1738 maptex tex = self->tex [skey->tile];
1584 int px = x * T + T * 2 / 32; 1739 int px = (((int)skey->x) - 1) * T;
1585 int py = y * T - T * 6 / 32; 1740 int py = (((int)skey->y) - 1) * T;
1741 int border = bits & 15;
1742 int corner = (bits >> 8) & ~(bits >> 4) & 15;
1743 float dx = tex.s * .0625f; // 16 images/row
1744 float dy = tex.t * .5f ; // 2 images/column
1586 1745
1746 // this time naively avoiding texture state changes
1747 // save gobs of state changes.
1748 if (last_name != tex.name)
1749 {
1750 if (!tex.name)
1751 continue; // smoothing not yet available
1752
1587 glEnd (); 1753 glEnd ();
1588 glBindTexture (GL_TEXTURE_2D, last_name = tex.name); 1754 glBindTexture (GL_TEXTURE_2D, last_name = tex.name);
1589 glBegin (GL_QUADS); 1755 glBegin (GL_QUADS);
1756 }
1590 1757
1758 if (border)
1759 {
1760 float ox = border * dx;
1761
1762 glTexCoord2f (ox , 0.f ); glVertex2f (px , py );
1763 glTexCoord2f (ox , dy ); glVertex2f (px , py + T);
1764 glTexCoord2f (ox + dx, dy ); glVertex2f (px + T, py + T);
1765 glTexCoord2f (ox + dx, 0.f ); glVertex2f (px + T, py );
1766 }
1767
1768 if (corner)
1769 {
1770 float ox = corner * dx;
1771
1591 glTexCoord2f (0 , 0 ); glVertex2f (px , py ); 1772 glTexCoord2f (ox , dy ); glVertex2f (px , py );
1592 glTexCoord2f (0 , tex.t); glVertex2f (px , py + T); 1773 glTexCoord2f (ox , dy * 2.f); glVertex2f (px , py + T);
1593 glTexCoord2f (tex.s, tex.t); glVertex2f (px + T, py + T); 1774 glTexCoord2f (ox + dx, dy * 2.f); glVertex2f (px + T, py + T);
1594 glTexCoord2f (tex.s, 0 ); glVertex2f (px + T, py ); 1775 glTexCoord2f (ox + dx, dy ); glVertex2f (px + T, py );
1776 }
1595 } 1777 }
1596 } 1778 }
1597 } 1779 }
1598 }
1599 } 1780 }
1781 }
1782
1783 hv_clear (smooth);
1784 }
1600 1785
1601 glEnd (); 1786 glEnd ();
1602 1787
1603 glDisable (GL_TEXTURE_2D); 1788 glDisable (GL_TEXTURE_2D);
1604 glDisable (GL_BLEND); 1789 glDisable (GL_BLEND);
1856 2041
1857 for (z = 0; z <= 2; z++) 2042 for (z = 0; z <= 2; z++)
1858 { 2043 {
1859 tileid t = tile [z]; 2044 tileid t = tile [z];
1860 2045
1861 if (t >= self->texs || !self->tex [t].name) 2046 if (t >= self->texs || (t && !self->tex [t].name))
1862 { 2047 {
1863 XPUSHs (sv_2mortal (newSViv (t))); 2048 XPUSHs (sv_2mortal (newSViv (t)));
1864 need_texid (self, t); 2049 need_texid (self, t);
1865 } 2050 }
1866 2051

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines