Example #1
0
void calculateView()
{
    cameraPos.z = getZ( cameraPos.x, cameraPos.y ) + tripodHeight;
    
    vec4 lookAtPos( cameraPos.x + cos( cameraRotZ ) * cos( cameraRotXY ),
                    cameraPos.y + cos( cameraRotZ ) * sin( cameraRotXY ),
                    cameraPos.z + sin( cameraRotZ ),
                    1.0 );

    projStack.push( Perspective( 45.0, 1.0, 0.01, viewLimitOn ? viewLimit : 3.0 * std::fmax( gridSize, tripodHeight ) ) );
    mvStack.push( LookAt( cameraPos, lookAtPos, up ) );
}
Example #2
0
TEST( MatrixUtils, generateLookAtLH )
{
   Matrix tamyLookAtMtx;

   Vector cameraOriginPos( 10, 20, -30 ); 
   Vector lookAtPos( 15, 20, -30 );
   Vector upAxis; upAxis.set( Quad_0100 );

   MatrixUtils::generateLookAtLH( cameraOriginPos, lookAtPos, upAxis, tamyLookAtMtx );

   Vector expectedLookVec;
   expectedLookVec.setSub( lookAtPos, cameraOriginPos );
   expectedLookVec.normalize();

   Vector transformedLookVec;
   tamyLookAtMtx.transformNorm( Vector( 0, 0, 1 ), transformedLookVec );

   COMPARE_VEC( cameraOriginPos, tamyLookAtMtx.position() );
   COMPARE_VEC( expectedLookVec, transformedLookVec );
}
//===========================================================================
void cCamera::renderView(const int a_windowWidth, 
						 const int a_windowHeight)
{
	//-----------------------------------------------------------------------
	// (1) COMPUTE SHADOW MAPS
	//-----------------------------------------------------------------------

	// initialize a temporary variable that will inform us if shadow casting is used 
	// by our application and also supported by the hardware. 
	bool useShadowCasting = false;
    list<cShadowMap*> shadowMaps;
    shadowMaps.clear();

	// shadow casting has been requested, we will first need to verify if the hardware
	// can support it
	if (m_useShadowCasting)
	{
		// we verify if shadow casting is supported by hardware
		if (isShadowCastingSupported())
		{
            // we check every light source. if it is a spot light we verify if shadow casting is enabled
            for (unsigned int i=0; i<m_parentWorld->m_lights.size(); i++)
            {
			    cSpotLight* light =  dynamic_cast<cSpotLight*>(m_parentWorld->getLightSource(i));
			    if (light != NULL)
			    {
				    if (light->getShadowMapEnabled())
				    {
                        // update shadow map
				        light->updateShadowMap();

                        // add shadowmap to list
                        shadowMaps.push_back(light->m_shadowMap);

                        // shadow mapping is used by at least one light source!
					    useShadowCasting = true;
				    }
			    }
            }
		}
	}


	//-----------------------------------------------------------------------
	// (2) INITIALIZE CURRENT VIEWPORT
	//-----------------------------------------------------------------------

    // check window size
    if (a_windowHeight == 0) { return; }

    // store most recent size of display
    m_lastDisplayWidth = a_windowWidth;
    m_lastDisplayHeight = a_windowHeight;

	// setup viewport
	glViewport(0, 0, a_windowWidth, a_windowHeight);

    // compute aspect ratio
    double glAspect = ((double)a_windowWidth / (double)a_windowHeight);

    // compute global pose
    computeGlobalPositionsFromRoot(true);

    // set background color
    glClearColor(m_parentWorld->getBackgroundColor().getR(),
                 m_parentWorld->getBackgroundColor().getG(),
                 m_parentWorld->getBackgroundColor().getB(),
                 1.0);


	//-----------------------------------------------------------------------
	// (3) VERIFY IF STEREO DISPLAY IS ENABLED
	//-----------------------------------------------------------------------
    GLboolean stereo = false;
    unsigned int numStereoPass = 1;
    if (m_useStereo)
    {
        // verify if stereo is available by the graphics hardware and camera is of perspective model
        glGetBooleanv(GL_STEREO, &stereo);  
        if (stereo && m_perspectiveMode)
        {
            // stereo is available - we shall perform 2 rendering passes for LEFT and RIGHT eye.
            numStereoPass = 2;
        }
        else
        {
            stereo = false;
        }   
    }


	//-----------------------------------------------------------------------
	// (4) RENDER THE ENTIRE SCENE
	//-----------------------------------------------------------------------
    for (unsigned int i=0; i<numStereoPass; i++)
    {
	    //-------------------------------------------------------------------
	    // (4.1) SELECTING THE DISPLAY BUFFER (MONO / STEREO)
	    //-------------------------------------------------------------------
        if (stereo)
        {
            if (i == 0)
            {
                glDrawBuffer(GL_BACK_LEFT);
            }
            else
            {
                glDrawBuffer(GL_BACK_RIGHT);
            }
        }
        else
        {
            glDrawBuffer(GL_BACK);
        }

	    //-------------------------------------------------------------------
	    // (4.2) CLEAR CURRENT BUFFER
	    //-------------------------------------------------------------------

        // clear the color and depth buffers
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
	    glShadeModel(GL_SMOOTH);

	    //-------------------------------------------------------------------
	    // (4.3)  RENDER BACK PLANE
	    //-------------------------------------------------------------------

        // render the 2D backlayer
        // it will set up its own projection matrix
        if (m_backLayer->getNumChildren())
	    {
		    renderLayer(m_backLayer,
                        a_windowWidth,
                        a_windowHeight);
	    }

        // clear depth buffer
        glClear(GL_DEPTH_BUFFER_BIT);

	    //-------------------------------------------------------------------
	    // (4.4a) SETUP CAMERA  (MONO RENDERING)
	    //-------------------------------------------------------------------
        if (!stereo)
        {
            // init projection matrix
	        glMatrixMode(GL_PROJECTION);
	        glLoadIdentity();

            // create projection matrix depending of camera mode
            if (m_perspectiveMode)
            {
		        // setup perspective camera
		        glMatrixMode(GL_PROJECTION);
		        glLoadIdentity();
		        gluPerspective(
				        m_fieldViewAngle,   // Field of View angle.
				        glAspect,           // Aspect ratio of viewing volume.
				        m_distanceNear,     // Distance to Near clipping plane.
				        m_distanceFar);     // Distance to Far clipping plane.
            }
            else
            {
                // setup orthographic camera
                double left     = -m_orthographicWidth / 2.0;
                double right    = -left;
                double bottom   = left / glAspect;
                double top      = -bottom;

                glOrtho(left,               // Left vertical clipping plane.
                        right,              // Right vertical clipping plane.            
                        bottom,             // Bottom vertical clipping plane.
                        top,                // Top vertical clipping plane.
                        m_distanceNear,     // Distance to Near clipping plane.
				        m_distanceFar       // Distance to Far clipping plane.
                    );
            }

            // setup cameta position
            glMatrixMode(GL_MODELVIEW);
	        glLoadIdentity();

	        // compute camera location
	        cVector3d lookAt = m_globalRot.getCol0();
	        cVector3d lookAtPos;
	        m_globalPos.subr(lookAt, lookAtPos);
	        cVector3d up = m_globalRot.getCol2();

	        // setup modelview matrix
	        gluLookAt( m_globalPos(0) ,  m_globalPos(1) ,  m_globalPos(2) ,
			           lookAtPos(0) ,    lookAtPos(1) ,    lookAtPos(2) ,
			           up(0) ,           up(1) ,           up(2)  );
        }


	    //-------------------------------------------------------------------
	    // (4.4b) SETUP CAMERA  (STEREO RENDERING)
	    //-------------------------------------------------------------------
        else
        {
		    //-----------------------------------------------------------------
		    // Based on Paul Bourke's stereo rendering tutorial:
		    // http://local.wasp.uwa.edu.au/~pbourke/miscellaneous/stereographics/stereorender/
		    //-----------------------------------------------------------------

		    double radians = ((C_PI / 180.0) * m_fieldViewAngle / 2.0f);
		    double wd2 = m_distanceNear * tan(radians);
		    double ndfl = m_distanceNear / m_stereoFocalLength;

		    // compute the look, up, and cross vectors
		    cVector3d lookv = m_globalRot.getCol0();
		    lookv.mul(-1.0);

		    cVector3d upv = m_globalRot.getCol2();
		    cVector3d offsetv = cCross(lookv,upv);

		    offsetv.mul(m_stereoEyeSeparation / 2.0);

		    if (i == 0) offsetv.mul(-1.0);

		    // decide whether to offset left or right
		    double stereo_multiplier = (i == 0) ? 1.0f : -1.0f;  // (i == 0) correspond to LEFT IMAGE, (i == 1) correspond to RIGHT IMAGE

		    double left   = -1.0 * glAspect * wd2 + stereo_multiplier * 0.5 * m_stereoEyeSeparation * ndfl;
		    double right  =        glAspect * wd2 + stereo_multiplier * 0.5 * m_stereoEyeSeparation * ndfl;
		    double top    =        wd2;
		    double bottom = -1.0 * wd2;

		    // setup projection matrix
		    glMatrixMode(GL_PROJECTION);
		    glLoadIdentity();
		    glFrustum(left,right,bottom,top,m_distanceNear,m_distanceFar);

		    // initialize modelview matrix
		    glMatrixMode(GL_MODELVIEW);
		    glLoadIdentity();

		    // compute the offset we should apply to the current camera position
		    cVector3d pos = cAdd(m_globalPos,offsetv);

		    // compute the shifted camera position
		    cVector3d lookAtPos;
		    pos.addr(lookv, lookAtPos);

		    // setup modelview matrix
		    gluLookAt(pos(0) ,       pos(1) ,       pos(2) ,
				      lookAtPos(0) , lookAtPos(1) , lookAtPos(2) ,
				      upv(0) ,       upv(1) ,       upv(2) 
				      );
        }

        // Backup the view and projection matrix for future reference
        glGetDoublev(GL_PROJECTION_MATRIX,m_projectionMatrix.getData());
	    glGetDoublev(GL_MODELVIEW_MATRIX, m_modelviewMatrix.getData());


	    //-------------------------------------------------------------------
	    // (4.5) RENDER THE 3D WORLD
	    //-------------------------------------------------------------------

        // Set up reasonable default OpenGL state
        glEnable(GL_LIGHTING);
        glDisable(GL_BLEND);
        glDepthMask(GL_TRUE);
        glEnable(GL_DEPTH_TEST);
	    glDepthFunc(GL_LEQUAL);

	    // rendering options
	    cRenderOptions options;

        // optionally perform multiple rendering passes for transparency
        if (m_useMultipassTransparency) 
	    {
		    ////////////////////////////////////////////////////////////////////
		    // MULTI PASS - USING SHADOW CASTING
		    ////////////////////////////////////////////////////////////////////
		    if (useShadowCasting)
		    {
                // setup rendering options
                options.m_camera                                = this;
                options.m_single_pass_only						= false;
                options.m_render_opaque_objects_only			= true;
                options.m_render_transparent_front_faces_only	= false;
                options.m_render_transparent_back_faces_only	= false;
                options.m_enable_lighting						= true;
                options.m_render_materials						= true;
                options.m_render_textures						= true;
                options.m_creating_shadow_map					= false;
                options.m_rendering_shadow						= true;
                options.m_shadow_light_level					= 1.0 - m_parentWorld->getShadowIntensity();
                options.m_storeObjectPositions					= false;
                options.m_resetDisplay                          = m_resetDisplay;

                // render 1st pass (opaque objects - shadowed regions)
                m_parentWorld->renderSceneGraph(options);

                // setup rendering options
                options.m_rendering_shadow						= false;
                options.m_shadow_light_level					= 1.0;

                // render 2nd pass (opaque objects - non shadowed regions)
                list<cShadowMap*>::iterator i;
                for(i = shadowMaps.begin(); i !=shadowMaps.end(); ++i)
                {
                    cShadowMap *shadowMap = *i;
                    shadowMap->render(options);

                    glEnable(GL_POLYGON_OFFSET_FILL);
                    m_parentWorld->renderSceneGraph(options);
                    glDisable(GL_POLYGON_OFFSET_FILL);

                    // restore states
                    glActiveTexture(GL_TEXTURE0_ARB);
                    glDisable(GL_TEXTURE_2D);
                    glDisable(GL_TEXTURE_GEN_S);
                    glDisable(GL_TEXTURE_GEN_T);
                    glDisable(GL_TEXTURE_GEN_R);
                    glDisable(GL_TEXTURE_GEN_Q);
                    glDisable(GL_ALPHA_TEST);
                }

                // setup rendering options
                options.m_render_opaque_objects_only			= false;
                options.m_render_transparent_back_faces_only	= true;

                // render 3rd pass (transparent objects - back faces only)
                m_parentWorld->renderSceneGraph(options);

                // modify rendering options for third pass
                options.m_render_transparent_back_faces_only	= false;
                options.m_render_transparent_front_faces_only	= true;

                // render 4th pass (transparent objects - back faces only)
                m_parentWorld->renderSceneGraph(options);
		    }


		    ////////////////////////////////////////////////////////////////////
		    // MULTI PASS - WITHOUT SHADOWS
		    ////////////////////////////////////////////////////////////////////
		    else
		    {
			    // setup rendering options for first pass
                options.m_camera                                = this;
			    options.m_single_pass_only						= false;
			    options.m_render_opaque_objects_only			= true;
			    options.m_render_transparent_front_faces_only	= false;
			    options.m_render_transparent_back_faces_only	= false;
			    options.m_enable_lighting						= true;
			    options.m_render_materials						= true;
			    options.m_render_textures						= true;
			    options.m_creating_shadow_map					= false;
			    options.m_rendering_shadow						= false;
			    options.m_shadow_light_level					= 1.0;
			    options.m_storeObjectPositions					= true;
                options.m_resetDisplay                          = m_resetDisplay;

			    // render 1st pass (opaque objects - all faces)
			    m_parentWorld->renderSceneGraph(options);

			    // modify rendering options
			    options.m_render_opaque_objects_only			= false;
			    options.m_render_transparent_back_faces_only	= true;
			    options.m_storeObjectPositions					= false;

			    // render 2nd pass (transparent objects - back faces only)
			    m_parentWorld->renderSceneGraph(options);

			    // modify rendering options
			    options.m_render_transparent_back_faces_only	= false;
			    options.m_render_transparent_front_faces_only	= true;

			    // render 3rd pass (transparent objects - front faces only)
			    m_parentWorld->renderSceneGraph(options);
		    }
        }
        else
        {
		    ////////////////////////////////////////////////////////////////////
		    // SINGLE PASS - USING SHADOW CASTING 
		    ////////////////////////////////////////////////////////////////////
		    if (useShadowCasting)
		    {
			    // setup rendering options for single pass
                options.m_camera                                = this;
			    options.m_single_pass_only						= true;
			    options.m_render_opaque_objects_only			= false;
			    options.m_render_transparent_front_faces_only	= false;
			    options.m_render_transparent_back_faces_only	= false;
			    options.m_enable_lighting						= true;
			    options.m_render_materials						= true;
			    options.m_render_textures						= true;
			    options.m_creating_shadow_map					= false;
			    options.m_rendering_shadow						= true;
			    options.m_shadow_light_level					= 1.0 - m_parentWorld->getShadowIntensity();
			    options.m_storeObjectPositions					= false;
                options.m_resetDisplay                          = m_resetDisplay;

			    // render 1st pass (opaque objects - all faces - shadowed regions)
			    m_parentWorld->renderSceneGraph(options);

			    // setup rendering options
			    options.m_rendering_shadow						= false;
			    options.m_shadow_light_level					= 1.0;

			    // render 2nd pass (opaque objects - all faces - non shadowed regions)
                list<cShadowMap*>::iterator i;
                for(i = shadowMaps.begin(); i !=shadowMaps.end(); ++i)
                {
                    cShadowMap *shadowMap = *i;
                    shadowMap->render(options);

                    glEnable(GL_POLYGON_OFFSET_FILL);
                    m_parentWorld->renderSceneGraph(options);
                    glDisable(GL_POLYGON_OFFSET_FILL);

                    // restore states
                    glActiveTexture(GL_TEXTURE0_ARB);
                    glDisable(GL_TEXTURE_2D);
                    glDisable(GL_TEXTURE_GEN_S);
                    glDisable(GL_TEXTURE_GEN_T);
                    glDisable(GL_TEXTURE_GEN_R);
                    glDisable(GL_TEXTURE_GEN_Q);
                    glDisable(GL_ALPHA_TEST);
                }

			    // restore states
			    glActiveTexture(GL_TEXTURE0_ARB);
			    glDisable(GL_TEXTURE_2D);
			    glDisable(GL_TEXTURE_GEN_S);
			    glDisable(GL_TEXTURE_GEN_T);
			    glDisable(GL_TEXTURE_GEN_R);
			    glDisable(GL_TEXTURE_GEN_Q);
			    glDisable(GL_ALPHA_TEST);
		    }


		    ////////////////////////////////////////////////////////////////////
		    // SINGLE PASS - WITHOUT SHADOWS
		    ////////////////////////////////////////////////////////////////////
		    else
		    {
			    // setup rendering options for single pass
                options.m_camera                                = this;
			    options.m_single_pass_only						= true;
			    options.m_render_opaque_objects_only			= false;
			    options.m_render_transparent_front_faces_only	= false;
			    options.m_render_transparent_back_faces_only	= false;
			    options.m_enable_lighting						= true;
			    options.m_render_materials						= true;
			    options.m_render_textures						= true;
			    options.m_creating_shadow_map					= false;
			    options.m_rendering_shadow						= false;
			    options.m_shadow_light_level					= 1.0;
			    options.m_storeObjectPositions					= true;
                options.m_resetDisplay                          = m_resetDisplay;

			    // render single pass (all objects)
			    m_parentWorld->renderSceneGraph(options);                
		    }
        }        

	    //-------------------------------------------------------------------
	    // (4.6) RENDER FRONT PLANE
	    //-------------------------------------------------------------------

        // clear depth buffer
        glClear(GL_DEPTH_BUFFER_BIT);

        // render the 'front' 2d object layer; it will set up its own
        // projection matrix
        if (m_frontLayer->getNumChildren() > 0)
	    {
		    renderLayer(m_frontLayer, 
                        a_windowWidth, 
                        a_windowHeight);
	    }

        // if requested, display reset has now been completed
        m_resetDisplay = false;
    }
}