/* * dumpgrids.c * * Copyright (C) 2000, Matt Pharr * * This software is placed in the public domain and is provided as is * without express or implied warranty. * * DSO shadeop for RenderMan. When surface shaders have the following * lines added to them and are recompiled, they will dump out the * micropolygons that prman makes when rendering the scene into a file * named "grids.out". * * uniform float i = 0; * gridStart(i); * processGrid(P, Ci, u, v); * gridEnd(i); * * In this file, for each grid, there will be a line like "g 2 4", which * says that a 2x4 micropolygon grid was generated. Then were will be * a number of lines like "mp xxx yyy zzz ..." with 12 floats, giving the * four vertices of the mp. * * See http://www.pixar.com/products/rendermandocs/toolkit/Toolkit/dsoshadeops.html * for details about how to use DSO shadeops in prman. * * Enhancements to do/lurking bugs: * - Dumping color and opacity would be useful. * - Dumping P+dPtime to get motion information. * - I believe that this won't work correctly in the presence of a multithreaded * renderer (e.g. netrender) due to assumptions that it won't be called * re-entrantly. This should probably be fixed; the initDump() function * should be called once for each thread--we can just store the p[], etc * arrays in a structure that initdata points to. Disk I/O is still an issue.. * - This doesn't work in renderers like BMRT that don't shade SIMD-style. */ #include #include #include SHADEOP_TABLE(gridStart) = { { "void gridStart (float)", "", "" }, { "" } }; SHADEOP_TABLE(processGrid) = { { "void processGrid (point, color, float, float)", "", "" }, { "" } }; SHADEOP_TABLE(gridEnd) = { { "void gridEnd (float)", "initDump", "dumpCleanup" }, { "" } }; /* A safe(?) upper bound on the total number of vertices in a grid--i.e. Options "limits" "gridsize" [] */ #define MAX_SIZE 8192 static int pcPos = 0, uPos = 0, vPos = 0; static float u[MAX_SIZE], v[MAX_SIZE], p[MAX_SIZE][3], c[MAX_SIZE][3]; void *initDump(int xx, void *x) { FILE *f = fopen("grids.out", "w"); assert(f); return f; } void dumpCleanup(void *data) { FILE *f = (FILE *)data; fclose(f); } SHADEOP(gridStart) { pcPos = uPos = vPos = 0; return 0; } SHADEOP(processGrid) { float *pp = (float *)argv[1], *cp = (float *)argv[2]; float uv = *(float *)argv[3], vv = *(float *)argv[4]; int i; /* Store all position and color values that we're called with */ assert(argc == 5); for (i = 0; i < 3; ++i) { p[pcPos][i] = pp[i]; c[pcPos][i] = cp[i]; } ++pcPos; assert(pcPos < MAX_SIZE); /* Only store u and v values that we haven't seen before. By counting the number of unique u's and v's, we can infer the grid size. */ for (i = 0; i < uPos; ++i) if (u[i] == uv) break; if (i == uPos) { u[i] = uv; ++uPos; assert(uPos < MAX_SIZE); } for (i = 0; i < vPos; ++i) if (v[i] == vv) break; if (i == vPos) { v[i] = vv; ++vPos; assert(vPos < MAX_SIZE); } return 0; } SHADEOP(gridEnd) { FILE *f = (FILE *)initdata; int i, j; fprintf(f, "g %d %d\n", uPos-1, vPos-1); for (i = 0; i < vPos-1; ++i) for (j = 0; j < uPos-1; ++j) { int v0 = i * uPos + j; int v1 = i * uPos + j + 1; int v2 = (i+1)*uPos + j + 1; int v3 = (i+1)*uPos + j; fprintf(f, "mp %f %f %f %f %f %f %f %f %f %f %f %f\n", p[v0][0], p[v0][1], p[v0][2], p[v1][0], p[v1][1], p[v1][2], p[v2][0], p[v2][1], p[v2][2], p[v3][0], p[v3][1], p[v3][2]); } return 0; }