static RAD_Model RAD_ReadFile( const char *filename )
	// Read radiosity solution model from input file.
	// The axis-aligned bounding box is computed.
{
	char badFile[] = "Invalid input model file";

	// Open input file
	FILE *fp = fopen( filename, "r" );
	if ( fp == NULL ) 
		ShowFatalError( __FILE__, __LINE__, "Cannot open input model file \"%s\"", filename );

	RAD_Model m;

	if ( fscanf( fp, "%d", &(m.numQuads) ) != 1 || m.numQuads < 0 )
		ShowFatalError( __FILE__, __LINE__, "%s \"%s\"", badFile, filename );

	m.quads = (RAD_Quad *) CheckedMalloc( sizeof(RAD_Quad) * m.numQuads );

	float minIntensity = FLT_MAX;
	float maxIntensity = 0.0f;
	float max_rgb[3] = { 0.0f, 0.0f, 0.0f };

	for ( int q = 0; q < m.numQuads; q++ )
	{
		for ( int i = 0; i < 4; i++ )
		{
			float vert[3], rgb[3];

			if ( fscanf( fp, "%f %f %f", &vert[0], &vert[1], &vert[2] ) != 3 )
				ShowFatalError( __FILE__, __LINE__, "%s \"%s\"", badFile, filename );

			if ( fscanf( fp, "%f %f %f", &rgb[0], &rgb[1], &rgb[2] ) != 3 )
				ShowFatalError( __FILE__, __LINE__, "%s \"%s\"", badFile, filename );

			CopyArray3( m.quads[q].v[i], vert );
			CopyArray3( m.quads[q].rgb[i], rgb );

			float intensity = rgb[0] + rgb[1] + rgb[2];
			if ( intensity > maxIntensity ) maxIntensity = intensity;
			if ( intensity < minIntensity ) minIntensity = intensity;
			if ( rgb[0] > max_rgb[0] ) max_rgb[0] = rgb[0];
			if ( rgb[1] > max_rgb[1] ) max_rgb[1] = rgb[1];
			if ( rgb[2] > max_rgb[2] ) max_rgb[2] = rgb[2];
		}
	}

	fclose( fp );
	m.minIntensity = minIntensity;
	m.maxIntensity = maxIntensity;
	CopyArray3( m.max_rgb, max_rgb );
	ComputeBoundingBox( &m );
	return m;
}
示例#2
0
文件: quadmodel.cpp 项目: 9gix/cg
void QM_SurfaceInit( QM_Surface *s )
{
	if ( s == NULL ) return;
	CopyArray3( s->reflectivity, ZERO_VEC_3F );
	CopyArray3( s->emission, ZERO_VEC_3F );

	s->numOrigQuads = 0;
	s->origQuads = NULL;
	s->numShooterQuads = 0;
	s->shooters = NULL;
	s->numGathererQuads = 0;
	s->gatherers = NULL;
}
示例#3
0
文件: quadmodel.cpp 项目: 9gix/cg
void QM_ModelInit( QM_Model *m )
{
	if ( m == NULL ) return;
	m->numSurfaces = 0;
	m->surfaces = NULL;
	m->totalShooters = 0;
	m->shooters = NULL;
	m->totalGatherers = 0;
	m->gatherers = NULL;

	CopyArray3( m->min_xyz, ZERO_VEC_3F );
	CopyArray3( m->max_xyz, ZERO_VEC_3F );
	CopyArray3( m->dim_xyz, ZERO_VEC_3F );
	CopyArray3( m->center, ZERO_VEC_3F );
	m->radius = 0.0f;
}
示例#4
0
文件: quadsviewer.cpp 项目: 9gix/cg
static GLuint MakeGathererQuadsDisplayList( const QM_Model *m )
{
	GLuint dlist = glGenLists( 1 );
	if ( dlist == 0 ) ShowFatalError( __FILE__, __LINE__, "Cannot create display list" );
	glNewList( dlist, GL_COMPILE );

		for ( int s = 0; s < m->numSurfaces; s++ )
		{
			float am[4], di[4], sp[4], em[4], shininess = 32.0;
			CopyArray3( am, m->surfaces[s].reflectivity ); am[3] = 1.0f;
			CopyArray3( di, m->surfaces[s].reflectivity ); di[3] = 1.0f;
			CopyArray3( em, m->surfaces[s].emission ); em[3] = 1.0f;
			sp[0] = sp[1] = sp[2] = sp[3] = 0.5f;

			glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT, am );
			glMaterialfv( GL_FRONT_AND_BACK, GL_DIFFUSE, di );
			glMaterialfv( GL_FRONT_AND_BACK, GL_SPECULAR, sp );
			glMaterialfv( GL_FRONT_AND_BACK, GL_EMISSION, em );
			glMaterialf( GL_FRONT_AND_BACK, GL_SHININESS, shininess );

			glBegin( GL_QUADS );
				for ( int q = 0; q < m->surfaces[s].numGathererQuads; q++ )
				{
					QM_GathererQuad *quad = &(m->surfaces[s].gatherers[q]);

					glNormal3fv( quad->normal );
					glVertex3fv( quad->v[0] );
					glVertex3fv( quad->v[1] );
					glVertex3fv( quad->v[2] );
					glVertex3fv( quad->v[3] );
				}
			glEnd();
		}

	glEndList();
	return dlist;
}
示例#5
0
文件: quadmodel.cpp 项目: 9gix/cg
void QM_ComputeVertexRadiosities( QM_Model *m )
	// Compute the radiosities at the vertices by averaging 
	// the radiosities of the quads that use the vertex.
{
	if ( m == NULL || m->numSurfaces <= 0 ) return;

	for ( int s = 0; s < m->numSurfaces; s++ )
	{
		QM_Surface *surface = &(m->surfaces[s]);

		for ( int g = 0; g < surface->numGathererQuads; g++ )
		{
			QM_GathererQuad *gatherer = &(surface->gatherers[g]);

			for ( int i = 0; i < 4; i++ )
			{
				int numQuadsUsingVertex = 0;
				CopyArray3( gatherer->vRadiosity[i], ZERO_VEC_3F );

				for ( int g2 = 0; g2 < surface->numGathererQuads; g2++ )
				{
					QM_GathererQuad *gatherer2 = &(surface->gatherers[g2]);

					for ( int i2 = 0; i2 < 4; i2++ )
					{
						float sqrDist = VecSqrDist( gatherer->v[i], gatherer2->v[i2] );
						if ( sqrDist <= EQUAL_VERTEX_THRESHOLD )
						{
							gatherer->vRadiosity[i][0] += gatherer2->radiosity[0];
							gatherer->vRadiosity[i][1] += gatherer2->radiosity[1];
							gatherer->vRadiosity[i][2] += gatherer2->radiosity[2];
							numQuadsUsingVertex++;
						}
					}
				}

				gatherer->vRadiosity[i][0] /= numQuadsUsingVertex;
				gatherer->vRadiosity[i][1] /= numQuadsUsingVertex;
				gatherer->vRadiosity[i][2] /= numQuadsUsingVertex;
			}
		}
	}
}
示例#6
0
文件: quadmodel.cpp 项目: 9gix/cg
void QM_Subdivide( QM_Model *m, float maxShooterQuadEdgeLength, float maxGathererQuadEdgeLength )
	// Subdivide the original quads in the model to smaller
	// shooter quads and even-smaller gatherer quads.
	// Each shooter quad cannot have edge longer than maxShooterQuadEdgeLength, and
	// each gatherer quad cannot have edge longer than maxGathererQuadEdgeLength.
{
	if ( m == NULL || m->numSurfaces <= 0 ) return;

// Subdivide original quads to get shooter quads.

	int modelTotalShooters = 0;		// This will contain the total number of shooter quads in model.

	for ( int s = 0; s < m->numSurfaces; s++ )
	{
		QM_Surface *surface = &(m->surfaces[s]);

		// Find longest edge length of all original quads in the current surface.
		float maxEdgeLen = 0.0f;
		for ( int q = 0; q < surface->numOrigQuads; q++ )
		{
			QM_OrigQuad *origQuad = &(surface->origQuads[q]);
			float edgeLen;
			edgeLen = VecDist( origQuad->v[0], origQuad->v[1] );
			if ( edgeLen > maxEdgeLen ) maxEdgeLen = edgeLen;
			edgeLen = VecDist( origQuad->v[1], origQuad->v[2] );
			if ( edgeLen > maxEdgeLen ) maxEdgeLen = edgeLen;
			edgeLen = VecDist( origQuad->v[2], origQuad->v[3] );
			if ( edgeLen > maxEdgeLen ) maxEdgeLen = edgeLen;
			edgeLen = VecDist( origQuad->v[3], origQuad->v[0] );
			if ( edgeLen > maxEdgeLen ) maxEdgeLen = edgeLen;
		}

		// Compute how many regular segments to divide the longest edge into so that 
		// every resulting segment is not longer than maxShooterQuadEdgeLength.
		int numSegments = (int) ceil( maxEdgeLen / maxShooterQuadEdgeLength );

		// Each original quad on the current surface is going to be subdivided into
		// (numSegments*numSegments) shooter quads.
		// Therefore, the total number of shooter quads for this surface is...
		surface->numShooterQuads = surface->numOrigQuads * numSegments * numSegments;

		surface->shooters = (QM_ShooterQuad *) CheckedMalloc( sizeof(QM_ShooterQuad) * surface->numShooterQuads );
		int surfShootersCount = 0;  // This will contain the number of shooters in this surface.

		for ( int q = 0; q < surface->numOrigQuads; q++ )
		{
			QM_OrigQuad *origQuad = &(surface->origQuads[q]);

			for ( int y = 0; y < numSegments; y++ )
				for ( int x = 0; x < numSegments; x++ )
				{
					float newv[4][3];
					QuadBilinearInterpolate( newv[0], (float) x / numSegments, (float) y / numSegments, origQuad->v );
					QuadBilinearInterpolate( newv[1], (float) (x+1) / numSegments, (float) y / numSegments, origQuad->v );
					QuadBilinearInterpolate( newv[2], (float) (x+1) / numSegments, (float) (y+1) / numSegments, origQuad->v );
					QuadBilinearInterpolate( newv[3], (float) x / numSegments, (float) (y+1) / numSegments, origQuad->v );

					QM_ShooterQuad *shooterQuad = &(surface->shooters[ surfShootersCount ]);
					for ( int i = 0; i < 4; i++ ) CopyArray3( shooterQuad->v[i], newv[i] );
					QuadCentroid( shooterQuad->centroid, shooterQuad->v );
					CopyArray3( shooterQuad->normal, origQuad->normal );
					shooterQuad->area = QuadArea( shooterQuad->v );

					// Initialize the unshot power of the shooter quad.
					shooterQuad->unshotPower[0] = surface->emission[0] * shooterQuad->area;
					shooterQuad->unshotPower[1] = surface->emission[1] * shooterQuad->area;
					shooterQuad->unshotPower[2] = surface->emission[2] * shooterQuad->area;

					shooterQuad->surface = surface;
					surfShootersCount++;
					modelTotalShooters++;
				}
		}
	}


	// Build an array of pointers to all the shooters in the model.
	m->totalShooters = modelTotalShooters;
	m->shooters = (QM_ShooterQuad **) CheckedMalloc( sizeof(QM_ShooterQuad *) * modelTotalShooters );
	int modelTotalShootersCount = 0;

	for ( int s = 0; s < m->numSurfaces; s++ )
		for ( int q = 0; q < m->surfaces[s].numShooterQuads; q++ )
		{
			m->shooters[ modelTotalShootersCount ] = &(m->surfaces[s].shooters[q]);
			modelTotalShootersCount++;
		}



// Subdivide shooter quads to get gatherer quads.

	int modelTotalGatherers = 0;		// This will contain the total number of gatherers quads in model.

	for ( int s = 0; s < m->numSurfaces; s++ )
	{
		QM_Surface *surface = &(m->surfaces[s]);

		// Find longest edge length of all shooter quads in the current surface.
		float maxEdgeLen = 0.0f;
		for ( int q = 0; q < surface->numShooterQuads; q++ )
		{
			QM_ShooterQuad *shooterQuad = &(surface->shooters[q]);
			float edgeLen;
			edgeLen = VecDist( shooterQuad->v[0], shooterQuad->v[1] );
			if ( edgeLen > maxEdgeLen ) maxEdgeLen = edgeLen;
			edgeLen = VecDist( shooterQuad->v[1], shooterQuad->v[2] );
			if ( edgeLen > maxEdgeLen ) maxEdgeLen = edgeLen;
			edgeLen = VecDist( shooterQuad->v[2], shooterQuad->v[3] );
			if ( edgeLen > maxEdgeLen ) maxEdgeLen = edgeLen;
			edgeLen = VecDist( shooterQuad->v[3], shooterQuad->v[0] );
			if ( edgeLen > maxEdgeLen ) maxEdgeLen = edgeLen;
		}

		// Compute how many regular segments to divide the longest edge into so that 
		// every resulting segment is not longer than maxGathererQuadEdgeLength.
		int numSegments = (int) ceil( maxEdgeLen / maxGathererQuadEdgeLength );

		// Each shooter quad on the current surface is going to be subdivided into
		// (numSegments*numSegments) gatherer quads.
		// Therefore, the total number of gatherer quads for this surface is...
		surface->numGathererQuads = surface->numShooterQuads * numSegments * numSegments;

		surface->gatherers = (QM_GathererQuad *) CheckedMalloc( sizeof(QM_GathererQuad) * surface->numGathererQuads );
		int surfGatherersCount = 0;  // This will contain the number of gatherers in this surface.

		for ( int q = 0; q < surface->numShooterQuads; q++ )
		{
			QM_ShooterQuad *shooterQuad = &(surface->shooters[q]);

			for ( int y = 0; y < numSegments; y++ )
				for ( int x = 0; x < numSegments; x++ )
				{
					float newv[4][3];
					QuadBilinearInterpolate( newv[0], (float) x / numSegments, (float) y / numSegments, shooterQuad->v );
					QuadBilinearInterpolate( newv[1], (float) (x+1) / numSegments, (float) y / numSegments, shooterQuad->v );
					QuadBilinearInterpolate( newv[2], (float) (x+1) / numSegments, (float) (y+1) / numSegments, shooterQuad->v );
					QuadBilinearInterpolate( newv[3], (float) x / numSegments, (float) (y+1) / numSegments, shooterQuad->v );

					QM_GathererQuad *gathererQuad = &(surface->gatherers[ surfGatherersCount ]);
					for ( int i = 0; i < 4; i++ ) CopyArray3( gathererQuad->v[i], newv[i] );
					CopyArray3( gathererQuad->normal, shooterQuad->normal );
					gathererQuad->area = QuadArea( gathererQuad->v );

					// Initialize the radiosity of the gatherer quad.
					gathererQuad->radiosity[0] = surface->emission[0];
					gathererQuad->radiosity[1] = surface->emission[1];
					gathererQuad->radiosity[2] = surface->emission[2];

					CopyArray3( gathererQuad->vRadiosity[0], ZERO_VEC_3F );
					CopyArray3( gathererQuad->vRadiosity[1], ZERO_VEC_3F );
					CopyArray3( gathererQuad->vRadiosity[2], ZERO_VEC_3F );
					CopyArray3( gathererQuad->vRadiosity[3], ZERO_VEC_3F );

					gathererQuad->shooter = shooterQuad;
					gathererQuad->surface = surface;
					surfGatherersCount++;
					modelTotalGatherers++;
				}
		}
	}


	// Build an array of pointers to all the gatherers in the model.
	m->totalGatherers = modelTotalGatherers;
	m->gatherers = (QM_GathererQuad **) CheckedMalloc( sizeof(QM_GathererQuad *) * modelTotalGatherers );
	int modelTotalGatherersCount = 0;

	for ( int s = 0; s < m->numSurfaces; s++ )
		for ( int q = 0; q < m->surfaces[s].numGathererQuads; q++ )
		{
			m->gatherers[ modelTotalGatherersCount ] = &(m->surfaces[s].gatherers[q]);
			modelTotalGatherersCount++;
		}

	return;
}
示例#7
0
文件: quadmodel.cpp 项目: 9gix/cg
QM_Model QM_ReadFile( const char *filename )
	// Read model from input file.
	// The output QM_Model has only QM_OrigQuad.
	// The axis-aligned bounding box is computed.
{
	char badFile[] = "Invalid input model file";
	char badEOF[] = "Unexpected end of file";
	char lineBuf[ MAX_LINE_LEN + 1 ];

	// Open input file
	FILE *fp = fopen( filename, "r" );
	if ( fp == NULL ) 
		ShowFatalError( __FILE__, __LINE__, "Cannot open input model file \"%s\"", filename );

	int lineNum = 0;

//=== VERTICES ===

	int numVertices = 0;
	float *vertexTable = NULL;  // An array of 3D vertices.

	// Read number of vertices.
	if ( !ReadDataLine( lineBuf, &lineNum, filename, fp ) )
		ShowFatalError( __FILE__, __LINE__, "%s \"%s\"", badEOF, filename );

	if ( sscanf( lineBuf, "%d", &numVertices ) != 1  ||  numVertices < 0 )
		ShowFatalError( __FILE__, __LINE__, "%s \"%s\" at line %d", badFile, filename, lineNum );

	vertexTable = (float *) CheckedMalloc( sizeof(float) * 3 * numVertices );

	// Read the vertices.
	for ( int v = 0; v < numVertices; v++ )
	{
		float x, y, z;

		if ( !ReadDataLine( lineBuf, &lineNum, filename, fp ) )
			ShowFatalError( __FILE__, __LINE__, "%s \"%s\"", badEOF, filename );

		if ( sscanf( lineBuf, "%f %f %f", &x, &y, &z ) != 3 )
			ShowFatalError( __FILE__, __LINE__, "%s \"%s\" at line %d", badFile, filename, lineNum );

		vertexTable[ 3 * v + 0 ] = x;
		vertexTable[ 3 * v + 1 ] = y;
		vertexTable[ 3 * v + 2 ] = z;
	}


//=== MATERIALS ===

	int numMaterials = 0;
	float *reflectivityTable = NULL;	// An array of RGB reflectivity values.
	float *emissionTable = NULL;		// An array of RGB emission values.

	// Read number of materials.
	if ( !ReadDataLine( lineBuf, &lineNum, filename, fp ) )
		ShowFatalError( __FILE__, __LINE__, "%s \"%s\"", badEOF, filename );

	if ( sscanf( lineBuf, "%d", &numMaterials ) != 1  ||  numMaterials < 0 )
		ShowFatalError( __FILE__, __LINE__, "%s \"%s\" at line %d", badFile, filename, lineNum );

	reflectivityTable = (float *) CheckedMalloc( sizeof(float) * 3 * numMaterials );
	emissionTable = (float *) CheckedMalloc( sizeof(float) * 3 * numMaterials );

	// Read the materials.
	for ( int m = 0; m < numMaterials; m++ )
	{
		float r, g, b;

		if ( !ReadDataLine( lineBuf, &lineNum, filename, fp ) )
			ShowFatalError( __FILE__, __LINE__, "%s \"%s\"", badEOF, filename );

		if ( sscanf( lineBuf, "%f %f %f", &r, &g, &b ) != 3 )
			ShowFatalError( __FILE__, __LINE__, "%s \"%s\" at line %d", badFile, filename, lineNum );

		reflectivityTable[ 3 * m + 0 ] = r;
		reflectivityTable[ 3 * m + 1 ] = g;
		reflectivityTable[ 3 * m + 2 ] = b;

		if ( !ReadDataLine( lineBuf, &lineNum, filename, fp ) )
			ShowFatalError( __FILE__, __LINE__, "%s \"%s\"", badEOF, filename );

		if ( sscanf( lineBuf, "%f %f %f", &r, &g, &b ) != 3 )
			ShowFatalError( __FILE__, __LINE__, "%s \"%s\" at line %d", badFile, filename, lineNum );

		emissionTable[ 3 * m + 0 ] = r;
		emissionTable[ 3 * m + 1 ] = g;
		emissionTable[ 3 * m + 2 ] = b;
	}


//=== SURFACES ===

	int numSurfaces = 0;
	QM_Surface *surfaceTable = NULL;	// An array of surfaces.

	// Read number of surfaces.
	if ( !ReadDataLine( lineBuf, &lineNum, filename, fp ) )
		ShowFatalError( __FILE__, __LINE__, "%s \"%s\"", badEOF, filename );

	if ( sscanf( lineBuf, "%d", &numSurfaces ) != 1  ||  numSurfaces < 0 )
		ShowFatalError( __FILE__, __LINE__, "%s \"%s\" at line %d", badFile, filename, lineNum );

	surfaceTable = (QM_Surface *) CheckedMalloc( sizeof(QM_Surface) * numSurfaces );

	// Read the surfaces.
	for ( int s = 0; s < numSurfaces; s++ )
	{
		QM_SurfaceInit( &surfaceTable[s] );

		int matID, numQuads;

		// Read material index.
		if ( !ReadDataLine( lineBuf, &lineNum, filename, fp ) )
			ShowFatalError( __FILE__, __LINE__, "%s \"%s\"", badEOF, filename );

		if ( sscanf( lineBuf, "%d", &matID ) != 1  ||  matID < 0 || matID >= numMaterials )
			ShowFatalError( __FILE__, __LINE__, "%s \"%s\" at line %d", badFile, filename, lineNum );

		CopyArray3( surfaceTable[s].reflectivity, &reflectivityTable[3*matID] );
		CopyArray3( surfaceTable[s].emission, &emissionTable[3*matID] );

		// Read number of quadrilaterals in the surface.
		if ( !ReadDataLine( lineBuf, &lineNum, filename, fp ) )
			ShowFatalError( __FILE__, __LINE__, "%s \"%s\"", badEOF, filename );

		if ( sscanf( lineBuf, "%d", &numQuads ) != 1  ||  numQuads < 0 )
			ShowFatalError( __FILE__, __LINE__, "%s \"%s\" at line %d", badFile, filename, lineNum );

		surfaceTable[s].numOrigQuads = numQuads;
		surfaceTable[s].origQuads = (QM_OrigQuad *) CheckedMalloc( sizeof(QM_OrigQuad) * numQuads );

		// Read vertex indices for each quadrilateral.
		for ( int q = 0; q < numQuads; q++ )
		{
			int vertID[4];

			if ( !ReadDataLine( lineBuf, &lineNum, filename, fp ) )
				ShowFatalError( __FILE__, __LINE__, "%s \"%s\"", badEOF, filename );

			if ( sscanf( lineBuf, "%d %d %d %d", &vertID[0], &vertID[1], &vertID[2], &vertID[3] ) != 4 || 
				 vertID[0] < 0 || vertID[0] >= numVertices || vertID[1] < 0 || vertID[1] >= numVertices ||
				 vertID[2] < 0 || vertID[2] >= numVertices || vertID[3] < 0 || vertID[3] >= numVertices )
				ShowFatalError( __FILE__, __LINE__, "%s \"%s\" at line %d", badFile, filename, lineNum );

			CopyArray3( surfaceTable[s].origQuads[q].v[0], &vertexTable[ 3*vertID[0] ] );
			CopyArray3( surfaceTable[s].origQuads[q].v[1], &vertexTable[ 3*vertID[1] ] );
			CopyArray3( surfaceTable[s].origQuads[q].v[2], &vertexTable[ 3*vertID[2] ] );
			CopyArray3( surfaceTable[s].origQuads[q].v[3], &vertexTable[ 3*vertID[3] ] );

			// Compute normal vector to the quadrilateral.
			VecTriNormal( surfaceTable[s].origQuads[q].normal, 
				          surfaceTable[s].origQuads[q].v[0], 
						  surfaceTable[s].origQuads[q].v[1], 
						  surfaceTable[s].origQuads[q].v[2] );
			VecNormalize( surfaceTable[s].origQuads[q].normal, surfaceTable[s].origQuads[q].normal );
		}
	}

	QM_Model model = QM_ModelInit();
	model.numSurfaces = numSurfaces;
	model.surfaces = surfaceTable;
	ComputeBoundingBox( &model );

	fclose( fp );
	free( vertexTable );
	free( reflectivityTable );
	free( emissionTable );
	return model;
}