Example #1
0
		/** \brief Create a view from imageNum of the provided file.
		 *
		 * \param file - file from which to read the image data.
		 * \param imageNum - subimage number for this view in the input file
		 * \param currToWorld - current -> world transformation matrix.
		 */
		CqShadowView(const boost::shared_ptr<IqTiledTexInputFile>& file, TqInt imageNum,
				const CqMatrix& currToWorld)
			: m_currToLight(),
			m_currToRaster(),
			m_currToRasterVec(),
			m_viewDirec(),
			m_pixels(file, imageNum)
		{
			// TODO refactor with CqShadowSampler, also refactor this function,
			// since it's a bit unweildly...
			if(!file)
				AQSIS_THROW_XQERROR(XqInternal, EqE_NoFile,
						"Cannot construct shadow map from NULL file handle");

			const CqTexFileHeader& header = file->header(imageNum);
			if(header.channelList().sharedChannelType() != Channel_Float32)
				AQSIS_THROW_XQERROR(XqBadTexture, EqE_BadFile,
						"Shadow maps must hold 32-bit floating point data");

			// Get matrix which transforms the sample points to the light
			// camera coordinates.
			const CqMatrix* worldToLight
				= header.findPtr<Attr::WorldToCameraMatrix>();
			if(!worldToLight)
			{
				AQSIS_THROW_XQERROR(XqBadTexture, EqE_BadFile,
						"No world -> camera matrix found in file \""
						<< file->fileName() << "\"");
			}
			m_currToLight = (*worldToLight) * currToWorld;

			// Get matrix which transforms the sample points to texture coordinates.
			const CqMatrix* worldToLightScreen
				= header.findPtr<Attr::WorldToScreenMatrix>();
			if(!worldToLightScreen)
			{
				AQSIS_THROW_XQERROR(XqBadTexture, EqE_BadFile,
						"No world -> screen matrix found in file \""
						<< file->fileName() << "\"");
			}
			m_currToRaster = (*worldToLightScreen) * currToWorld;
			// worldToLightScreen transforms world coordinates to "screen" coordinates,
			// ie, onto the 2D box [-1,1]x[-1,1].  We instead want texture coordinates,
			// which correspond to the box [0,width]x[0,height].  In
			// addition, the direction of increase of the y-axis should be
			// swapped, since texture coordinates define the origin to be in
			// the top left of the texture rather than the bottom right.
			m_currToRaster.Translate(CqVector3D(1,-1,0));
			m_currToRaster.Scale(0.5f, -0.5f, 1);

			// Transform the light origin to "current" space to use
			// when checking the visibility of a point.
			m_lightPos = m_currToLight.Inverse()*CqVector3D(0,0,0);
			// Transform the normal (0,0,1) in light space into a normal in
			// "current" space.  The appropriate matrix is the inverse of the
			// cam -> light normal transformation, which itself is the inverse
			// transpose of currToLightVec.
			CqMatrix currToLightVec = m_currToLight;
			currToLightVec[3][0] = 0;
			currToLightVec[3][1] = 0;
			currToLightVec[3][2] = 0;
			m_viewDirec = currToLightVec.Transpose()*CqVector3D(0,0,1);
			m_viewDirec.Unit();
		}
		/** \brief Create a view from imageNum of the provided file.
		 *
		 * \param file - file from which to read the image data.
		 * \param imageNum - subimage number for this view in the input file
		 * \param currToWorld - current -> world transformation matrix.
		 */
		CqOccView(const boost::shared_ptr<IqTiledTexInputFile>& file, TqInt imageNum,
				const CqMatrix& currToWorld)
			: m_currToLight(),
			m_currToRaster(),
			m_currToRasterVec(),
			m_negViewDirec(),
			m_pixels(file, imageNum)
		{
			// TODO refactor with CqShadowSampler, also refactor this function,
			// since it's a bit unweildly...
			if(!file)
				AQSIS_THROW_XQERROR(XqInternal, EqE_NoFile,
						"Cannot construct shadow map from NULL file handle");

			const CqTexFileHeader& header = file->header(imageNum);
			if(header.channelList().sharedChannelType() != Channel_Float32)
				AQSIS_THROW_XQERROR(XqBadTexture, EqE_BadFile,
						"Shadow maps must hold 32-bit floating point data");

			// Get matrix which transforms the sample points to the light
			// camera coordinates.
			const CqMatrix* worldToLight
				= header.findPtr<Attr::WorldToCameraMatrix>();
			if(!worldToLight)
			{
				AQSIS_THROW_XQERROR(XqBadTexture, EqE_BadFile,
						"No world -> camera matrix found in file \""
						<< file->fileName() << "\"");
			}
			m_currToLight = (*worldToLight) * currToWorld;

			// Get matrix which transforms the sample points to texture coordinates.
			const CqMatrix* worldToLightScreen
				= header.findPtr<Attr::WorldToScreenMatrix>();
			if(!worldToLightScreen)
			{
				AQSIS_THROW_XQERROR(XqBadTexture, EqE_BadFile,
						"No world -> screen matrix found in file \""
						<< file->fileName() << "\"");
			}
			m_currToRaster = (*worldToLightScreen) * currToWorld;
			// worldToLightScreen transforms world coordinates to "screen" coordinates,
			// ie, onto the 2D box [-1,1]x[-1,1].  We instead want texture coordinates,
			// which correspond to the box [0,width]x[0,height].  In
			// addition, the direction of increase of the y-axis should be
			// swapped, since texture coordinates define the origin to be in
			// the top left of the texture rather than the bottom right.
			m_currToRaster.Translate(CqVector3D(1,-1,0));
			m_currToRaster.Scale(0.5f*header.width(), -0.5f*header.height(), 1);
			// This extra translation is by half a pixel width - it moves the
			// raster coordinates 
			m_currToRaster.Translate(CqVector3D(-0.5,-0.5,0));

			// Convert current -> texture transformation into a vector
			// transform rather than a point transform.
			// TODO: Put this stuff into the CqMatrix class?
			m_currToRasterVec = m_currToRaster;
			m_currToRasterVec[3][0] = 0;
			m_currToRasterVec[3][1] = 0;
			m_currToRasterVec[3][2] = 0;
			// This only really makes sense when the matrix is affine rather
			// than projective, ie, the last column is (0,0,0,h) 
			//
			// TODO: Investigate whether this is really correct.
//			assert(m_currToRasterVec[0][3] == 0);
//			assert(m_currToRasterVec[1][3] == 0);
//			assert(m_currToRasterVec[2][3] == 0);
			m_currToRasterVec[0][3] = 0;
			m_currToRasterVec[1][3] = 0;
			m_currToRasterVec[2][3] = 0;

			// Transform the normal (0,0,1) in light space into a normal in
			// "current" space.  The appropriate matrix is the inverse of the
			// cam -> light normal transformation, which itself is the inverse
			// transpose of currToLightVec.
			CqMatrix currToLightVec = m_currToLight;
			currToLightVec[3][0] = 0;
			currToLightVec[3][1] = 0;
			currToLightVec[3][2] = 0;
			m_negViewDirec = currToLightVec.Transpose()*CqVector3D(0,0,-1);
			m_negViewDirec.Unit();
		}