CoefficientSpectrum* ArealightTracer::traceRay_r( const Ray& ray, int bounceNum) {

    if( ray.GetStart().x > 9000 ) {
        //std::cout << "Using yellow" << std::endl;
        return new RGBSpectrum( *SampledSpectrum::IllumYellow );
    }
    Intersection* inter = new Intersection();
    unsigned long materialIndex = closestIntersect( ray, inter );

    if( hitSomething( inter ) ) {
        CoefficientSpectrum* lightColor;
        CoefficientSpectrum* materialColor;
        CoefficientSpectrum* diffuseColor;
        CoefficientSpectrum* specularColor;
        Material mat = scene->renderObjects[materialIndex]->mat;
        if( useRGB ) {
            lightColor = new RGBSpectrum(
                *scene->lights[0]->mat.GetColorAt(inter));
            materialColor = new RGBSpectrum(*mat.GetColorAt(inter));
            specularColor = new RGBSpectrum( *scene->lights[0]->mat.GetColorAt(inter) );
            diffuseColor = new RGBSpectrum( *scene->lights[0]->mat.GetColorAt(inter) );
        } else { //use SampledSpectrum
            lightColor = new SampledSpectrum(
                *scene->lights[0]->mat.GetColorAt(inter));
            materialColor = new SampledSpectrum(*mat.GetColorAt(inter));
            specularColor = new SampledSpectrum( *scene->lights[0]->mat.GetColorAt(inter) );
            diffuseColor = new SampledSpectrum( *scene->lights[0]->mat.GetColorAt(inter) );
        }

        glm::mat4 lightMatrix = scene->lights[0]->prim->transform;
        glm::vec3 lightPos = extractTranslation(lightMatrix);
        glm::vec3 lightVector = calcLightVector(inter->hitPt, lightPos);

        //sfDir is the direction of the shadow feeler.
        //glm::vec3 sfDir = glm::normalize(lightPos - inter->hitPt);
        //Ray sfRay(inter->hitPt + 0.01f*sfDir, sfDir);
        //float lightDistance = sfRay.ParamAtPt( lightPos );
        //Intersection* sfInter = new Intersection();
        //unsigned long obstructIndex = closestIntersect( sfRay, sfInter );
        float diffuseTerm = 0.0f;
        float specularTerm = 0.0f;
        //Material obstructMat = scene->renderObjects[obstructIndex]->mat;
        //if( hitSomething( sfInter ) && obstructMat.transparency < EPSILON
        //&& ( sfInter->tParam < lightDistance ) ) { //light obstructed
        //diffuseTerm = 0.1f;
        //specularTerm = 0.0f;
        //} else {
        //diffuseTerm = calcDiffuseTerm(lightVector, inter);
        //specularTerm = calcSpecularTerm(inter->hitPt,
        //scene->cam.m_eye, mat.specPow, inter);
        //}

        float lightContrib = sampleAreaLight( inter );
        //float lightContrib = 1;
        diffuseTerm = calcDiffuseTerm(lightVector, inter) * lightContrib;
        specularTerm = calcSpecularTerm(inter->hitPt,
                                        scene->cam.m_eye, mat.specPow, inter) * lightContrib;

        //HACK: from before, specularColor and diffuseColor all start out
        //as lightColor

        diffuseColor->TimesScalar( DIFFUSE_CONST * diffuseTerm );
        diffuseColor->Convolve( *materialColor );
        specularColor->TimesScalar( SPECULAR_CONST * specularTerm );
        //HACK BELOW: MODIFY specular color, then SHALLOW COPY to final color!
        specularColor->AddHeapCS(diffuseColor);
        CoefficientSpectrum* finalColor = specularColor;

        //materialColor->TimesScalar( diffuseTerm );

        if ( mat.transparency > 0.0f && bounceNum < BOUNCE_LIMIT ) {
            Ray refrRay = ray.GetRefracted( inter->normal, inter->hitPt,
                                            mat.refractiveIndex );
            //refrRay.isRefracted = true;
            CoefficientSpectrum* refrColor = traceRay_r( refrRay, bounceNum + 1);

            finalColor->TimesScalar(1 - mat.transparency);
            refrColor->TimesScalar(mat.transparency);
            finalColor->AddHeapCS(refrColor);
        }

        if( mat.reflectivity > 0.0f && bounceNum < BOUNCE_LIMIT) {
            Ray reflRay = ray.GetReflected( inter->normal, inter->hitPt);
            CoefficientSpectrum* reflColor = traceRay_r( reflRay, bounceNum + 1);

            finalColor->TimesScalar(1 - mat.reflectivity);
            reflColor->TimesScalar(mat.reflectivity);
            finalColor->AddHeapCS(reflColor);
        }

        delete lightColor;
        delete materialColor;
        delete diffuseColor;
        delete inter;
        return finalColor;
    } else { //return background color
        if( useRGB ) {
            delete inter;
            return new RGBSpectrum( *SampledSpectrum::IllumWhite );
        } else {
            delete inter;
            return new SampledSpectrum( *SampledSpectrum::IllumWhite );
        }
    }
}