int ImfHeaderSetBox2fAttribute (ImfHeader *hdr, const char name[], float xMin, float yMin, float xMax, float yMax) { try { Box2f box (V2f (xMin, yMin), V2f (xMax, yMax)); if (header(hdr)->find(name) == header(hdr)->end()) { header(hdr)->insert (name, Imf::Box2fAttribute (box)); } else { header(hdr)->typedAttribute<Imf::Box2fAttribute>(name).value() = box; } return 1; } catch (const std::exception &e) { setErrorMessage (e); return 0; } }
void ImfHeaderSetDataWindow (ImfHeader *hdr, int xMin, int yMin, int xMax, int yMax) { header(hdr)->dataWindow() = Box2i (V2i (xMin, yMin), V2i (xMax, yMax)); }
VonMisesFischerApprox::VonMisesFischerApprox(const float* data, int length): kappas(), mus(), radiosities() { int nLobes = (length-1)/7; kappas.resize(nLobes,0.0f); mus.resize(nLobes,V3f(0,0,0)); radiosities.resize(nLobes,C3f(0,0,0)); for (int i=0; i < nLobes; i++) { kappas[i] = data[i*7+1]; mus[i] = V3f(data[(i*7+2)],data[(i*7+3)],data[(i*7+4)]); radiosities[i] = C3f(data[(i*7+5)],data[(i*7+6)],data[(i*7+7)]); } }
PhongModelApprox::PhongModelApprox(const float* data, int length): lobeDirs(), lobeCols() { int nLobes = (length-5)/6; phong = (int) data[1]; N = V3f(data[2],data[3],data[4]); lobeDirs.resize(nLobes,V3f(0,0,0)); lobeCols.resize(nLobes,C3f(0,0,0)); for (int i=0; i < nLobes; i++) { lobeDirs[i] = V3f(data[(i*6+5)],data[(i*6+6)],data[(i*6+7)]); lobeCols[i] = C3f(data[(i*6+8)],data[(i*6+9)],data[(i*6+10)]); } }
float Gamma::operator() (half h) { // // Defog // float x = max (0.f, (h - d)); // // Exposure // x *= m; // // Knee // if (x > kl) x = kl + knee (x - kl, f); // // Gamma // x = Imath::Math<float>::pow (x, g); // // Scale and clamp // return clamp (x * s, 0.f, 255.f); }
Header::Header (int width, int height, float pixelAspectRatio, const V2f &screenWindowCenter, float screenWindowWidth, LineOrder lineOrder, Compression compression) : _map() { staticInitialize(); Box2i displayWindow (V2i (0, 0), V2i (width - 1, height - 1)); initialize (*this, displayWindow, displayWindow, pixelAspectRatio, screenWindowCenter, screenWindowWidth, lineOrder, compression); }
void VonMisesFischerApprox::approximate(const Hemisphere& hemi) { float kappa = hemi.getPhong(); V3f N = hemi.getNormal(); V3f* directions = hemi.getLobeDirections(); C3f* hemiRads = hemi.getLobeRadiosities(); for (int i=0; i <mus.size(); i++) { if (i >= hemi.getNLobes()) { float nan = std::numeric_limits<float>::quiet_NaN(); mus[i] = V3f(nan,nan,nan); } else { V3f L = directions[i]; V3f R = -L - 2 * (dot(-L, N)) * N; mus[i] = R; radiosities[i] = hemiRads[i]*dot(L,N); kappas[i] = kappa; } } }
void PhongModelApprox::approximate(const Hemisphere& hemi) { N = hemi.getNormal(); phong = hemi.getPhong(); V3f* directions = hemi.getLobeDirections(); C3f* radiosities = hemi.getLobeRadiosities(); for (int i=0; i <lobeDirs.size(); i++) { if (i >= hemi.getNLobes()) { float nan = std::numeric_limits<float>::quiet_NaN(); lobeDirs[i] = V3f(nan,nan,nan); } else { V3f L = directions[i]; L = L/L.length(); V3f R = -L - 2 * (dot(-L, N)) * N; lobeDirs[i] = R; lobeCols[i] = radiosities[i]*dot(N,L); } } }
VonMisesFischerApprox::VonMisesFischerApprox(int nLobes) : kappas(nLobes,0), mus(nLobes,V3f(0,0,0)), radiosities(nLobes,C3f(0,0,0)) { }
PhongModelApprox::PhongModelApprox(int nLobes) : lobeDirs(nLobes,V3f(0,0,0)), lobeCols(nLobes,C3f(0,0,0)) { }
static void renderNode(IntegratorT& integrator, V3f P, V3f N, float cosConeAngle, float sinConeAngle, float maxSolidAngle, int dataSize, const DiffusePointOctree::Node* node) { // This is an iterative traversal of the point hierarchy, since it's // slightly faster than a recursive traversal. // // The max required size for the explicit stack should be < 200, since // tree depth shouldn't be > 24, and we have a max of 8 children per node. const DiffusePointOctree::Node* nodeStack[200]; nodeStack[0] = node; int stackSize = 1; while(stackSize > 0) { node = nodeStack[--stackSize]; { // Examine node bound and cull if possible // TODO: Reinvestigate using (node->aggP - P) with spherical harmonics V3f c = node->center - P; if(sphereOutsideCone(c, c.length2(), node->boundRadius, N, cosConeAngle, sinConeAngle)) continue; } float r = node->aggR; V3f p = node->aggP - P; float plen2 = p.length2(); // Examine solid angle of interior node bounding sphere to see whether we // can render it directly or not. // // TODO: Would be nice to use dot(node->aggN, p.normalized()) in the solid // angle estimation. However, we get bad artifacts if we do this naively. // Perhaps with spherical harmoics it'll be better. float solidAngle = M_PI*r*r / plen2; if(solidAngle < maxSolidAngle) { integrator.setPointData(reinterpret_cast<const float*>(&node->aggCol)); renderDisk(integrator, N, p, node->aggN, r, cosConeAngle, sinConeAngle); } else { // If we get here, the solid angle of the current node was too large // so we must consider the children of the node. // // The render order is sorted so that points are rendered front to // back. This greatly improves the correctness of the hider. // // FIXME: The sorting procedure gets things wrong sometimes! The // problem is that points may stick outside the bounds of their octree // nodes. Probably we need to record all the points, sort, and // finally render them to get this right. if(node->npoints != 0) { // Leaf node: simply render each child point. std::pair<float, int> childOrder[8]; // INDIRECT assert(node->npoints <= 8); for(int i = 0; i < node->npoints; ++i) { const float* data = &node->data[i*dataSize]; V3f p = V3f(data[0], data[1], data[2]) - P; childOrder[i].first = p.length2(); childOrder[i].second = i; } std::sort(childOrder, childOrder + node->npoints); for(int i = 0; i < node->npoints; ++i) { const float* data = &node->data[childOrder[i].second*dataSize]; V3f p = V3f(data[0], data[1], data[2]) - P; V3f n = V3f(data[3], data[4], data[5]); float r = data[6]; integrator.setPointData(data+7); renderDisk(integrator, N, p, n, r, cosConeAngle, sinConeAngle); } continue; } else { // Interior node: render children. std::pair<float, const DiffusePointOctree::Node*> children[8]; int nchildren = 0; for(int i = 0; i < 8; ++i) { DiffusePointOctree::Node* child = node->children[i]; if(!child) continue; children[nchildren].first = (child->center - P).length2(); children[nchildren].second = child; ++nchildren; } std::sort(children, children + nchildren); // Interior node: render each non-null child. Nodes we want to // render first must go onto the stack last. for(int i = nchildren-1; i >= 0; --i) nodeStack[stackSize++] = children[i].second; } } } }
void ImfHeaderSetScreenWindowCenter (ImfHeader *hdr, float x, float y) { header(hdr)->screenWindowCenter() = V2f (x, y); }