⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gribparser.cpp

📁 一个非常有用的开源代码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
	{		fprintf(stderr, "Not enough arguments to PointsGeneralPolygons, needs at least 6, got %d\n", data.size() - 1);		//data.debugPrint( cerr, 3 );		return false;	}	if ( data.hasOptionalArg( "P" ) )		homogeneous = false;	else if ( data.hasOptionalArg( "Pw" ) )		homogeneous = true;	else	{		fprintf(stderr, "Doesn't have points or homogeneous points - skipping\n");		//data.debugPrint( cerr, 3 );		return false;	}	npolys = data[1].size();	nvertices.reserve( npolys );	vertex_indices.resize( npolys );	uint sum_idx = 0;	for ( ipoly = 0; ipoly < npolys; ipoly++ )	{		if ( data[1].intVal( ipoly ) != 1 )		{			fprintf(stderr, "I only handle polys with a single loop.\n");			//data.debugPrint( cerr, 3 );			return false;		}		int nvertices_temp = data[2].intVal( ipoly );		nvertices.push_back( nvertices_temp );		vertex_indices[ ipoly ].reserve( nvertices_temp );		for ( uint ivtx = sum_idx; ivtx < sum_idx + nvertices_temp; ivtx++ )		{			vertex_indices[ ipoly ].push_back( data[3].intVal( ivtx ) );		}		sum_idx += nvertices_temp;	}	// Get geometry of points	const RibData& points_arg = data.findOptionalArg( homogeneous ? "Pw" : "P" );	npoints = points_arg.size();	if ( homogeneous )		npoints /= 4;	else		npoints /= 3;	points = new double[ npoints * 4 ];	if ( homogeneous )	{		for ( ipt = 0; ipt < npoints; ipt++ )		{			points[ ipt*4 + 0 ] = points_arg.doubleVal( ipt*4 + 0 );			points[ ipt*4 + 1 ] = points_arg.doubleVal( ipt*4 + 1 );			points[ ipt*4 + 2 ] = points_arg.doubleVal( ipt*4 + 2 );			points[ ipt*4 + 3 ] = points_arg.doubleVal( ipt*4 + 3 );		}	}	else	{		for ( ipt = 0; ipt < npoints; ipt++ )		{			points[ ipt*4 + 0 ] = points_arg.doubleVal( ipt*3 + 0 );			points[ ipt*4 + 1 ] = points_arg.doubleVal( ipt*3 + 1 );			points[ ipt*4 + 2 ] = points_arg.doubleVal( ipt*3 + 2 );			points[ ipt*4 + 3 ] = 1.0;		}	}	// Get normals	if ( data.hasOptionalArg( "N" ) )	{		const RibData& normals_arg = data.findOptionalArg( "N" );		uint total_size = normals_arg.size();		nnormals = total_size / 3; // 3 components per normal		normals = new double[ total_size ];		for ( uint inormal = 0; inormal < total_size; inormal++ )		{			normals[ inormal ] = normals_arg.doubleVal( inormal );		}	}	// Get texture coordinates	if ( data.hasOptionalArg( "st" ) )	{		const RibData& texcoords_arg = data.findOptionalArg( "st" );		uint total_size = texcoords_arg.size();		ntexcoords = total_size / 2; // 2 components per texture coordinate		texcoords = new double[ total_size ];		for ( uint ist = 0; ist < total_size; ist++ )		{			texcoords[ ist ] = texcoords_arg.doubleVal( ist );		}	}	// Transform points	double curr_transform[16];	getObjectTransform( curr_transform );	for ( ipt = 0; ipt < npoints; ipt++ )	{		double *curr_pt = &points[ ipt*4 ];		matrixMultiplyPoint( curr_pt, curr_transform, curr_pt );	}	// There are a couple of different ways of storing a polygonal mesh.	// We've implemented a subset of Renderman's pointsGeneralPolygons command.	// The basic idea is that you have an array of loops, an array of the number of vertices in each loop,	//     an array of those vertices, and then the data for the vertices.	// The data consists of points, and then optionally normals and texture coordinates.	// The index for a given vertex is the same for vertices, points, and texture coordinates, so a single vertex only has one normal	// However, they compensate for that by just duplicating data, if needed.	//	// On to what you'll actually need to do.	//	// The data you'll need is stored in the following variables:	//	// npolys: The number of polygons	// npoints: The number of points	// nnormals: The number of normals	// ntexcoords: The number of texture coordinates	// nvertices: An array of size npolys.  Tells how many vertices each polygon has.	// vertex_indices: A 2d array of size [(npolys)][(nvertices[npolys])].	//                 This keeps track of the indices of the vertices around a polygon	//                 For example, vertex_indices[ 5 ][ 2 ] would be the vertex 2 on polygon 5.	// points: An array of doubles, 4 for each point (whether the points were specified homogeneously or not)	// normals: An array of doubles, 3 for each point, if normals are provided for this polyMesh.  If not, you should compute face normals.	// texcoords: An array of doubles, 2 for each point.	// homogeneous: A boolean, telling you whether you need to use homogeneous coordinates or not.	//              You might be able to get some speed out of not dividing out w, especially for large meshes.	//              In the sample files for the class, none of them are homogeneous, so this is only really for loading other files.	//        GRayTraceMaterial *material = getMaterial();        GRayTraceTriMesh *mesh = new GRayTraceTriMesh(material, npoints, npolys, nnormals, ntexcoords);	// Points	GRayTraceVector v;	for (ipt = 0; ipt < npoints; ipt++)	{		v.m_vals[0] = points[ipt * 4];		v.m_vals[1] = points[ipt * 4 + 1];		v.m_vals[2] = points[ipt * 4 + 2];	        mesh->SetPoint(ipt, &v);	}	// Normals	for (ipt = 0; ipt < nnormals; ipt++)	{		v.m_vals[0] = normals[ipt * 3];		v.m_vals[1] = normals[ipt * 3 + 1];		v.m_vals[2] = normals[ipt * 3 + 2];	        mesh->SetNormal(ipt, &v);	}	// Texture coords	for (ipt = 0; ipt < ntexcoords; ipt++)	    mesh->SetTextureCoord(ipt, texcoords[ipt * 2], texcoords[ipt * 2 + 1]);	// Triangles	for(ipoly = 0; ipoly < npolys; ipoly++ ) 	{                vector< uint > & idx = vertex_indices[ ipoly ];		mesh->SetTriangle(ipoly, idx[0], idx[1], idx[2]);	}        // Add to the scene        m_pScene->AddMesh( mesh );	if(material)	{		GRayTraceColor* pEmissive = material->GetColor(GRayTraceMaterial::Emissive, NULL);		if (!pEmissive->IsBlack() )		{			for(ipoly = 0; ipoly < npolys; ipoly++)			{				GRayTraceTriangle* pTriangle = new GRayTraceTriangle(mesh, ipoly);				m_pScene->AddObject(pTriangle); // This is a duplicate object of the one the mesh added				GRayTraceAreaLight* pAreaLight = new GRayTraceAreaLight(pTriangle, pEmissive->r, pEmissive->g, pEmissive->b);				m_pScene->AddLight( pAreaLight );			}		}	}	// Clean up the allocated memory.	if ( points != NULL )		delete[] points;	if ( normals != NULL )		delete[] normals;	if ( texcoords != NULL )		delete[] texcoords;	return true;}bool RibParser::handleAreaLightSource( const RibData& data ){	// The default emissive color is white for any area light source	double emissive_color[ 4 ] = { 1, 1, 1, 1 };	if ( data.size() < 3 )	{		fprintf(stderr, "Bad number of arguments to AreaLightSource.  Requires at least 1, has %d\n", data.size() - 1);		//data.debugPrint( cerr, 3 );		return false;	}	else	{		if ( data.hasOptionalArg( "lightcolor" ) )			data.fillDoubleArrayFromOptionalArg( "lightcolor", emissive_color, 3 );		// Set the emissive color in the appropriate state block(s)		int i = state.size() - 1;		do {			for ( uint j = 0; j < 3; j++ )				state[ i ].emissive_color[ j ] = emissive_color[ j ];			i--;		} while ( state[ i ].type == StateBlock::TRANSFORMBLOCK && i > 0 );		//       In project 4 we do geometry light sources.		//       The basic idea is just setting the emissive on the material.		//       We do it with the AreaLightSource command, for more compatibility with how		//       real-world RIBs do it.		//		//       You'll need to replace this with your own material class.		// Make a copy of the current material, replace the emissive color, and set		GRayTraceMaterial* new_material = new GRayTraceMaterial(getMaterial());		new_material->SetColor( GRayTraceMaterial::Emissive, emissive_color[0], emissive_color[1], emissive_color[2] );		// Add the material to the scene, so it'll be deleted properly		m_pScene->AddMaterial( new_material );		// Set the current material on the parser state		setMaterial( new_material );		return true;	}}void RibParser::pushState( int block_type ){	state.push_back( StateBlock( block_type, state.back() ) );	if ( block_type == StateBlock::WORLDBLOCK )	{		// Move the object transform to the camera transform, and clear the object transform.		double transform[16];		getObjectTransform( transform );		setCameraTransform( transform );		matrixMakeIdentity( transform );		setObjectTransform( transform );	}}void RibParser::popState( int block_type ){	if ( state.back().getType() != block_type )		fprintf(stderr, "Block error: Mismatched block types: %d terminated by %d\n", state.back().getType(), block_type);	// If we're about to pop the world block, create a camera.	if ( state.back().getType() == StateBlock::WORLDBLOCK )	{		// These variables record the type of render requested, for easy construction of the camera.		bool ray_tracing_camera = false, path_tracing_camera = false;		// Will be made the default camera in the scene.		GRayTraceCamera *camera = NULL;		// Camera parameters: Samples per pixel, ray recursion depth, and tone mapping constant		int ray_depth;//		double tone_mapping_constant;		double from[4] = { 0, 0, 0, 1 };		double to[4] = { 0, 0, 1, 1 }; // This 'to' point isn't what you'd expect,		                               // but it allows us to change the handedness easily.		double up[4] = { 0, 1, 0, 1 };		double transform[16];  // Camera to world transform.		getCameraTransform( transform );		double inverted[16];		if ( !matrixInvert( inverted, transform ) )		{			fprintf(stderr, "Transform matrix wasn't invertible.  Expect weird behavior\n");		}		matrixMultiplyPoint( from, inverted, from );		matrixMultiplyPoint( to, inverted, to );		matrixMultiplyPoint( up, inverted, up );		// Change up point to up vector.		for ( uint i = 0; i < 4; i++ )			up[i] = up[i] - from[i];		if ( hasAttribute( "cs655Setting", "renderType" ) )		{			string render_type = getAttribute( "cs655Setting", "renderType" ).stringVal( 0 );			if ( render_type == "rayTracing" )				ray_tracing_camera = true;			else if ( render_type == "pathTracing" )				path_tracing_camera = true;		}		if ( !ray_tracing_camera && !path_tracing_camera )		{			printf("No renderType attribute specified: Assuming ray tracing\n");			ray_tracing_camera = true;		}		// At this point it's either a ray tracing camera, or path tracing.		// Get other attributes common to both cameras		ray_depth = getAttribute( "cs655Setting", "rayDepth" ).intVal( 0 );		camera = m_pScene->GetCamera();		if ( ray_tracing_camera )		{		}		else if ( path_tracing_camera )		{			// Get the tone mapping constant from the attributes.			GRayTraceReal tone_mapping_constant = getAttribute( "cs655Setting", "toneMappingConstant" ).doubleVal( 0 );			m_pScene->SetToneMappingConstant( (GRayTraceReal)tone_mapping_constant );		}		camera->SetRaysPerPixel( pixel_samples );		camera->SetMaxDepth( ray_depth );		camera->SetFocalDistance( focal_distance );		camera->SetLensDiameter( lens_diameter );		camera->GetLookFromPoint()->Set(from[0], from[1], from[2]);		camera->GetLookAtPoint()->Set(to[0], to[1], to[2]);		camera->GetViewUpVector()->Set(up[0], up[1], up[2]);		camera->SetViewAngle(fov);		camera->SetImageSize(image_width, image_height);		//camera->setScene(scene);		//scene->setDefaultCamera(camera);	}	// We'll crash if we remove the root block, so um.. don't.	if ( state.size() == 1 )		fprintf(stderr, "Block error: Too many closing blocks, removing the file block from the stack is invalid.\n");	else		state.pop_back();}void RibParser::setMaterial(GRayTraceMaterial* material){	int i = state.size() - 1;	state[ i ].material = material;	// Transform blocks only catch transforms, so propagate the material until you hit a different block type	while ( state[ i ].type == StateBlock::TRANSFORMBLOCK && i > 0 )	{		--i;		state[ i ].material = material;	}}GRayTraceMaterial* RibParser::getMaterial(){	if ( state.back().material == NULL )	{		// If there is no current material, make and return the default material.#ifdef PARSER_DEBUG		fprintf(stderr, "Material requested, but no material currently defined.  Returning default material.\n");#endif		GRayTraceMaterial *material = new GRayTraceMaterial();		m_pScene->AddMaterial(material);		setMaterial(material);		return material;	}	else	{		return state.back().material;	}}void RibParser::setColor( const double* color ){	StateBlock& block = state.back();	for ( uint i = 0; i < 3; i++ )		block.color[ i ] = color[ i ];}void RibParser::getColor( double *color ){	StateBlock& block = state.back();	for ( uint i = 0; i < 3; i++ )		color[ i ] = block.color[ i ];}void RibParser::setCameraTransform( const double transform[16] ){	for ( uint i = 0; i < 16; i++ )		camera_to_world[ i ] = transform[ i ];}void RibParser::getCameraTransform( double transform[16] ){	for ( uint i = 0; i < 16; i++ )		transform[ i ] = camera_to_world[ i ];}void RibParser::setObjectTransform( const double transform[16] ){	StateBlock& block = state.back();	for ( uint i = 0; i < 16; i++ )		block.transform[ i ] = transform[ i ];}void RibParser::getObjectTransform( double transform[16] ){	StateBlock& block = state.back();	for ( uint i = 0; i < 16; i++ )		transform[ i ] = block.transform[ i ];}void RibParser::multiplyTransform( const double transform[16] ){	matrixMultiply( state.back().transform, state.back().transform, transform );}bool RibParser::hasAttribute( const string& attr_class, const string& attr_name ){	int i = state.size() - 1;	bool success = false;	do {		state[ i ].getAttribute( attr_class, attr_name, success );		if ( success )			return true;		--i;	} while ( i >= 0 );	return false;}RibData& RibParser::getAttribute( const string& attr_class, const string& attr_name ){	bool success = false;	int i = state.size() - 1;	do {		RibData& data = state[ i ].getAttribute( attr_class, attr_name, success );		if ( success )			return data;		--i;	} while ( i >= 0 );	success = false;	return *((RibData*)NULL);}void RibParser::setAttribute( const string& attr_class, const string& attr_name, const RibData& data ){	int i = state.size() - 1;	do {		if ( state[ i ].type != StateBlock::TRANSFORMBLOCK )			break; // This is the one we want, don't decrement any more.		i--;	}	while ( i > 0 ); // If we ever fail this test, we should be at the root block.		// Either at the root, or the topmost non-transform, catch the attribute.	// Since we look up attributes from the top of the stack, 	// this will properly allow shadowing of attribute values	state[ i ].setAttribute( attr_class, attr_name, data );}RibData& RibParser::getObjectDefinition( unsigned int index ){	if ( object_definitions.size() <= index )		object_definitions.resize( index + 1 );	return object_definitions[ index ];}////////////////////// Utility Matrix Functions////////////////////void RibParser::matrixZero( double matrix[16] ){	for ( uint i = 0; i < 16; i++ )		matrix[ i ] = 0;}void RibParser::matrixMakeIdentity( double matrix[16] ){	matrixZero( matrix );	for ( uint i = 0; i < 4; i++ )		matrix[ i * 4 + i ] = 1;}void RibParser::matrixMultiply( double dest[16], const double left[16], const double right[16] ){	uint i;	double temp[16];	matrixZero( temp );	for ( i = 0; i < 4; i++ )		for ( uint j = 0; j < 4; j++ )			for ( uint k = 0; k < 4; k++ )				temp[ i*4 + j ] += left[ k*4 + j ] * right[ i*4 + k ];	// Copy to the dest	for ( i = 0; i < 16; i++ )		dest[ i ] = temp[ i ];}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -