Esempio n. 1
0
int Hsh::loadData(FILE* file, int width, int height, int basisTerm, bool urti, CallBackPos * cb,const QString& text)
{
	type = "HSH";
	w = width;
	h = height;

	ordlen = basisTerm;
	bands = 3;
	fread(gmin, sizeof(float), basisTerm, file);
	fread(gmax, sizeof(float), basisTerm, file);

	if (feof(file))
		return -1;

	int offset = 0;

	int size = w * h * basisTerm;
	float* redPtr = new float[size];
	float* greenPtr = new float[size];
	float* bluePtr = new float[size];
	
	unsigned char c;

	if (!urti)
	{
		for(int j = 0; j < h; j++)
		{
			if (cb != NULL && j % 50 == 0)(*cb)(j * 50.0 / h, text);
			for(int i = 0; i < w; i++)
			{				
				offset = j * w + i;
				for (int k = 0; k < basisTerm; k++)
				{
					if (feof(file))
						return -1;
					fread(&c, sizeof(unsigned char), 1, file);
					redPtr[offset*basisTerm + k] = (((float)c) / 255.0) * (gmax[k] - gmin[k]) + gmin[k];
				}
				for (int k = 0; k < basisTerm; k++)
				{
					if (feof(file))
						return -1;
					fread(&c, sizeof(unsigned char), 1, file);
					greenPtr[offset*basisTerm + k] = (((float)c) / 255.0) * (gmax[k] - gmin[k]) + gmin[k];
				}
				for (int k = 0; k < basisTerm; k++)
				{
					if (feof(file))
						return -1;
					fread(&c, sizeof(unsigned char), 1, file);
					bluePtr[offset*basisTerm + k] = (((float)c) / 255.0) * (gmax[k] - gmin[k]) + gmin[k];
				}
			}
		}
	}
	else
	{
		for(int j = 0; j < h; j++)
		{
			if (cb != NULL && j % 50 == 0)(*cb)(j * 50 / h, text);
			for(int i = 0; i < w; i++)
			{				
				offset = j * w + i;
				for (int k = 0; k < basisTerm; k++)
				{
					if (feof(file))
						return -1;
					fread(&c, sizeof(unsigned char), 1, file);
					redPtr[offset*basisTerm + k] = (((float)c) / 255.0) * gmin[k] + gmax[k];
				}
				for (int k = 0; k < basisTerm; k++)
				{
					if (feof(file))
						return -1;
					fread(&c, sizeof(unsigned char), 1, file);
					greenPtr[offset*basisTerm + k] = (((float)c) / 255.0) * gmin[k] + gmax[k];
				}
				for (int k = 0; k < basisTerm; k++)
				{
					if (feof(file))
						return -1;
					fread(&c, sizeof(unsigned char), 1, file);
					bluePtr[offset*basisTerm + k] = (((float)c) / 255.0) * gmin[k] + gmax[k];
				}
			}
		}
	}
	
	fclose(file);

	mipMapSize[0] = QSize(w, h);

	redCoefficients.setLevel(redPtr, size, 0);
	greenCoefficients.setLevel(greenPtr, size, 0);
	blueCoefficients.setLevel(bluePtr, size, 0);
	
	// Computes mip-mapping.
	if (cb != NULL)	(*cb)(50, "Mip mapping generation...");
	
	for (int level = 1; level < MIP_MAPPING_LEVELS; level++)
	{
		int width = mipMapSize[level - 1].width();
		int height = mipMapSize[level - 1].height();
		int width2 = ceil(width / 2.0);
		int height2 = ceil(height / 2.0);
		size = width2*height2*basisTerm;
		redCoefficients.setLevel(new float[size], size, level);
		greenCoefficients.setLevel(new float[size], size, level);
		blueCoefficients.setLevel(new float[size], size, level);
		int th_id;
		#pragma omp parallel for
		for (int i = 0; i < height - 1; i+=2)
		{
			th_id = omp_get_thread_num();
			if (th_id == 0)
			{
				if (cb != NULL && i % 50 == 0)	(*cb)(50 + (level-1)*8 + i*8.0/height, "Mip mapping generation...");
			}
			for (int j = 0; j < width - 1; j+=2)
			{
				int index1 = (i * width + j)*ordlen;
				int index2 = (i * width + j + 1)*ordlen;
				int index3 = ((i + 1) * width + j)*ordlen;
				int index4 = ((i + 1) * width + j + 1)*ordlen;
				int offset = (i/2 * width2 + j/2)*ordlen;
				for (int k = 0; k < basisTerm; k++)
				{
					redCoefficients.calcMipMapping(level, offset + k, index1 + k, index2 + k, index3 + k , index4 + k);
					greenCoefficients.calcMipMapping(level, offset + k, index1 + k, index2 + k, index3 + k , index4 + k);
					blueCoefficients.calcMipMapping(level, offset + k, index1 + k, index2 + k, index3 + k , index4 + k);
				}
			}
		}
		if (width2 % 2 != 0)
		{
			for (int i = 0; i < height - 1; i+=2)
			{
				int index1 = ((i + 1) * width - 1)*ordlen;
				int index2 = ((i + 2) * width - 1)*ordlen;
				int offset = ((i/2 + 1) * width2 - 1)*ordlen;
				for (int k = 0; k < basisTerm; k++)
				{
					redCoefficients.calcMipMapping(level, offset + k, index1 + k, index2 + k);
					greenCoefficients.calcMipMapping(level, offset + k, index1 + k, index2 + k);
					blueCoefficients.calcMipMapping(level, offset + k, index1 + k, index2 + k);
				}
			}
		}
		if (height % 2 != 0)
		{
			for (int i = 0; i < width - 1; i+=2)
			{
				int index1 = ((height - 1) * width + i)*ordlen;
				int index2 = ((height - 1) * width + i + 1)*ordlen;
				int offset = ((height2 - 1) * width2 + i/2)*ordlen;
				for (int k = 0; k < basisTerm; k++)
				{
					redCoefficients.calcMipMapping(level, offset + k, index1 + k, index2 + k);
					greenCoefficients.calcMipMapping(level, offset + k, index1 + k, index2 + k);
					blueCoefficients.calcMipMapping(level, offset + k, index1 + k, index2 + k);
				}
			}
		}
		if (height % 2 != 0 && width % 2 != 0)
		{
			int index1 = (height*width - 1)*ordlen;
			int offset = (height2*width2 - 1)*ordlen;
			for (int k = 0; k < basisTerm; k++)
			{
				redCoefficients.calcMipMapping(level, offset + k, index1 + k);
				greenCoefficients.calcMipMapping(level, offset + k, index1 + k);
				blueCoefficients.calcMipMapping(level, offset + k, index1 + k);
			}
		}
		mipMapSize[level] = QSize(width2, height2);
	}

	//Compute normals.
	if (cb != NULL) (*cb)(75 , "Normals generation...");
	Eigen::Vector3d l0(sin(M_PI/4)*cos(M_PI/6), sin(M_PI/4)*sin(M_PI/6), cos(M_PI/4));
	Eigen::Vector3d l1(sin(M_PI/4)*cos(5*M_PI / 6), sin(M_PI/4)*sin(5*M_PI / 6), cos(M_PI/4));
	Eigen::Vector3d l2(sin(M_PI/4)*cos(3*M_PI / 2), sin(M_PI/4)*sin(3*M_PI / 2), cos(M_PI/4));
    float hweights0[16], hweights1[16], hweights2[16];
	getHSH(M_PI / 4, M_PI / 6, hweights0, ordlen);
	getHSH(M_PI / 4, 5*M_PI / 6, hweights1, ordlen);
	getHSH(M_PI / 4, 3*M_PI / 2, hweights2, ordlen);
	
	
	Eigen::Matrix3d L;
	L.setIdentity();
	L.row(0) = l0;
	L.row(1) = l1;
	L.row(2) = l2;
	Eigen::Matrix3d LInverse = L.inverse();
	
	for (int level = 0; level < MIP_MAPPING_LEVELS; level++)
	{
		const float* rPtr = redCoefficients.getLevel(level);
		const float* gPtr = greenCoefficients.getLevel(level);
		const float* bPtr = blueCoefficients.getLevel(level);
		vcg::Point3f* temp = new vcg::Point3f[mipMapSize[level].width()*mipMapSize[level].height()];
		if (cb != NULL) (*cb)(75 + level*6, "Normal generation...");

		#pragma omp parallel for
		for (int y = 0; y < mipMapSize[level].height(); y++)
		{
			for (int x = 0; x < mipMapSize[level].width(); x++)
			{
				int offset= y * mipMapSize[level].width() + x;
				Eigen::Vector3d f(0, 0, 0);
				for (int k = 0; k < ordlen; k++)
				{
					f(0) += rPtr[offset*ordlen + k] * hweights0[k];
					f(1) += rPtr[offset*ordlen + k] * hweights1[k];
					f(2) += rPtr[offset*ordlen + k] * hweights2[k];
				}
				for (int k = 0; k < ordlen; k++)
				{
					f(0) += gPtr[offset*ordlen + k] * hweights0[k];
					f(1) += gPtr[offset*ordlen + k] * hweights1[k];
					f(2) += gPtr[offset*ordlen + k] * hweights2[k];
				}
				for (int k = 0; k < ordlen; k++)
				{
					f(0) += bPtr[offset*ordlen + k] * hweights0[k];
					f(1) += bPtr[offset*ordlen + k] * hweights1[k];
					f(2) += bPtr[offset*ordlen + k] * hweights2[k];
				}
				f /= 3.0;
				Eigen::Vector3d normal = LInverse * f;
				temp[offset] = vcg::Point3f(normal(0), normal(1), normal(2));
				temp[offset].Normalize();
			}
		}
		normals.setLevel(temp, mipMapSize[level].width()*mipMapSize[level].height(), level);
	}
	

	return 0;

}
Esempio n. 2
0
void SpecularEnhancement::applyHSH(const PyramidCoeffF& redCoeff, const PyramidCoeffF& greenCoeff, const PyramidCoeffF& blueCoeff, const QSize* mipMapSize, const PyramidNormals& normals, const RenderingInfo& info, unsigned char* buffer)
{
	const float* redPtr = redCoeff.getLevel(info.level);
	const float* greenPtr = greenCoeff.getLevel(info.level);
	const float* bluePtr = blueCoeff.getLevel(info.level);
	const vcg::Point3f* normalsPtr = normals.getLevel(info.level);
	int tempW = mipMapSize[info.level].width();
    float hweights[9];
	vcg::Point3d temp(info.light.X(), info.light.Y(), info.light.Z());
	temp.Normalize();
	float phi = atan2(temp.Y(), temp.X());
	if (phi<0) 
		phi = 2*M_PI+phi;
    float theta = qMin<float>(acos(temp.Z()/temp.Norm()), M_PI / 2 - 0.04);

	//int offsetBuf = 0;
	getHSH(theta, phi, hweights, sqrt((float)info.ordlen));
	
	#pragma omp parallel for schedule(static,CHUNK) 
	for (int y = info.offy; y < info.offy + info.height; y++)
	{
		int offsetBuf = (y-info.offy)*info.width*4;
		int offset= y * tempW + info.offx;
		for (int x = info.offx; x < info.offx + info.width; x++)
		{
            float red = 0, green = 0, blue = 0;
			int offset2 = offset * info.ordlen;
			for (int k = 0; k < info.ordlen; k++)
			{
				int offset3 = offset2 + k;
				red += redPtr[offset3] * hweights[k];
				green += greenPtr[offset3] * hweights[k];
				blue += bluePtr[offset3] * hweights[k];
			}
			red *= 256;
			green *= 256;
			blue *= 256;

            vcg::Point3f h(0.0f, 0.0f, 1.0f);
			h += info.light;
            h /= 2.0f;
			h.Normalize();

            float nDotH = h * normalsPtr[offset];
			if (nDotH < 0) 
				nDotH = 0.0;
            else if (nDotH > 1.0f)
				nDotH = 1.0;
            nDotH = pow(nDotH, exp/5.0f);

            float temp = (red + green + blue)/3;
            float lum =  temp * ks * 4.0f * nDotH;
			buffer[offsetBuf + 0] = tobyte( red * kd + lum);
			buffer[offsetBuf + 1] = tobyte( green * kd + lum );
			buffer[offsetBuf + 2] = tobyte( blue * kd + lum );
            buffer[offsetBuf + 3] = 0xff;
			offsetBuf += 4;
			offset++;
		}
	}


}