Beispiel #1
0
void GLShader::bindLights(LightList& lights, Renderer* renderer)
{
    int locOffset = 0;

    if ((mShaderLocs[LIGHT_UBO_INDEX].size() == 0) || lights.isDirty())
    {
        mShaderLocs[LIGHT_UBO_INDEX].resize(lights.getNumUniforms());
        lights.forEachLight([this, renderer, locOffset](Light& light) mutable
        {
            UniformBlock& lightData = light.uniforms().uniforms();

            findUniforms(light, locOffset);
            lightData.bindBuffer(this, renderer, locOffset);
            locOffset += lightData.getNumEntries();
        });
    }
    else
    {
        lights.forEachLight([this, renderer, locOffset](Light& light) mutable
        {
            UniformBlock& lightData = light.uniforms().uniforms();

            lightData.bindBuffer(this, renderer, locOffset);
            locOffset += lightData.getNumEntries();
        });
    }
}
Beispiel #2
0
void updateLights() {

	for(LightList::iterator light = Lights.begin(); light != Lights.end(); light++) {
		if(light->on) {
			if(fabsf(light->orient.Yaw   += (kPi/180.0f) * light->origin.Yaw  ) >= k2Pi) light->orient.Yaw   -= k2Pi;
			if(fabsf(light->orient.Pitch += (kPi/180.0f) * light->origin.Pitch) >= k2Pi) light->orient.Pitch -= k2Pi;
			if(fabsf(light->orient.Roll  += (kPi/180.0f) * light->origin.Roll ) >= k2Pi) light->orient.Roll  -= k2Pi;
		}
	}

}
//------------------------------------------------------------------------------
void SegmentedDynamicLightManager::regenerateActiveLightList(const LightList& i_LightList)
{
	//add the buffers to the segmented lists
	LightList::const_iterator itLight = i_LightList.begin(),
		itLightEnd = i_LightList.end();
	for(;itLight != itLightEnd ; ++itLight)
	{
		const Light* pLight = (*itLight);
		Light::LightTypes type = pLight->getType();
		if (((type == Light::LT_SPOTLIGHT) || (type == Light::LT_POINT)) &&
			(pLight->getAttenuationRange() > 0))
		{
				
			MapLightData::iterator it = mActiveLights.insert(
				MapLightData::value_type(pLight,LightData())).first;
			LightData& lightData = it->second;
				
			calculateLightBounds(pLight, lightData);
		}
	}
}
Beispiel #4
0
void DrawScene()
{
	glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );

	glEnable( GL_LIGHTING );
	glEnable( GL_DEPTH_TEST );

	glPushMatrix();
	Point3 p = camera.pos;
	Point3 t = camera.pos + camera.dir;
	Point3 u = camera.up;
	gluLookAt( p.x, p.y, p.z,  t.x, t.y, t.z,  u.x, u.y, u.z );

	glRotatef( viewAngle1, 1, 0, 0 );
	glRotatef( viewAngle2, 0, 0, 1 );

	if ( lights.size() > 0 ) {
		for ( unsigned int i=0; i<lights.size(); i++ ) {
			lights[i]->SetViewportLight(i);
		}
	} else {
		float white[] = {1,1,1,1};
		float black[] = {0,0,0,0};
		Point4 p(camera.pos, 1);
		glEnable ( GL_LIGHT0 );
		glLightfv( GL_LIGHT0, GL_AMBIENT,  black );
		glLightfv( GL_LIGHT0, GL_DIFFUSE,  white );
		glLightfv( GL_LIGHT0, GL_SPECULAR, white );
		glLightfv( GL_LIGHT0, GL_POSITION, &p.x );
	}

	DrawNode(&rootNode);

	glPopMatrix();

	glDisable( GL_DEPTH_TEST );
	glDisable( GL_LIGHTING );
}
Beispiel #5
0
void setupLights() {
	Obj.ambientIntensity = 1.0f;
	Obj.ambientColor = vec3(0.2,0.2,0.2);
	light3 l;
	l.on = true;
	l.orient = vecMath::Normalize(vec3(1.0f,0.0f,0.2f));
	l.origin = vec3(0.0,1.0,0.0);
	l.color = vec3(1.0,0.0,0.0);
	Lights.push_back(l);
	
	l.on = true;
	l.orient = vecMath::Normalize(vec3(0.0f,1.0f,0.2f));
	l.origin = vec3(0.0,-1.333,0.0);
	l.color = vec3(0.0,1.0,0.0);
	Lights.push_back(l);

	l.on = true;
	l.orient = vecMath::Normalize(vec3(1.0f,1.0f,0.2f));
	l.origin = vec3(1.5,1.5,0.0);
	l.color = vec3(0.0,0.0,1.0);
	Lights.push_back(l);


}
 //-----------------------------------------------------------------------
 void SceneNode::findLights(LightList& destList, Real radius, uint32 lightMask) const
 {
     // No any optimisation here, hope inherits more smart for that.
     //
     // If a scene node is static and lights have moved, light list won't change
     // can't use a simple global boolean flag since this is only called for
     // visible nodes, so temporarily visible nodes will not be updated
     // Since this is only called for visible nodes, skip the check for now
     //
     if (mCreator)
     {
         // Use SceneManager to calculate
         mCreator->_populateLightList(this, radius, destList, lightMask);
     }
     else
     {
         destList.clear();
     }
 }
Beispiel #7
0
void DrawScene()
{
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );
    
    const TextureMap *bgMap = background.GetTexture();
    if ( bgMap ) {
        glDepthMask(GL_FALSE);
        glMatrixMode(GL_PROJECTION);
        glPushMatrix();
        glLoadIdentity();
        glMatrixMode(GL_MODELVIEW);
        Color c = background.GetColor();
        glColor3f(c.r,c.g,c.b);
        if ( bgMap->SetViewportTexture() ) {
            glEnable( GL_TEXTURE_2D );
            glMatrixMode( GL_TEXTURE );
            Matrix3 tm = bgMap->GetInverseTransform();
            Point3 p = tm * bgMap->GetPosition();
            float m[16] = { tm[0],tm[1],tm[2],0, tm[3],tm[4],tm[5],0, tm[6],tm[7],tm[8],0, -p.x,-p.y,-p.z,1 };
            glLoadMatrixf( m );
            glMatrixMode( GL_MODELVIEW );
        } else {
            glDisable( GL_TEXTURE_2D );
        }
        glBegin(GL_QUADS);
        glTexCoord2f(0,1);
        glVertex2f(-1,-1);
        glTexCoord2f(1,1);
        glVertex2f( 1,-1);
        glTexCoord2f(1,0);
        glVertex2f( 1, 1);
        glTexCoord2f(0,0);
        glVertex2f(-1, 1);
        glEnd();
        glMatrixMode(GL_PROJECTION);
        glPopMatrix();
        glMatrixMode(GL_MODELVIEW);
        glDepthMask(GL_TRUE);
        
        glDisable( GL_TEXTURE_2D );
    }
    
    glEnable( GL_LIGHTING );
    glEnable( GL_DEPTH_TEST );
    
    glPushMatrix();
    Point3 p = camera.pos;
    Point3 t = camera.pos + camera.dir*camera.focaldist;
    Point3 u = camera.up;
    if ( camera.dof > 0 ) {
        Point3 v = camera.dir ^ camera.up;
        float r = sqrtf(float(rand())/RAND_MAX)*camera.dof;
        float a = M_PI * 2.0f * float(rand())/RAND_MAX;
        p += r*cosf(a)*v + r*sinf(a)*u;
    }
    gluLookAt( p.x, p.y, p.z,  t.x, t.y, t.z,  u.x, u.y, u.z );
    
    glRotatef( viewAngle1, 1, 0, 0 );
    glRotatef( viewAngle2, 0, 0, 1 );
    
    if ( lights.size() > 0 ) {
        for ( unsigned int i=0; i<lights.size(); i++ ) {
            lights[i]->SetViewportLight(i);
        }
    } else {
        float white[] = {1,1,1,1};
        float black[] = {0,0,0,0};
        Point4 p(camera.pos, 1);
        glEnable ( GL_LIGHT0 );
        glLightfv( GL_LIGHT0, GL_AMBIENT,  black );
        glLightfv( GL_LIGHT0, GL_DIFFUSE,  white );
        glLightfv( GL_LIGHT0, GL_SPECULAR, white );
        glLightfv( GL_LIGHT0, GL_POSITION, &p.x );
    }
    
    DrawNode(&rootNode);
    
    glPopMatrix();
    
    glDisable( GL_DEPTH_TEST );
    glDisable( GL_LIGHTING );
    glDisable( GL_TEXTURE_2D );
}
Beispiel #8
0
Color MtlBlinn::Shade(const Ray &ray, const HitInfo &hInfo, const LightList &lights, int reflection_bounceCount, int gi_bounceCount) const
{
	Color ambientComp, diffuseComp, specularComp, reflectiveComp, refractiveComp, reflectionTotal, refractionTotal, noColor, diffuseReflection;
	diffuseReflection = ambientComp = diffuseComp = specularComp = reflectiveComp = refractiveComp  = noColor = reflectionTotal = refractionTotal = Color(0.0f, 0.0f, 0.0f);
	Color fromReflection = Color(0.0f, 0.0f, 0.0f);
	Color fromRefraction = Color(0.0f, 0.0f, 0.0f);
	Point3 viewDirection = -ray.dir;
	float schlicksConstant, ratioOfRefraction;
	Color kd = diffuse.Sample(hInfo.uvw);

	int hitside = HIT_FRONT;
	float n1 = 1;
	float n2 = ior;

	for (int i = 0; i < lights.size(); i++)
	{
		Color lightColor = lights[i]->Illuminate(hInfo.p, hInfo.N);
		/*if (lightColor != noColor)
		{*/
			if (lights[i]->IsAmbient())
			{
				ambientComp = ambientComponent(lights[i], lightColor, hInfo, diffuse.Sample(hInfo.uvw));
			}
			else
			{
				//lightColor.ClampMinMax();
				Point3 rayDir = ray.dir;
				globalPhotonMap.EstimateIrradiance<50>(lightColor, rayDir, 2.0f, hInfo.p, &hInfo.N);
				diffuseComp = diffuseComponent(lights[i], lightColor, hInfo, diffuse.Sample(hInfo.uvw));
				specularComp = specularComponent(lights[i], lightColor, viewDirection, hInfo, specular.Sample(hInfo.uvw), glossiness);
			}
		//}
	}
			/************************Refraction************************************************************/
	if(refraction.Sample(hInfo.uvw) != noColor && reflection_bounceCount > 0)
	{
		Ray refractionRay;
		HitInfo refractionRayHit;
		refractionRayHit.Init();
		refractionRay.p = hInfo.p;
		if (hInfo.front == HIT_FRONT)
		{
			refractionRay.dir = getRefractionVector(viewDirection, getPerturbedNormal(hInfo.N, hInfo.p, refractionGlossiness), n1, n2);
		}
		else
		{
			refractionRay.dir = getRefractionVector(viewDirection, getPerturbedNormal( -hInfo.N, hInfo.p, refractionGlossiness), n2, n1);
		}
				
		if(TraceRay(&rootNode, refractionRay, refractionRayHit, hitside))
		{
			Point3 refractionDir = refractionRay.dir;
			refractiveComp += refractionRayHit.node->GetMaterial()->Shade(refractionRay, refractionRayHit, 
				lights, --reflection_bounceCount);
			refractiveComp *= refraction.Sample(hInfo.uvw);
		}
		else
		{
			refractiveComp =  environment.SampleEnvironment(refractionRay.dir);
		}				
	}


	/********************Schlick's Approximation - Fresnel Reflection***************************/
	schlicksConstant = pow(((n1 - n2) / (n1 + n2)), 2);
	ratioOfRefraction = schlicksConstant + (1 - schlicksConstant) * pow((1 - viewDirection.Dot(hInfo.N)), 5);
	reflectionTotal = ratioOfRefraction*refraction.Sample(hInfo.uvw);
	refractionTotal = (1 - ratioOfRefraction)*refraction.Sample(hInfo.uvw);
	///*******************************************************************************************/
	//refractiv    eComp *= refractionTotal; //It = (1-R) * KT'
	reflectionTotal += reflection.Sample(hInfo.uvw); //Doing outside in case refraction didn't occured at all
	/*********************************************************************************************/

	/**********************Reflection*************************************************************/
	if(reflectionTotal != noColor && reflection_bounceCount > 0)
	{
		Ray reflectionViewVector;
		reflectionViewVector.dir = getReflectionVector(viewDirection, 
			getPerturbedNormal(hInfo.N, hInfo.p, reflectionGlossiness));
		reflectionViewVector.p = hInfo.p;
		HitInfo reflectionRayHit;
		reflectionRayHit.Init();
		//--reflection_bounceCount;
		if (TraceRay(&rootNode, reflectionViewVector, reflectionRayHit, HIT_FRONT))
		{
			fromReflection += reflectionRayHit.node->GetMaterial()->Shade(reflectionViewVector, 
				reflectionRayHit, lights, --reflection_bounceCount);
			reflectiveComp = reflectionTotal * fromReflection;
		}
		else
		{
			reflectiveComp = environment.SampleEnvironment(reflectionViewVector.dir);
		}
	}
	/****************************************************************************************************/
	if(GI_ALGO)
	{
		if (kd != noColor && gi_bounceCount > 0)
		{
			HemiSphereSampler giHemiSampler = HemiSphereSampler(__gi_sampleCount, __gi_sampleCount, 1);
			giHemiSampler.generateSamples();
			Point3 randomDirectionAtHitPoint = Point3(0.0f, 0.0f, 0.0f);
			HitInfo diffuseReflectionHitInfo;
			Ray diffuseReflectionRay;
			for (int i = 0; i < giHemiSampler.getCurrentSampleCount(); ++i)
			{
				randomDirectionAtHitPoint = giHemiSampler.getSample(getRandomNumber(0, giHemiSampler.getCurrentSampleCount())).getOffset();
				diffuseReflectionRay.p = hInfo.p;
				Point3 u = Point3(0.0f, 0.0f, 0.0f);
				Point3 v = Point3(0.0f, 0.0f, 0.0f);
				Point3 w = Point3(0.0f, 0.0f, 0.0f);
				w = hInfo.N;
				getOrthoNormalBasisVector(w, u, v);
				diffuseReflectionRay.dir = randomDirectionAtHitPoint.x * u +
					randomDirectionAtHitPoint.y * v +
					randomDirectionAtHitPoint.z *w;
				diffuseReflectionHitInfo.Init();
				if (TraceRay(&rootNode, diffuseReflectionRay, diffuseReflectionHitInfo, HIT_FRONT))
				{
					diffuseReflection = diffuseReflectionHitInfo.node->GetMaterial()->Shade(diffuseReflectionRay,
						diffuseReflectionHitInfo, lights, 0, gi_bounceCount - 1);					
				}
				else
				{
					diffuseReflection = environment.SampleEnvironment(diffuseReflectionRay.dir);
				}
				giHemiSampler.setSampleColor(i, diffuseReflection);
				giHemiSampler.setIsSampleHit(i, true);
			}

			diffuseReflection = giHemiSampler.getAveragedSampleListColor() * diffuseReflection * kd * M_PI;
		}
	}
	else
	{
		if (kd != noColor && gi_bounceCount > 0)
		{
			HemiSphereSampler giHemiSampler = HemiSphereSampler(__gi_sampleCount, __gi_sampleCount, 1);
			giHemiSampler.generateSamples();
			Point3 randomDirectionAtHitPoint = Point3(0.0f, 0.0f, 0.0f);
			HitInfo diffuseReflectionHitInfo;
			Ray diffuseReflectionRay;
			
			randomDirectionAtHitPoint = giHemiSampler.getSample(getRandomNumber(0, giHemiSampler.getCurrentSampleCount())).getOffset();
			diffuseReflectionRay.p = hInfo.p;
			Point3 u = Point3(0.0f, 0.0f, 0.0f);
			Point3 v = Point3(0.0f, 0.0f, 0.0f);
			Point3 w = Point3(0.0f, 0.0f, 0.0f);
			w = hInfo.N;
			getOrthoNormalBasisVector(w, u, v);
			diffuseReflectionRay.dir = randomDirectionAtHitPoint.x * u +
				randomDirectionAtHitPoint.y * v +
				randomDirectionAtHitPoint.z *w;
			
			diffuseReflectionHitInfo.Init();
			if (TraceRay(&rootNode, diffuseReflectionRay, diffuseReflectionHitInfo, HIT_FRONT))
			{
				diffuseReflection += diffuseReflectionHitInfo.node->GetMaterial()->Shade(diffuseReflectionRay,
					diffuseReflectionHitInfo, lights, 0, gi_bounceCount - 1);	
				diffuseReflection = diffuseReflection * kd;
			}
			else
			{
				diffuseReflection = environment.SampleEnvironment(diffuseReflectionRay.dir);
			}			
		}
	}
			
	return (ambientComp + diffuseComp + specularComp+ reflectiveComp + refractiveComp + diffuseReflection);
}
Beispiel #9
0
Color MtlBlinn::Shade(const Cone &ray, const HitInfo &hInfo, const LightList &lights, int bounceCount) const{
    float bias = BIAS_SHADING;
    Color shade;
    Color rShade = Color(0,0,0);
    Color tShade = Color(0,0,0);
    const Material *mat;
    mat = hInfo.node->GetMaterial();
    const MtlBlinn* mb =static_cast<const MtlBlinn*>(mat);
//    cout<<"HInfo front: "<<hInfo.front<<endl;
    /* local copy */
    Point3 P;
    P.Set(hInfo.p.x,hInfo.p.y,hInfo.p.z);
    Cone iRay = ray;
    
    Color ambInt = mb->diffuse.Sample(hInfo.uvw, hInfo.duvw);
    Color allOther = Color(0,0,0);
    Color diffuse = mb->diffuse.Sample(hInfo.uvw, hInfo.duvw);
    Color ambComponent = Color(0,0,0);
    Point3 newN = hInfo.N;
    
    
    for ( unsigned int i=0; i<lights.size(); i++ ) {
        if(lights[i]->IsAmbient()){
//            cout<<"ambient "<<endl;
            Color intensity = lights[i]->Illuminate(hInfo.p);
            ambComponent += (ambInt * intensity);
            continue;
        }
        else{
//            cout<<"other lighting  "<<endl;
            Point3 L = -lights[i]->Direction(P);
            L.Normalize();
            
            Point3 V = ray.p - P;
            V.Normalize();
            
            Point3 LplusV = L + V;
            Point3 H = (L+V)/LplusV.Length();
            H.Normalize();
            
            float alpha = mb->glossiness;
//            Point3 N = hInfo.N;
            Point3 N = newN;
            float S = H.Dot(N);
            S = pow(S,alpha);
            float costheta = L.Dot(N)/(L.Length() * N.Length());
            Color intensity = lights[i]->Illuminate(P);
//            cout<<"costheta "<<endl;
            allOther += intensity * (costheta>0?costheta:0) * (diffuse + S * (mb->specular.Sample(hInfo.uvw, hInfo.duvw))) ;
        }
        /* finally add inta*cola + intall*costheta*(cold + s* colS)*/
        shade = ambComponent  + allOther;
    }
    
    /* Calculate refraction */
    if(refraction.GetColor().r>0 && bounceCount>0){
        //compute new jittered normal
        float gloss = refractionGlossiness;
        if(gloss){
            float random = rand()/(float)RAND_MAX;
            float rRadius = sqrtf(random) * gloss;
            random = rand()/(float)RAND_MAX;
            float rAngle =  random * 2.0 * M_PI;
            float x = rRadius * cos(rAngle);
            float y = rRadius * sin(rAngle);
            Point3 xAxis(1,0,0), yAxis(0,1,0), v1, v2, normalDir;
            normalDir = hInfo.N;
            //    normalDir.Normalize();
            if(normalDir.Dot(xAxis) > 0.7)  v1 = normalDir.Cross(yAxis);
            else v1 = normalDir.Cross(xAxis);
            v2 = v1.Cross(normalDir);
            v1.Normalize(); v2.Normalize();
            v1 *= x;
            v2 *= y;
            
            newN = hInfo.N + v1.Length() + v2.Length();
            newN.Normalize();
        }
        else{
            newN = hInfo.N;
        }
        //-------------------------------------
        
        Color reflShade = Color(0,0,0);
        float R0, Refl = 0.0f, Trans = 0.0f;
        HitInfo temp;
        temp.Init();
        
//        Point3 N = hInfo.N;
        Point3 N = newN;
//        Point3 V = Point3(iRay.p.x -  hInfo.p.x, iRay.p.y - hInfo.p.y, iRay.p.z - hInfo.p.z);
        Point3 V = Point3(hInfo.p.x - iRay.p.x, hInfo.p.y - iRay.p.y, hInfo.p.z - iRay.p.z);
        V.Normalize();
        float n1 = 1, n2 = 1;
        if(hInfo.front){ /* Hitting from outside */
//            temp.front = false;
            n2 = ior;
//            cout<<"outside "<<endl;
        }
        else if(!hInfo.front){ /* Transmission from the inside */
//            temp.front = true;
            n1 = ior;
//            cout<<"intside... "<<endl;
//            N = -hInfo.N;
            N *= -1;
        }
        float ratio_n = n1 / n2;
        
        float costheta_v = -V.Dot(N);        /* refer: http://graphics.stanford.edu/courses/cs148-10-summer/docs/2006--degreve--reflection_refraction.pdf */

        float sin2theta_t = ratio_n * ratio_n * (1 - costheta_v * costheta_v);
        Point3 T =   ratio_n * V + (ratio_n * costheta_v - sqrtf(1 - sin2theta_t)) * N ;
//        cout<<ratio_n<<" "<<"cos_v "<<costheta_v<<" sin2theta_t "<<sin2theta_t<<endl;
        Cone tRay = Cone(hInfo.p,T);
        
        //tRay.dir.Normalize();
        tRay.p.x = tRay.p.x + bias *tRay.dir.x; /* add bias */
        tRay.p.y = tRay.p.y + bias *tRay.dir.y;
        tRay.p.z = tRay.p.z + bias *tRay.dir.z;
//        cout<<"B temp front: "<< temp.front<<endl;
        temp.timeInstance = hInfo.timeInstance;
        if(sin2theta_t <= 1){
            if(RayTrace_2(tRay, temp)){ /* ray tracing after refraction */
//                bounceCount--;
                tShade  =  temp.node->GetMaterial()->Shade(tRay,temp,lights,bounceCount);
            }
            else{ /* no hit after refraction */
                tShade = environment.SampleEnvironment(tRay.dir);
                
            }
            /* Calculate Schlick's approximation */
            
            R0 = (n1 - n2)/(n1 + n2);
            R0 *= R0;
            double  X = 0.0;
            //                if(n1 > n2){
            //                    X = 1.0 - sqrtf(1.0 - sin2theta_t);
            //                }
            //                else{ X = 1.0 - costheta_v; }
            X = 1.0 - costheta_v;
            Refl = R0 + (1.0 - R0) *  X * X * X * X * X;
            Trans = 1.0 - Refl;
            
            tShade.r *= exp(-absorption.r * temp.z);
            tShade.g *= exp(-absorption.g * temp.z);
            tShade.b *= exp(-absorption.b * temp.z);
        }
        else {/* Total internal reflection */
            Refl = 1.0f;
        }
        
            
        
        
        /* Calculate reflection due to reflectance */
        if(bounceCount >0){
//            N = hInfo.N;
            N = newN;
            Point3 V = Point3(iRay.p.x -  P.x, iRay.p.y - P.y, iRay.p.z - P.z);
            //V.Normalize();
            Point3 VR = 2 * V.Dot(N) * N - V;
            //VR.Normalize();
            Cone rRay = Cone(P + BIAS_SHADING * VR, VR);
            rRay.dir.Normalize();
            HitInfo temp1;
            temp1.Init();
            temp.timeInstance = hInfo.timeInstance;
            if(rootNode.GetNumChild()>0){
                if(RayTrace_2(rRay, temp1)){
                    bounceCount --;
                    reflShade = temp1.node->GetMaterial()->Shade(rRay, temp1, lights, bounceCount);
                }
                else{
                    reflShade = environment.SampleEnvironment(rRay.dir);
//                    reflShade = Color(1,100,1);
                }
            }
        }
        
//        cout<<"Refl: "<<Refl<<"Trans "<<Trans<<endl;
        tShade = refraction.GetColor().r * (Trans * tShade + Refl * reflShade);
        
        
    }

    /* calculate reflection*/
    if(reflection.GetColor().r>0 && bounceCount > 0){
        //compute new jittered normal
        float gloss = reflectionGlossiness;
        if(gloss){
            float random = rand()/(float)RAND_MAX;
            float rRadius = sqrtf(random) * gloss;
            random = rand()/(float)RAND_MAX;
            float rAngle =  random * 2.0 * M_PI;
            float x = rRadius * cos(rAngle);
            float y = rRadius * sin(rAngle);
            Point3 xAxis(1,0,0), yAxis(0,1,0), v1, v2, normalDir;
            normalDir = hInfo.N;
            //    normalDir.Normalize();
            if(normalDir.Dot(xAxis) > 0.7)  v1 = normalDir.Cross(yAxis);
            else v1 = normalDir.Cross(xAxis);
            v2 = v1.Cross(normalDir);
            v1.Normalize(); v2.Normalize();
            v1 *= x;
            v2 *= y;
            
            newN = hInfo.N + v1+ v2;
            newN.Normalize();
        }
        else{
            newN = hInfo.N;
        }
        //-------------------------------------
        
        Point3 N = newN;//hInfo.N;
        Point3 V = Point3(iRay.p.x -  P.x, iRay.p.y - P.y, iRay.p.z - P.z);
       // V.Normalize();
        Point3 VR = 2 * V.Dot(N) * N - V;
        Cone rRay = Cone(P + BIAS_SHADING * VR, VR);
        rRay.dir.Normalize();
        HitInfo temp;
        temp.Init();
        temp.timeInstance=hInfo.timeInstance;
        if(rootNode.GetNumChild()>0){
            if(RayTrace_2(rRay, temp)){
                bounceCount--;
                rShade = reflection.GetColor().r * temp.node->GetMaterial()->Shade(rRay, temp, lights, bounceCount);
            }
            else{
                rShade =  reflection.GetColor().r *environment.SampleEnvironment(rRay.dir);
//                rShade = Color(1,111,1);
            }
        }
    }
    
  
    
    /* Add shade with reflected and refracted colors */
    shade += (rShade + tShade);
    return shade;
};
Beispiel #10
0
Color MtlBlinn::Shade(const Ray &ray, const HitInfo &hInfo, const LightList &lights, int bounceCount) const{
    float bias = BIAS_SHADING;
    Color shade;
    Color rShade = Color(0,0,0);
    Color tShade = Color(0,0,0);
    const Material *mat;
    mat = hInfo.node->GetMaterial();
    const MtlBlinn* mb =static_cast<const MtlBlinn*>(mat);
//    cout<<"HInfo front: "<<hInfo.front<<endl;
    /* local copy */
    Point3 P;
    P.Set(hInfo.p.x,hInfo.p.y,hInfo.p.z);
    Ray iRay = ray;
    
    Color ambInt = mb->diffuse;
    Color allOther = Color(0,0,0);
    Color diffuse = mb->diffuse;;
    Color ambComponent = Color(0,0,0);
    
    for ( unsigned int i=0; i<lights.size(); i++ ) {
        if(lights[i]->IsAmbient()){
//            cout<<"ambient "<<endl;
            Color intensity = lights[i]->Illuminate(hInfo.p);
            ambComponent += (ambInt * intensity);
            continue;
        }
        else{
//            cout<<"other lighting  "<<endl;
            Point3 L = -lights[i]->Direction(P);
            L.Normalize();
            
            Point3 V = ray.p - P;
            V.Normalize();
            
            Point3 LplusV = L + V;
            Point3 H = (L+V)/LplusV.Length();
            H.Normalize();
            
            float alpha = mb->glossiness;
            Point3 N = hInfo.N;
            float S = H.Dot(N);
            S = pow(S,alpha);
            float costheta = L.Dot(N)/(L.Length() * N.Length());
            Color intensity = lights[i]->Illuminate(P);
//            cout<<"costheta "<<endl;
            allOther += intensity * (costheta>0?costheta:0) * (diffuse + S * (mb->specular)) ;
        }
        /* finally add inta*cola + intall*costheta*(cold + s* colS)*/
        shade = ambComponent  + allOther;
    }
    
    /* Calculate refraction */
    if(refraction.Grey()>0 && bounceCount>0){
        Color reflShade = Color(0,0,0);
        float R0, Refl = 0.0f, Trans = 0.0f;
        HitInfo temp;
        temp.Init();
        
        Point3 N = hInfo.N;
//        Point3 V = Point3(iRay.p.x -  hInfo.p.x, iRay.p.y - hInfo.p.y, iRay.p.z - hInfo.p.z);
        Point3 V = Point3(hInfo.p.x - iRay.p.x, hInfo.p.y - iRay.p.y, hInfo.p.z - iRay.p.z);
        V.Normalize();
        float n1 = 1, n2 = 1;
        if(hInfo.front){ /* Hitting from outside */
//            temp.front = false;
            n2 = ior;
//            cout<<"outside "<<endl;
        }
        else if(!hInfo.front){ /* Transmission from the inside */
//            temp.front = true;
            n1 = ior;
//            cout<<"intside... "<<endl;
            N = -hInfo.N;
        }
        float ratio_n = n1 / n2;
        
        float costheta_v = -V.Dot(N);        /* refer: http://graphics.stanford.edu/courses/cs148-10-summer/docs/2006--degreve--reflection_refraction.pdf */

        float sin2theta_t = ratio_n * ratio_n * (1 - costheta_v * costheta_v);
        Point3 T =   ratio_n * V + (ratio_n * costheta_v - sqrtf(1 - sin2theta_t)) * N ;
//        cout<<ratio_n<<" "<<"cos_v "<<costheta_v<<" sin2theta_t "<<sin2theta_t<<endl;
        Ray tRay = Ray(hInfo.p,T);
        
        //tRay.dir.Normalize();
        tRay.p.x = tRay.p.x + bias *tRay.dir.x; /* add bias */
        tRay.p.y = tRay.p.y + bias *tRay.dir.y;
        tRay.p.z = tRay.p.z + bias *tRay.dir.z;
//        cout<<"B temp front: "<< temp.front<<endl;
        if(sin2theta_t <= 1){
            if(RayTrace_2(tRay, temp)){
//                bounceCount--;
//                cout<<"A temp front: "<< temp.front<<endl;
                tShade  =  temp.node->GetMaterial()->Shade(tRay,temp,lights,bounceCount);
                tShade.r *= exp(-absorption.r * temp.z);
                tShade.g *= exp(-absorption.g * temp.z);
                tShade.b *= exp(-absorption.b * temp.z);
//                shade = tShade; /* remove later */
//                return shade;
               
                
                /* Calculate Schlick's approximation */
                
                R0 = (n1 - n2)/(n1 + n2);
                R0 *= R0;
                double  X = 0.0;
//                if(n1 > n2){
//                    X = 1.0 - sqrtf(1.0 - sin2theta_t);
//                }
//                else{ X = 1.0 - costheta_v; }
                X = 1.0 - costheta_v;
                Refl = R0 + (1.0 - R0) *  X * X * X * X * X;
                Trans = 1.0 - Refl;
                
            }
        }
        else {/* Total internal reflection */
            Refl = 1.0f;
        }
        
        /* Calculate reflection due to reflectance */
        if(bounceCount >0){
            N = hInfo.N;
            Point3 V = Point3(iRay.p.x -  P.x, iRay.p.y - P.y, iRay.p.z - P.z);
            //V.Normalize();
            Point3 VR = 2 * V.Dot(N) * N - V;
            //VR.Normalize();
            Ray rRay = Ray(P, VR);
            //rRay.dir.Normalize();
            rRay.p.x = rRay.p.x + bias *rRay.dir.x;
            rRay.p.y = rRay.p.y + bias *rRay.dir.y;
            rRay.p.z = rRay.p.z + bias *rRay.dir.z;
            HitInfo temp1;
            temp1.Init();
            if(rootNode.GetNumChild()>0){
                if(RayTrace_2(rRay, temp1)){
                    bounceCount --;
                    reflShade =   temp1.node->GetMaterial()->Shade(rRay, temp1, lights, bounceCount);
                }
            }
        }
        
//        cout<<"Refl: "<<Refl<<"Trans "<<Trans<<endl;
        tShade = refraction * (Trans * tShade + Refl * reflShade);
        
        
    }
    





    /* calculate reflection*/
    if(reflection.Grey()>0 && bounceCount > 0){

        Point3 N = hInfo.N;
        Point3 V = Point3(iRay.p.x -  P.x, iRay.p.y - P.y, iRay.p.z - P.z);
       // V.Normalize();
        Point3 VR = 2 * V.Dot(N) * N - V;
        Ray rRay = Ray(hInfo.p, VR);
        //rRay.dir.Normalize();
        rRay.p.x = rRay.p.x + bias *rRay.dir.x;
        rRay.p.y = rRay.p.y + bias *rRay.dir.y;
        rRay.p.z = rRay.p.z + bias *rRay.dir.z;
        HitInfo temp;
        temp.Init();
        if(rootNode.GetNumChild()>0){
            if(RayTrace_2(rRay, temp)){
                bounceCount--;
                rShade = reflection * temp.node->GetMaterial()->Shade(rRay, temp, lights, bounceCount);
            }
        }
    }
    
  
    
    /* Add shade with reflected and refracted colors */
    shade += (rShade + tShade);
    return shade;
};
Beispiel #11
0
int LoadScene(const char *filename)
{
    cout<<"Load.......";
    TiXmlDocument doc(filename);
    if ( ! doc.LoadFile() ) {
        printf("Failed to load the file \"%s\"\n", filename);
        return 0;
    }
    
    TiXmlElement *xml = doc.FirstChildElement("xml");
    if ( ! xml ) {
        printf("No \"xml\" tag found.\n");
        return 0;
    }
    
    TiXmlElement *scene = xml->FirstChildElement("scene");
    if ( ! scene ) {
        printf("No \"scene\" tag found.\n");
        return 0;
    }
    
    TiXmlElement *cam = xml->FirstChildElement("camera");
    if ( ! cam ) {
        printf("No \"camera\" tag found.\n");
        return 0;
    }
    
    nodeMtlList.clear();
    rootNode.Init();
    materials.DeleteAll();
    lights.DeleteAll();
    LoadScene( scene );
    
    // Assign materials
    int numNodes = nodeMtlList.size();
    for ( int i=0; i<numNodes; i++ ) {
        Material *mtl = materials.Find( nodeMtlList[i].mtlName );
        if ( mtl ) nodeMtlList[i].node->SetMaterial(mtl);
    }
    nodeMtlList.clear();
    
    // Load Camera
    camera.Init();
    camera.dir += camera.pos;
    TiXmlElement *camChild = cam->FirstChildElement();
    while ( camChild ) {
        if      ( COMPARE( camChild->Value(), "position"  ) ) ReadVector(camChild,camera.pos);
        else if ( COMPARE( camChild->Value(), "target"    ) ) ReadVector(camChild,camera.dir);
        else if ( COMPARE( camChild->Value(), "up"        ) ) ReadVector(camChild,camera.up);
        else if ( COMPARE( camChild->Value(), "fov"       ) ) ReadFloat (camChild,camera.fov);
        else if ( COMPARE( camChild->Value(), "width"     ) ) camChild->QueryIntAttribute("value", &camera.imgWidth);
        else if ( COMPARE( camChild->Value(), "height"    ) ) camChild->QueryIntAttribute("value", &camera.imgHeight);
        camChild = camChild->NextSiblingElement();
    }
    camera.dir -= camera.pos;
    camera.dir.Normalize();
    Point3 x = camera.dir ^ camera.up;
    camera.up = (x ^ camera.dir).GetNormalized();
    
    renderImage.Init( camera.imgWidth, camera.imgHeight );
    
    return 1;
}
Beispiel #12
0
void LoadLight(TiXmlElement *element)
{
    Light *light = NULL;
    
    // name
    const char* name = element->Attribute("name");
    printf("Light [");
    if ( name ) printf("%s",name);
    printf("]");
    
    // type
    const char* type = element->Attribute("type");
    if ( type ) {
        if ( COMPARE(type,"ambient") ) {
            printf(" - Ambient\n");
            AmbientLight *l = new AmbientLight();
            light = l;
            for ( TiXmlElement *child = element->FirstChildElement(); child!=NULL; child = child->NextSiblingElement() ) {
                if ( COMPARE( child->Value(), "intensity" ) ) {
                    Color c(1,1,1);
                    ReadColor( child, c );
                    l->SetIntensity(c);
                    printf("   intensity %f %f %f\n",c.r,c.g,c.b);
                }
            }
        } else if ( COMPARE(type,"direct") ) {
            printf(" - Direct\n");
            DirectLight *l = new DirectLight();
            light = l;
            for ( TiXmlElement *child = element->FirstChildElement(); child!=NULL; child = child->NextSiblingElement() ) {
                if ( COMPARE( child->Value(), "intensity" ) ) {
                    Color c(1,1,1);
                    ReadColor( child, c );
                    l->SetIntensity(c);
                    printf("   intensity %f %f %f\n",c.r,c.g,c.b);
                } else if ( COMPARE( child->Value(), "direction" ) ) {
                    Point3 v(1,1,1);
                    ReadVector( child, v );
                    l->SetDirection(v);
                    printf("   direction %f %f %f\n",v.x,v.y,v.z);
                }
            }
        } else if ( COMPARE(type,"point") ) {
            printf(" - Point\n");
            PointLight *l = new PointLight();
            light = l;
            for ( TiXmlElement *child = element->FirstChildElement(); child!=NULL; child = child->NextSiblingElement() ) {
                if ( COMPARE( child->Value(), "intensity" ) ) {
                    Color c(1,1,1);
                    ReadColor( child, c );
                    l->SetIntensity(c);
                    printf("   intensity %f %f %f\n",c.r,c.g,c.b);
                } else if ( COMPARE( child->Value(), "position" ) ) {
                    Point3 v(0,0,0);
                    ReadVector( child, v );
                    l->SetPosition(v);
                    printf("   position %f %f %f\n",v.x,v.y,v.z);
                }
            }
        } else {
            printf(" - UNKNOWN\n");
        }
    }
    
    if ( light ) {
        light->SetName(name);
        lights.push_back(light);
    }
    
}
void
avtOpenGL3DTextureVolumeRenderer::Render(
    const avtVolumeRendererImplementation::RenderProperties &props,
    const avtVolumeRendererImplementation::VolumeData &volume)
{
    static bool haveIssuedWarning = false;

#ifdef HAVE_LIBGLEW
    if(!(avt::glew::supported("GL_VERSION_1_2") ||
         avt::glew::supported("GL_EXT_texture3D")))
#endif
    {
        if(!haveIssuedWarning)
        {
            avtCallback::IssueWarning("Volume rendering based on 3D textures "
                                      "is not supported on your GPU.");
            haveIssuedWarning = true;
        }
        return;
    }

    // save state of what we will modify
    glPushAttrib(GL_COLOR_BUFFER_BIT|GL_TEXTURE_BIT|
        GL_DEPTH_BUFFER_BIT|GL_ENABLE_BIT);

    // Get the transfer function
    int ncolors=256;
    int nopacities=256;
    unsigned char rgba[256*4];
    props.atts.GetTransferFunction(rgba);

    // Get the dimensions
    int dims[3];
    vtkRectilinearGrid *grid = (vtkRectilinearGrid *)volume.grid;
    grid->GetDimensions(dims);

    int nx=dims[0];
    int ny=dims[1];
    int nz=dims[2];

    // Find the smallest power of two in each dimension
    // that will accomodate this data set
    int newnx = MAX(int(pow(2.0,1+int(log(double(nx-1))/log(2.0)))),1);
    int newny = MAX(int(pow(2.0,1+int(log(double(ny-1))/log(2.0)))),1);
    int newnz = MAX(int(pow(2.0,1+int(log(double(nz-1))/log(2.0)))),1);

    // Get the new lighting parameters
    LightList lights = avtCallback::GetCurrentLightList();

    // Determine if we need to invalidate the old texture
    if (volumetex && (props.atts != oldAtts || lights != oldLights))
    {
        glDeleteTextures(1, (GLuint*)&volumetexId);
        volumetexId = 0;
        delete[] volumetex;
        volumetex = NULL;
    }
    oldAtts = props.atts;
    oldLights = lights;


    //
    // Extract the lighting information from the actual light list
    //

    float light[4] = {0,0,1, 0};
    float ambient = 0.0;

    // Find an ambient light
    int i;
    for (i=0; i<lights.NumLights(); i++)
    {
        const LightAttributes &l = lights.GetLight(i);
        if (l.GetEnabledFlag() && l.GetType()==LightAttributes::Ambient)
        {
            // Take it's overall brightness
            double rgba[4];
            l.GetColor().GetRgba(rgba);
            ambient = l.GetBrightness() * (rgba[0]+rgba[1]+rgba[2])/3.;
            break;
        }
    }

    // Find a directional (object or camera) light
    for (i=0; i<lights.NumLights(); i++)
    {
        const LightAttributes &l = lights.GetLight(i);
        if (l.GetEnabledFlag() && l.GetType()!=LightAttributes::Ambient)
        {
            // Take it's direction
            const double *dir = l.GetDirection();
            light[0] = dir[0];
            light[1] = dir[1];
            light[2] = dir[2];
            break;
        }
    }

    // If we want to transform the light so it is attached to the camera:
    //I->MultiplyPoint(light, light);

    //
    // Create the 3D texture if we need to
    //

    if (!volumetex)
    {
        int nels=newnx*newny*newnz;
        volumetex = new unsigned char[4*nels];
        int outindex = -1;
        for (int k=0; k<newnz; k++)
        {
            for (int j=0; j<newny; j++)
            {
                for (int i=0; i<newnx; i++)
                {
                    int ijk[3]={i,j,k};
                    outindex++;
                    volumetex[outindex*4 + 0] = 0;
                    volumetex[outindex*4 + 1] = 0;
                    volumetex[outindex*4 + 2] = 0;
                    volumetex[outindex*4 + 3] = 0;

                    if (i>=nx || j>=ny || k>=nz)
                    {
                        // out of bounds data
                        continue;
                    }

                    int index = grid->ComputePointId(ijk);

                    float  v = volume.data.data->GetTuple1(index);
                    float  o = volume.opacity.data->GetTuple1(index);

                    // drop empty ones
                    if (v < -1e+37)
                        continue;

                    // normalize the value
                    v = (v < volume.data.min ? volume.data.min : v);
                    v = (v > volume.data.max ? volume.data.max : v);
                    v = (v-volume.data.min)/volume.data.size;
                    o = (o < volume.opacity.min ? volume.opacity.min : o);
                    o = (o > volume.opacity.max ? volume.opacity.max : o);
                    o = (o-volume.opacity.min)/volume.opacity.size;

                    // opactity map
                    float opacity;
                    opacity = float(rgba[int(o*(nopacities-1))*4 + 3])*
                        props.atts.GetOpacityAttenuation()/256.;
                    opacity = MAX(0,MIN(1,opacity));

                    // drop transparent splats
                    //if (opacity < .0001)
                    //    continue;

                    // do shading
                    float brightness;
                    const bool shading = props.atts.GetLightingFlag();
                    if (shading)
                    {
                        // Get the gradient
                        float gi = volume.gx[index];
                        float gj = volume.gy[index];
                        float gk = volume.gz[index];

                        // Amount of shading should be somewhat proportional
                        // to the magnitude of the gradient
                        float gm = 1.0;
                        if (props.atts.GetLowGradientLightingReduction() !=
                                                      VolumeAttributes::Off)
                        {
                           double lp = 1.0;
                           switch (props.atts.GetLowGradientLightingReduction())
                           {
                             case VolumeAttributes::Lowest:  lp = 1./16.;break;
                             case VolumeAttributes::Lower:   lp = 1./8.; break;
                             case VolumeAttributes::Low:     lp = 1./4.; break;
                             case VolumeAttributes::Medium:  lp = 1./2.; break;
                             case VolumeAttributes::High:    lp = 1.;    break;
                             case VolumeAttributes::Higher:  lp = 2.;    break;
                             case VolumeAttributes::Highest: lp = 4.;    break;
                             default: break;
                           }
                           if (props.atts.GetLowGradientLightingClampFlag())
                           {
                               gm = volume.gm[index] /
                                 props.atts.GetLowGradientLightingClampValue();
                           }
                           else
                           {
                               gm = volume.gmn[index];
                           }
                           gm = pow((double)gm, lp);
                        }
                        if (gm < 0)
                            gm = 0;
                        if (gm > 1)
                            gm = 1;

                        // Get the base lit brightness based on the 
                        // light direction and the gradient
                        float grad[3] = {gi,gj,gk};
                        float lightdir[3] = {light[0],light[1],light[2]};
                        brightness = vtkMath::Dot(grad,lightdir);
                        if (brightness<0) brightness *= -1;

                        // Modulate by the gradient magnitude
                        brightness = (1.0 - gm)*1.0 + gm*brightness;

                        // Modulate by the amount of ambient lighting
                        brightness = (1.0 - ambient)*brightness + ambient;
                    }
                    else
                    {
                        // No shading ata ll
                        brightness=1;
                    }

                    // Determine the actual color and opacity now
                    int colorindex = int(ncolors * v);
                    if (colorindex < 0)
                        colorindex = 0;
                    if (colorindex >= ncolors)
                        colorindex =  ncolors-1;
                    int colorindex4 = colorindex*4;
                    float scaledbrightness = brightness/255.;
                    float r,g,b;
                    r = float(rgba[colorindex4 + 0])*scaledbrightness;
                    g = float(rgba[colorindex4 + 1])*scaledbrightness;
                    b = float(rgba[colorindex4 + 2])*scaledbrightness;

                    volumetex[outindex*4 + 0] = (unsigned char)(r*255);
                    volumetex[outindex*4 + 1] = (unsigned char)(g*255);
                    volumetex[outindex*4 + 2] = (unsigned char)(b*255);
                    volumetex[outindex*4 + 3] = (unsigned char)(opacity*255);
                }
            }
        }

        // Create the texture
        //glPixelStorei(GL_UNPACK_ALIGNMENT,1);
        glGenTextures(1, (GLuint*)&volumetexId);
        glBindTexture(GL_TEXTURE_3D, volumetexId);

        glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, newnx, newny, newnz,
                     0, GL_RGBA, GL_UNSIGNED_BYTE, volumetex);
    }

    //
    // We have the texture; now draw with it
    //

    // Set up OpenGL parameters
    glDisable(GL_LIGHTING);
    glBindTexture(GL_TEXTURE_3D, volumetexId);
    glTexParameterf(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP);
    glTexParameterf(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP);
    glTexParameterf(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP);
    glTexParameterf(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameterf(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glEnable(GL_TEXTURE_3D);

    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    glEnable(GL_BLEND);
    glDepthMask(false);

    // Set up camera parameters
    vtkCamera *camera = vtkCamera::New();
    props.view.SetCameraFromView(camera);
    vtkMatrix4x4 *cameraMatrix = camera->GetViewTransformMatrix();

    //
    // Contour the bounding box at a user specified number of depths
    //

    BoundingBoxContourer bbox;

    // Extract the depth values at the corners of our bounding box
    int mapStructuredToUnstructured[8] = {0, 1, 3, 2, 4, 5, 7, 6};
    int bbox_index = 0;
    float minz =  FLT_MAX;
    float maxz = -FLT_MAX;
    for (int k=0; k<nz; k+=nz-1)
    {
        for (int j=0; j<ny; j+=ny-1)
        {
            for (int i=0; i<nx; i+=nx-1)
            {
                int ijk[] = {i,j,k};
                double worldpt[4] = {0,0,0,1};
                grid->GetPoint(grid->ComputePointId(ijk), worldpt);

                // Get the world space coordinates

                // The contourer expects an unstructured hex
                int pt_index = mapStructuredToUnstructured[bbox_index];

                bbox.x[pt_index] = worldpt[0];
                bbox.y[pt_index] = worldpt[1];
                bbox.z[pt_index] = worldpt[2];

                // Get the texture coordinates
                bbox.r[pt_index] = float(i) / float(newnx + 0) + (0.5 / float(newnx));
                bbox.s[pt_index] = float(j) / float(newny + 0) + (0.5 / float(newny));
                bbox.t[pt_index] = float(k) / float(newnz + 0) + (0.5 / float(newnz));

                // Get the camera space coordinates
                double viewpt[4];
                cameraMatrix->MultiplyPoint(worldpt, viewpt);
                float dist = viewpt[2];

                bbox.v[pt_index] = dist;

                if (dist < minz)
                    minz = dist;
                if (dist > maxz)
                    maxz = dist;

                bbox_index++;

                if (nx == 1)
                    break;
            }

            if (ny == 1)
                break;
        }

        if (nz == 1)
            break;
    }

    // Determine the depth values we need
    int pt0 = mapStructuredToUnstructured[0];
    int ptn = mapStructuredToUnstructured[7];
    float dx = bbox.x[pt0] - bbox.x[ptn];
    float dy = bbox.y[pt0] - bbox.y[ptn];
    float dz = bbox.z[pt0] - bbox.z[ptn];
    float dist = sqrt(dx*dx + dy*dy + dz*dz);

    // Do the actual contouring
    glBegin(GL_TRIANGLES);
    glColor4f(1.,1.,1.,1.);
    int ns = props.atts.GetNum3DSlices();
    if (ns < 1)
        ns = 1;
    if (ns > 1000)
        ns = 1000;

    float tr[15], ts[15], tt[15];
    float vx[15], vy[15], vz[15];
    int   ntriangles;
    for (int z=0; z<ns; z++)
    {
        float value = (float(z)+0.5)/float(ns);

        bbox.ContourTriangles(minz + dist*value,
                              ntriangles, tr, ts, tt, vx, vy, vz);

        for (int t=0; t<ntriangles*3; t++)
        {
            glTexCoord3f(tr[t], ts[t], tt[t]);
            glVertex3f(vx[t], vy[t], vz[t]);
        }
    }
    glEnd();

    // Set some GL parameters back to their expected values
    // and free memory
    glPopAttrib();

    camera->Delete();
}