Ejemplo n.º 1
0
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)]);
	}
}
Ejemplo n.º 2
0
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)]);
	}
}
Ejemplo n.º 3
0
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;
		}
	}
}
Ejemplo n.º 4
0
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);
		}
	}
}
Ejemplo n.º 5
0
VonMisesFischerApprox::VonMisesFischerApprox(int nLobes) :
		kappas(nLobes,0), mus(nLobes,V3f(0,0,0)), radiosities(nLobes,C3f(0,0,0))  {

}
Ejemplo n.º 6
0
PhongModelApprox::PhongModelApprox(int nLobes) :
		lobeDirs(nLobes,V3f(0,0,0)), lobeCols(nLobes,C3f(0,0,0))  {
}
Ejemplo n.º 7
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;
            }
        }
    }
}