// Copyright Contributors to the Open Shading Language project. // SPDX-License-Identifier: BSD-3-Clause // https://github.com/AcademySoftwareFoundation/OpenShadingLanguage #ifndef OSLUTIL_H #define OSLUTIL_H // Return wireframe opacity factor [0, 1] given a geometry type in // ("triangles", "polygons" or "patches"), and a line_width in raster // or world space depending on the last (raster) boolean argument. // float wireframe(string edge_type, float line_width, int raster) { // ray differentials are so big in diffuse context that this function would always return "wire" if (raytype("path:diffuse")) return 0.0; int np = 0; point p[64]; float pixelWidth = 1; if (edge_type == "triangles") { np = 3; if (!getattribute("geom:trianglevertices", p)) return 0.0; } else if (edge_type == "polygons" || edge_type == "patches") { getattribute("geom:numpolyvertices", np); if (np < 3 || !getattribute("geom:polyvertices", p)) return 0.0; } if (raster) { // Project the derivatives of P to the viewing plane defined // by I so we have a measure of how big is a pixel at this point float pixelWidthX = length(Dx(P) - dot(Dx(P), I) * I); float pixelWidthY = length(Dy(P) - dot(Dy(P), I) * I); // Take the average of both axis' length pixelWidth = (pixelWidthX + pixelWidthY) / 2; } // Use half the width as the neighbor face will render the // other half. And take the square for fast comparison pixelWidth *= 0.5 * line_width; pixelWidth *= pixelWidth; for (int i = 0; i < np; i++) { int i2 = i ? i - 1 : np - 1; vector dir = P - p[i]; vector edge = p[i] - p[i2]; vector crs = cross(edge, dir); // At this point dot(crs, crs) / dot(edge, edge) is // the square of area / length(edge) == square of the // distance to the edge. if (dot(crs, crs) < (dot(edge, edge) * pixelWidth)) return 1; } return 0; } float wireframe(string edge_type, float line_width) { return wireframe(edge_type, line_width, 1); } float wireframe(string edge_type) { return wireframe(edge_type, 1.0, 1); } float wireframe() { return wireframe("polygons", 1.0, 1); } float draw_string(string str, float s, float t, int wrap_s, int wrap_t, int jitter) { // Glyphs from http://font.gohu.org/ (8x14 version, most common ascii characters only) int glyph_pixel(int c_, int x_, int y) { int c = c_ - 33; // nudge to origin int x = x_ - 1; if (c < 0 || x < 0 || y < 0 ) return 0; if (c > 93 || x > 6 || y > 13) return 0; int i = 98 * c + 7 * y + x; return ((getchar("0@P01248@00120000P49B0000000000000:DXlW2UoDX@10008@h;IR4n@R000015A000000000000000000000000h?00" "04@010000000000000000l0bGX@aL10000124XcX@Q25j300000000?Q248@8?000008@Pl5:DX@aL10" "000000`CX@o24`70000`AP01N48@P0100000000l5:DX@aL12T70124XcX@Q25:40000@P0P348@P01>" "00000240HP01248@P0a101248@T47B4940000HP01248@P01L00000000oBVS248@P000000000l48P7" "@Pn0000048@`31248@030000000P@Q25:DP0124`1001248@P01248@P0007@P01" "24`@P01R30000000S9S10000000", i / 6) - 48) >> (i % 6)) & 1; } int modp(int a, int b) { int x = a % b; return x < 0 ? x + b : x; } int len = strlen(str); int jit = jitter ? hash(str) : 0; int pix_w = len * 8; int pix_h = 14; int x = int(floor(s)); int y = int(floor(t)); if (wrap_s) x = modp(x + ( jitter & 15), pix_w + pix_h); if (wrap_t) y = modp(y + ((jitter >> 16) & 15), pix_h + pix_h); return float(glyph_pixel(getchar(str, x / 8), x - (x / 8) * 8, y)); } #endif /* OSLUTIL_H */