|
708 | 708 | ...
|
709 | 709 | virtual bool hit(const ray& r, double tmin, double tmax, hit_record& rec) const;
|
710 | 710 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
|
711 |
| - virtual bool sphere::bounding_box(double t0, double t1, aabb& output_box) const; |
| 711 | + virtual bool bounding_box(double t0, double t1, aabb& output_box) const; |
712 | 712 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
|
713 | 713 | ...
|
714 | 714 | };
|
|
1536 | 1536 | To make it smooth, we can linearly interpolate:
|
1537 | 1537 |
|
1538 | 1538 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
|
| 1539 | + |
| 1540 | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight |
1539 | 1541 | inline double trilinear_interp(double c[2][2][2], double u, double v, double w) {
|
1540 | 1542 | auto accum = 0.0;
|
1541 | 1543 | for (int i=0; i < 2; i++)
|
|
1548 | 1550 | return accum;
|
1549 | 1551 | }
|
1550 | 1552 |
|
| 1553 | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ |
| 1554 | + |
1551 | 1555 | class perlin {
|
1552 | 1556 | public:
|
1553 | 1557 | ...
|
1554 | 1558 | double noise(point3 vec3& p) const {
|
1555 | 1559 | auto u = p.x() - floor(p.x());
|
1556 | 1560 | auto v = p.y() - floor(p.y());
|
1557 | 1561 | auto w = p.z() - floor(p.z());
|
| 1562 | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight |
| 1563 | + |
1558 | 1564 | int i = floor(p.x());
|
1559 | 1565 | int j = floor(p.y());
|
1560 | 1566 | int k = floor(p.z());
|
|
1570 | 1576 | ];
|
1571 | 1577 |
|
1572 | 1578 | return trilinear_interp(c, u, v, w);
|
| 1579 | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ |
1573 | 1580 | }
|
1574 | 1581 | ...
|
1575 | 1582 | }
|
|
1581 | 1588 | And we get:
|
1582 | 1589 |
|
1583 | 1590 |  |
| 1591 | + ](../images/img-2.08-perlin-trilerp.png class=pixel) |
1585 | 1592 |
|
1586 | 1593 | </div>
|
1587 | 1594 |
|
|
1620 | 1627 | This gives a smoother looking image:
|
1621 | 1628 |
|
1622 | 1629 |  |
| 1630 | + ](../images/img-2.09-perlin-trilerp-smooth.png class=pixel) |
1624 | 1631 |
|
1625 | 1632 | </div>
|
1626 | 1633 |
|
|
1634 | 1641 | class noise_texture : public texture {
|
1635 | 1642 | public:
|
1636 | 1643 | noise_texture() {}
|
| 1644 | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight |
1637 | 1645 | noise_texture(double sc) : scale(sc) {}
|
| 1646 | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ |
1638 | 1647 |
|
1639 | 1648 | virtual color value(double u, double v, const point3& p) const {
|
1640 | 1649 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
|
|
1644 | 1653 |
|
1645 | 1654 | public:
|
1646 | 1655 | perlin noise;
|
| 1656 | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight |
1647 | 1657 | double scale;
|
| 1658 | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ |
1648 | 1659 | };
|
1649 | 1660 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
1650 | 1661 | [Listing [perlin-smoothed-2]: <kbd>[texture.h]</kbd> Perlin smoothed, higher frequency]
|
| 1662 | +</div> |
| 1663 | + |
| 1664 | +<div class='together'> |
| 1665 | +We then add that scale to the `two_perlin_spheres()` scene description:: |
| 1666 | + |
| 1667 | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ |
| 1668 | + hittable_list two_perlin_spheres() { |
| 1669 | + hittable_list objects; |
| 1670 | + |
| 1671 | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight |
| 1672 | + auto pertext = make_shared<noise_texture>(4); |
| 1673 | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ |
| 1674 | + objects.add(make_shared<sphere>(point3(0,-1000,0), 1000, make_shared<lambertian>(pertext))); |
| 1675 | + objects.add(make_shared<sphere>(point3(0, 2, 0), 2, make_shared<lambertian>(pertext))); |
| 1676 | + |
| 1677 | + return objects; |
| 1678 | + } |
| 1679 | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 1680 | + [Listing [scale-perlin]: <kbd>[main.cc]</kbd> Perlin-textured spheres with a scale to the noise] |
| 1681 | +</div> |
1651 | 1682 |
|
1652 | 1683 | which gives:
|
1653 | 1684 |
|
1654 |
| -  |
| 1685 | +  |
1655 | 1686 |
|
1656 | 1687 | </div>
|
1657 | 1688 |
|
|
1669 | 1700 | class perlin {
|
1670 | 1701 | public:
|
1671 | 1702 | perlin() {
|
| 1703 | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight |
1672 | 1704 | ranvec = new vec3[point_count];
|
1673 |
| - |
| 1705 | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ |
1674 | 1706 | for (int i = 0; i < point_count; ++i) {
|
| 1707 | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight |
1675 | 1708 | ranvec[i] = unit_vector(vec3::random(-1,1));
|
| 1709 | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ |
1676 | 1710 | }
|
1677 | 1711 |
|
1678 | 1712 | perm_x = perlin_generate_perm();
|
|
1681 | 1715 | }
|
1682 | 1716 |
|
1683 | 1717 | ~perlin() {
|
| 1718 | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight |
1684 | 1719 | delete[] ranvec;
|
| 1720 | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ |
1685 | 1721 | delete[] perm_x;
|
1686 | 1722 | delete[] perm_y;
|
1687 | 1723 | delete[] perm_z;
|
1688 | 1724 | }
|
1689 | 1725 | ...
|
1690 | 1726 | private:
|
| 1727 | + static const int point_count = 256; |
| 1728 | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight |
1691 | 1729 | vec3* ranvec;
|
| 1730 | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ |
1692 | 1731 | int* perm_x;
|
1693 | 1732 | int* perm_y;
|
1694 | 1733 | int* perm_z;
|
|
1706 | 1745 | public:
|
1707 | 1746 | ...
|
1708 | 1747 | double noise(const point3& p) const {
|
| 1748 | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight |
1709 | 1749 | auto u = p.x() - floor(p.x());
|
1710 | 1750 | auto v = p.y() - floor(p.y());
|
1711 | 1751 | auto w = p.z() - floor(p.z());
|
| 1752 | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ |
1712 | 1753 | int i = floor(p.x());
|
1713 | 1754 | int j = floor(p.y());
|
1714 | 1755 | int k = floor(p.z());
|
| 1756 | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight |
1715 | 1757 | vec3 c[2][2][2];
|
| 1758 | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ |
1716 | 1759 |
|
1717 | 1760 | for (int di=0; di < 2; di++)
|
1718 | 1761 | for (int dj=0; dj < 2; dj++)
|
1719 | 1762 | for (int dk=0; dk < 2; dk++)
|
| 1763 | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight |
1720 | 1764 | c[di][dj][dk] = ranvec[
|
1721 | 1765 | perm_x[(i+di) & 255] ^
|
1722 | 1766 | perm_y[(j+dj) & 255] ^
|
1723 | 1767 | perm_z[(k+dk) & 255]
|
1724 | 1768 | ];
|
| 1769 | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ |
| 1770 | + |
1725 | 1771 |
|
| 1772 | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight |
1726 | 1773 | return perlin_interp(c, u, v, w);
|
| 1774 | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ |
1727 | 1775 | }
|
1728 | 1776 | ...
|
1729 | 1777 | }
|
|
1739 | 1787 | ...
|
1740 | 1788 | private:
|
1741 | 1789 | ...
|
1742 |
| - inline double perlin_interp(vec3 c[2][2][2], double u, double v, double w) { |
| 1790 | + inline double perlin_interp(vec3 c[2][2][2], double u, double v, double w) const { |
1743 | 1791 | auto uu = u*u*(3-2*u);
|
1744 | 1792 | auto vv = v*v*(3-2*v);
|
1745 | 1793 | auto ww = w*w*(3-2*w);
|
|
1792 | 1840 | This finally gives something more reasonable looking:
|
1793 | 1841 |
|
1794 | 1842 |  |
| 1843 | + ](../images/img-2.11-perlin-shift.png class=pixel) |
1796 | 1844 |
|
1797 | 1845 | </div>
|
1798 | 1846 |
|
|
1828 | 1876 |
|
1829 | 1877 | Here `fabs()` is the absolute value function defined in `<cmath>`.
|
1830 | 1878 |
|
| 1879 | +<div class='together'> |
| 1880 | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ |
| 1881 | + class noise_texture : public texture { |
| 1882 | + public: |
| 1883 | + noise_texture() {} |
| 1884 | + noise_texture(double sc) : scale(sc) {} |
| 1885 | + |
| 1886 | + virtual color value(double u, double v, const point3& p) const { |
| 1887 | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight |
| 1888 | + return color(1,1,1) * noise.turb(scale * p); |
| 1889 | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ |
| 1890 | + } |
| 1891 | + |
| 1892 | + public: |
| 1893 | + perlin noise; |
| 1894 | + double scale; |
| 1895 | + }; |
| 1896 | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 1897 | + [Listing [noise-tex-2]: <kbd>[texture.h]</kbd> Noise texture with turbulence] |
| 1898 | +</div> |
| 1899 | + |
1831 | 1900 | <div class='together'>
|
1832 | 1901 | Used directly, turbulence gives a sort of camouflage netting appearance:
|
1833 | 1902 |
|
1834 |
| -  |
| 1903 | +  |
1835 | 1904 |
|
1836 | 1905 | </div>
|
1837 | 1906 |
|
|
1862 | 1931 | double scale;
|
1863 | 1932 | };
|
1864 | 1933 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
1865 |
| - [Listing [noise-tex-2]: <kbd>[texture.h]</kbd> Noise texture with turbulence] |
| 1934 | + [Listing [noise-tex-3]: <kbd>[texture.h]</kbd> Noise texture with marbled texture] |
1866 | 1935 |
|
1867 | 1936 | Which yields:
|
1868 | 1937 |
|
1869 |
| -  |
| 1938 | +  |
1870 | 1939 |
|
1871 | 1940 | </div>
|
1872 | 1941 |
|
|
1904 | 1973 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
|
1905 | 1974 | #include "rtweekend.h"
|
1906 | 1975 | #include "rtw_stb_image.h"
|
| 1976 | + #include "perlin.h" |
1907 | 1977 |
|
1908 | 1978 | #include <iostream>
|
1909 | 1979 |
|
| 1980 | + ... |
| 1981 | + |
1910 | 1982 | class image_texture : public texture {
|
1911 | 1983 | public:
|
1912 | 1984 | const static int bytes_per_pixel = 3;
|
|
1965 | 2037 |
|
1966 | 2038 | <div class='together'>
|
1967 | 2039 | The representation of a packed array in that order is pretty standard. Thankfully, the [stb_image][]
|
1968 |
| -package makes that super simple -- just include the header `rtw_stb_image.h` (found in the project |
1969 |
| -source code at `src/common/rtw_stb_image.h`) in `main.h`: |
| 2040 | +package makes that super simple -- just write a header called `rtw_stb_image.h` that also deals with |
| 2041 | +some compiler warnings: |
1970 | 2042 |
|
1971 | 2043 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
|
1972 |
| - #include "rtw_stb_image.h" |
| 2044 | + #ifndef RTWEEKEND_STB_IMAGE_H |
| 2045 | + #define RTWEEKEND_STB_IMAGE_H |
| 2046 | + |
| 2047 | + // Disable pedantic warnings for this external library. |
| 2048 | + #ifdef _MSC_VER |
| 2049 | + // Microsoft Visual C++ Compiler |
| 2050 | + #pragma warning (push, 0) |
| 2051 | + #endif |
| 2052 | + |
| 2053 | + #define STB_IMAGE_IMPLEMENTATION |
| 2054 | + #include "external/stb_image.h" |
| 2055 | + |
| 2056 | + // Restore warning levels. |
| 2057 | + #ifdef _MSC_VER |
| 2058 | + // Microsoft Visual C++ Compiler |
| 2059 | + #pragma warning (pop) |
| 2060 | + #endif |
| 2061 | + |
| 2062 | + #endif |
1973 | 2063 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
1974 |
| - [Listing [incl-stb-img]: Including the STB image package] |
| 2064 | + [Listing [rtw-stb-image]: <kbd>[rtw_stb_image.h]</kbd> Include the stb_image package] |
| 2065 | + |
| 2066 | +The above assumes that you have copied the `stb_image.h` into a folder called `export`. Adjust as per |
| 2067 | +your directory structure. |
1975 | 2068 | </div>
|
1976 | 2069 |
|
1977 | 2070 |
|
|
2003 | 2096 | to the lambertian material, and lambertian doesn’t need to be aware of it.
|
2004 | 2097 |
|
2005 | 2098 | <div class='together'>
|
2006 |
| -To test this, assign it to a sphere, and then temporarily cripple the `ray_color()` function in main |
2007 |
| -to just return attenuation. You should get something like: |
| 2099 | +To test this, throw it into main: |
| 2100 | + |
| 2101 | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ |
| 2102 | + int main() { |
| 2103 | + ... |
| 2104 | + switch (0) { |
| 2105 | + ... |
| 2106 | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ delete |
| 2107 | + default: |
| 2108 | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ |
| 2109 | + case 3: |
| 2110 | + ... |
| 2111 | + |
| 2112 | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight |
| 2113 | + default: |
| 2114 | + case 4: |
| 2115 | + world = earth(); |
| 2116 | + background = color(0.70, 0.80, 1.00); |
| 2117 | + lookfrom = point3(13,2,3); |
| 2118 | + lookat = point3(0,0,0); |
| 2119 | + vfov = 20.0; |
| 2120 | + break; |
| 2121 | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ |
| 2122 | + } |
| 2123 | + ... |
| 2124 | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 2125 | + [Listing [scene-perlin-view]: <kbd>[main.cc]</kbd> Viewing parameters] |
| 2126 | + |
| 2127 | +If the photo comes back with a large cyan sphere in the middle, then stb_image failed to find your |
| 2128 | +Earth map photo. The program will look for the file in the same directory as the executable. Make |
| 2129 | +sure to copy the Earth into your build directory, or rewrite `earth()` to point somewhere else. |
2008 | 2130 |
|
2009 |
| -  |
| 2131 | +  |
2010 | 2132 |
|
2011 | 2133 | </div>
|
2012 | 2134 |
|
|
0 commit comments