Esempio n. 1
0
void createOrenNayar20(BSDF* bsdf)
{
    Spectrum Kd(1);
    float sigma = 0.0;
    BxDF* bxdf = BSDF_ALLOC(arena, OrenNayar)(Kd, sigma);
    bsdf->Add(bxdf);
}
Esempio n. 2
0
double TStringKernel::KDynamicW(const TIntV& s, const TIntV& t, const TFltV& lc, const TFltV& wgt) {
    int x,y,i;
    const int k = lc.Len() + 1;

    int ls = s.Len(), lt = t.Len();
    TVec<TFltVV> Kd(2);
    // s is on X-axis and t is on Y-axis
    for (i = 0; i < 2; i++) Kd[i].Gen(ls+1, lt+1);

    // initialize Kd for i == 0
    for (x = 0; x <= ls; x++) {
        for (y = 0; y <= lt; y++) {
            Kd[0](x,y) = 1.0;
        }
    }

    // calculate Kd for i == 1..k-1
    double K = 0.0;
    for (i = 1; i < k; i++) {
        for (x = 0; x <=ls; x++) Kd[i%2](x,i-1) = 0.0;
        for (y = 0; y <=lt; y++) Kd[i%2](i-1,y) = 0.0;
    
        double Ki = 0.0;
        for (x = i; x <= ls; x++) {
            double Kdd = 0.0; int u = s[x-1];
            for (y = i; y <= lt; y++) {
                double w = wgt[t[y-1]];
                if (u == t[y-1]) {
                    Kdd = w * (Kdd + wgt[u]*Kd[(i-1)%2](x-1,y-1));
                    Ki += w*w * Kd[i%2](x-1, y-1);
                } else {
                    Kdd *= (1-w); // u is a gap! (w -> (1-w) ?)
                }
                Kd[i%2](x,y) = wgt[u]*Kd[i%2](x-1, y) + Kdd;
            }
        }
        K += lc[i-1] * Ki;
    }

    return K;
}
Esempio n. 3
0
void createLambertian(BSDF* bsdf)
{
    Spectrum Kd(1);
    BxDF* bxdf = BSDF_ALLOC(arena, Lambertian)(Kd);
    bsdf->Add(bxdf);
}
Esempio n. 4
0
//! computes interaction with a ground surface
bool simulation::AerodynamicModelContact::compute(
	AerodynamicForce &aeroForce,
	AerodynamicModelContactState &dynamicState,
	const AerodynamicModelContactControl &control,
	const dynamics::RigidBody &rigidBody,
	const GroundSurface &surface) {

	math::matrix3x1<float> contactLocation = rigidBody.location +
		rigidBody.orientation.rotate(location);

	math::matrix3x1<float> contactVelocity = 
		rigidBody.localParticleVelocity(location);

	aeroForce.lift = math::matrix3x1<float>(0, 0, 0);
	aeroForce.drag = math::matrix3x1<float>(0, 0, 0);
	aeroForce.location = contactLocation;
	aeroForce.velocity = contactVelocity;
	aeroForce.type = AerodynamicForce::Type_invalid;

			
	// first detect if there is a contact, defined as the location of the contact on the opposite
	// side of the surface as the location of the rigidBody center

	math::matrix3x1<float> P = surface.surface.normal() + 
		surface.surface.normal() * surface.surface.intersect(math::matrix3x1<float>::zero(), surface.surface.normal());

	if (signum(surface.surface(contactLocation)) != signum(surface.surface(P))) {

		math::matrix3x1<float> surfaceNorm = surface.surface.normal();
		float t_i = surface.surface.intersect(contactLocation, surfaceNorm);
		math::matrix3x1<float> intersection = t_i * surfaceNorm + contactLocation;

		// project displacement and velocity
		float t_i_dot = surfaceNorm.dot(contactVelocity);
			
		if (impulseType == AerodynamicContactResponse::Force_impulse) {
			if (t_i_dot < 0) {

				math::quaternion<float> orientation = rigidBody.orientation * control.orientation;

				// compute dashpot force
				float forceMagnitude = Ks() * t_i - Kd() * t_i_dot;
				math::matrix3x1<float> normalForce = surfaceNorm * forceMagnitude;

				dynamicState.load = forceMagnitude;

				// compute friction
				math::matrix3x1<float> tangentVelocity = surface.surface.project(contactVelocity);
			
				float frictionRolling = math::lerp<float>(control.brake, friction.rollingCoeff(), friction.dynamicCoeff()) * forceMagnitude;
				float frictionSkidding = friction.dynamicCoeff() * forceMagnitude;
				
				math::matrix3x1<float> tangentForce(0, 0, 0);
				if (tangentVelocity.normsq() > 0.0001f) {

					math::matrix3x1<float> V = tangentVelocity.unit();
					math::matrix3x1<float> F = surface.surface.project(orientation.rotate(math::matrix3x1<float>(0,0,1))).unit();
					math::matrix3x1<float> S = tangentVelocity.cross(surfaceNorm);

					math::matrix3x1<float> rollingFriction = -frictionRolling * (std::abs(V.dot(F))) * V;
					math::matrix3x1<float> skiddingFriction = frictionSkidding * (S.dot(F)) * S.unit();

					tangentForce = rollingFriction + skiddingFriction;

				}
				else {

				}

				// wheels spinning
				dynamicState.angularVelocity = -tangentVelocity.magnitude() / bogeyModel.x;

				// compute netforce
				aeroForce.lift = normalForce;
				aeroForce.drag = tangentForce;
				aeroForce.location = rigidBody.orientation.rotate(location);
				aeroForce.type = AerodynamicForce::Contact_force;

				return true;
			}
		}
		else if (type == AerodynamicContactResponse::Velocity_impulse) {
			// zero the velocity 
		}
	}
	else {
		dynamicState.load = 0;
	}
	return false;
}
Esempio n. 5
0
	int Renderer::preview( const std::string& fileName, const liqPreviewShaderOptions& options )
	{
		CM_TRACE_FUNC("Renderer::preview("<<fileName<<","<<options.shaderNodeName<<")");

		  std::string shaderFileName;
  liqShader currentShader;
  MObject	shaderObj;
  MString shader_type_TempForRefactoring;//  [2/14/2012 yaoyansi]

  if ( options.fullShaderPath ) 
  {
	  // a full shader path was specified
	  //cout <<"[liquid] got full path for preview !"<<endl;
	  //shaderFileName = const_cast<char*>(options.shaderNodeName);

	  std::string tmp( options.shaderNodeName );
	  currentShader.setShaderFileName(tmp.substr( 0, tmp.length() -  4 ) );

	  if ( options.type == "surface" ){
		  assert(0&&"we should use currentShader.shader_type_ex = \"surface\"");
		  //currentShader.shader_type = SHADER_TYPE_SURFACE;//  [2/14/2012 yaoyansi]
		  shader_type_TempForRefactoring = "surface";
	  }else if ( options.type == "displacement" ){
		  assert(0&&"we should use currentShader.shader_type_ex = \"displacement\"");
		  //currentShader.shader_type = SHADER_TYPE_DISPLACEMENT;//  [2/14/2012 yaoyansi]
		  shader_type_TempForRefactoring = "displacement";
	  }
	  //cout <<"[liquid]   options.shaderNodeName = " << options.shaderNodeName << endl;
	  //cout <<"[liquid]   options.type = "<<options.type<<endl;
  } 
  else 
  {
	  // a shader node was specified
	  MSelectionList shaderNameList;
	  shaderNameList.add( options.shaderNodeName.c_str() );
	  shaderNameList.getDependNode( 0, shaderObj );
	  if( shaderObj == MObject::kNullObj )
	  {
		  MGlobal::displayError( std::string( "Can't find node for " + options.shaderNodeName ).c_str() );
		  RiEnd();
		  return 0;
	  }
	  currentShader = liqShader( shaderObj );
	  shader_type_TempForRefactoring = currentShader.shader_type_ex;
	  shaderFileName = currentShader.getShaderFileName();
  }
  MFnDependencyNode assignedShader( shaderObj );


  // Get the Pathes in globals node
  MObject globalObjNode;
  MString liquidShaderPath = "",liquidTexturePath = "",liquidProceduralPath = "";
  MStatus status;
  MSelectionList globalList;
	
	// get the current project directory
  MString MELCommand = "workspace -q -rd";
  MString MELReturn;
  MGlobal::executeCommand( MELCommand, MELReturn );
  MString liquidProjectDir = MELReturn;
	
  status = globalList.add( "liquidGlobals" );
  if ( globalList.length() > 0 ) 
	{
    status.clear();
    status = globalList.getDependNode( 0, globalObjNode );
    MFnDependencyNode globalNode( globalObjNode );
		liquidGetPlugValue( globalNode, "shaderPath", liquidShaderPath, status);
    liquidGetPlugValue( globalNode, "texturePath", liquidTexturePath, status);
    liquidGetPlugValue( globalNode, "proceduralPath", liquidProceduralPath, status);
  }
  if( fileName.empty() ) 
	{
    RiBegin_liq( NULL );
#ifdef DELIGHT
    //RtPointer callBack( progressCallBack );
    //RiOption( "statistics", "progresscallback", &callBack, RI_NULL );
#endif
  } 
	else {
	liquidMessage2(messageInfo,"preview rib file: [%s]", fileName.c_str());
    RiBegin_liq( (RtToken)fileName.c_str() );
  }

  std::string liquidHomeDir = liquidSanitizeSearchPath( getEnvironment( "LIQUIDHOME" ) );
  std::string shaderPath( "&:@:.:~:" + liquidHomeDir + "/lib/shaders" );
  std::string texturePath( "&:@:.:~:" + liquidHomeDir + "/lib/textures" );
  std::string proceduralPath( "&:@:.:~:" + liquidHomeDir + "/lib/shaders" );

  std::string projectDir = std::string( liquidSanitizeSearchPath( liquidProjectDir ).asChar() );
  if ( liquidProjectDir != "")
  {
    shaderPath += ":" + projectDir;	
    texturePath += ":" + projectDir;
    proceduralPath += ":" + projectDir;
  }
  if ( liquidShaderPath != "" )
		shaderPath += ":" + std::string( liquidSanitizeSearchPath( parseString( liquidShaderPath, false ) ).asChar());	
  if ( liquidTexturePath != "" )
		texturePath += ":" + std::string( liquidSanitizeSearchPath( parseString( liquidTexturePath, false) ).asChar());	
  if ( liquidProceduralPath != "" )
		proceduralPath += ":" + std::string( liquidSanitizeSearchPath( parseString( liquidProceduralPath, false) ).asChar());	
	
  RtString list( const_cast< RtString >( shaderPath.c_str() ) );
  RiOption( "searchpath", "shader", &list, RI_NULL );
	
  RtString texPath( const_cast< RtString >( texturePath.c_str() ) );
  if( texPath[ 0 ] )
    RiOption( "searchpath","texture", &texPath, RI_NULL );
	
  RtString procPath( const_cast< RtString >( proceduralPath.c_str() ) );
  
  if( procPath[ 0 ] )
    RiOption( "searchpath","procedural", &procPath, RI_NULL );

  RiShadingRate( ( RtFloat )options.shadingRate );
  RiPixelSamples( options.pixelSamples, options.pixelSamples );

#ifdef PRMAN
  if ( MString( "PRMan" ) == liqglo.liquidRenderer.renderName )
	RiPixelFilter( RiCatmullRomFilter, 4., 4. );
#elif defined( DELIGHT )
  if ( MString( "3Delight" ) == liqglo.liquidRenderer.renderName )
    RiPixelFilter( RiSeparableCatmullRomFilter, 4., 4. );
//    RiPixelFilter( RiMitchellFilter, 4., 4.);
#else
  RiPixelFilter( RiCatmullRomFilter, 4., 4. );
#endif

  RiFormat( ( RtInt )options.displaySize, ( RtInt )options.displaySize, 1.0 );
  if( options.backPlane ) 
	{
    RiDisplay( const_cast< RtString >( options.displayName.c_str() ),
               const_cast< RtString >( options.displayDriver.c_str() ), RI_RGB, RI_NULL );
  } 
	else 
	{ // Alpha might be useful
    RiDisplay( const_cast< RtString >( options.displayName.c_str() ),
               const_cast< RtString >( options.displayDriver.c_str() ), RI_RGBA, RI_NULL );
  }
  RtFloat fov( 22.5 );
  RiProjection( "perspective", "fov", &fov, RI_NULL );
  RiTranslate( 0, 0, 2.75 );
  RiExposure(1, currentShader.m_previewGamma);
  
  RtInt visible = 1;
  RtString transmission = "transparent";

  RiAttribute( "visibility", ( RtToken ) "camera", &visible, RI_NULL );
  RiAttribute( "visibility",  ( RtToken ) "trace", &visible, RI_NULL );
  // RiAttribute( "visibility", ( RtToken ) "transmission", ( RtPointer ) &transmission, RI_NULL );
  
  RiWorldBegin();
  RiReverseOrientation();
  RiTransformBegin();
  RiRotate( -90., 1., 0., 0. );
  RiCoordinateSystem( "_environment" );
  RiTransformEnd();
  RtLightHandle ambientLightH, directionalLightH;
  RtFloat intensity;
  intensity = 0.05 * (RtFloat)options.previewIntensity;
  ambientLightH = RiLightSource( "ambientlight", "intensity", &intensity, RI_NULL );
  intensity = 0.9 * (RtFloat)options.previewIntensity;
  RtPoint from;
  RtPoint to;
  from[0] = -1.; from[1] = 1.5; from[2] = -1.;
  to[0] = 0.; to[1] = 0.; to[2] = 0.;
  RiTransformBegin();
    RiRotate( 55.,  1, 0, 0 );
    RiRotate( 30.,  0, 1, 0 );
    directionalLightH = RiLightSource( "liquiddistant", "intensity", &intensity, RI_NULL );
  RiTransformEnd();
  intensity = 0.2f * (RtFloat)options.previewIntensity;
  from[0] = 1.3f; from[1] = -1.2f; from[2] = -1.;
  RiTransformBegin();
    RiRotate( -50.,  1, 0, 0 );
    RiRotate( -40.,  0, 1, 0 );
    directionalLightH = RiLightSource( "liquiddistant", "intensity", &intensity, RI_NULL );
  RiTransformEnd();

  RiAttributeBegin();


  //ymesh omit this section, because liqShader::writeRibAttributes() do this work in that branch
  //I don't use liqShader::writeRibAttributes(), so I use this section. -yayansi
  float displacementBounds = 0.;
	liquidGetPlugValue( assignedShader, "displacementBound", displacementBounds, status);
  
  if ( displacementBounds > 0. ) 
	{
    RtString coordsys = "shader";
	RiArchiveRecord( RI_COMMENT, "ymesh omit this section, because liqShader::writeRibAttributes do this work in that branch" );
    RiAttribute( "displacementbound", "coordinatesystem", &coordsys, RI_NULL );	
    RiAttribute( "displacementbound", "sphere", &displacementBounds, "coordinatesystem", &coordsys, RI_NULL );
  }

  //LIQ_GET_SHADER_FILE_NAME( shaderFileName, options.shortShaderName, currentShader );

	// output shader space
  MString shadingSpace;
	liquidGetPlugValue( assignedShader, "shaderSpace", shadingSpace, status);
  
  if ( shadingSpace != "" ) 
	{
    RiTransformBegin();
    RiCoordSysTransform( (char*) shadingSpace.asChar() );
  }

  RiTransformBegin();
  // Rotate shader space to make the preview more interesting
  RiRotate( 60., 1., 0., 0. );
  RiRotate( 60., 0., 1., 0. );
  RtFloat scale( 1.f / ( RtFloat )options.objectScale );
  RiScale( scale, scale, scale );

  if ( shader_type_TempForRefactoring=="surface" || shader_type_TempForRefactoring=="shader"/*currentShader.shader_type == SHADER_TYPE_SURFACE || currentShader.shader_type == SHADER_TYPE_SHADER */ ) //  [2/14/2012 yaoyansi]
	{
		RiColor( currentShader.rmColor );
		RiOpacity( currentShader.rmOpacity );
		//cout << "Shader: " << shaderFileName << endl;
		if ( options.fullShaderPath ) 
				RiSurface( (RtToken)shaderFileName.c_str(), RI_NULL );
		else
		{
			liqShader liqAssignedShader( shaderObj );
			liqAssignedShader.forceAs = SHADER_TYPE_SURFACE;
			liqAssignedShader.write();
		}
  } 
	else if ( shader_type_TempForRefactoring=="displacement"/*currentShader.shader_type == SHADER_TYPE_DISPLACEMENT*/ ) //  [2/14/2012 yaoyansi]
	{
		RtToken Kd( "Kd" );
		RtFloat KdValue( 1. );
#ifdef GENERIC_RIBLIB    
    // !!! current ribLib has wrong interpretation of RiSurface parameters 
    RiSurface( "plastic", Kd, &KdValue, RI_NULL );
#else
		RiSurface( "plastic", &Kd, &KdValue, RI_NULL );
#endif    
		if ( options.fullShaderPath ) 
			RiDisplacement( (RtToken)shaderFileName.c_str(), RI_NULL );
		else 
		{
			liqShader liqAssignedShader( shaderObj );
			liqAssignedShader.forceAs = SHADER_TYPE_DISPLACEMENT;
			liqAssignedShader.write();
		}
  }
  RiTransformEnd();
  if ( shadingSpace != "" ) 
		RiTransformEnd();

 switch( options.primitiveType ) 
 {
    case CYLINDER: 
		{
      RiReverseOrientation();
      RiScale( 0.95, 0.95, 0.95 );
      RiRotate( 60., 1., 0., 0. );
      RiTranslate( 0., 0., -0.05 );
      RiCylinder( 0.5, -0.3, 0.3, 360., RI_NULL );
      RiTranslate( 0., 0., 0.3f );
      RiTorus( 0.485, 0.015, 0., 90., 360., RI_NULL );
      RiDisk( 0.015, 0.485, 360., RI_NULL );
      RiTranslate( 0., 0., -0.6 );
      RiTorus( 0.485, 0.015, 270., 360., 360., RI_NULL );
      RiReverseOrientation();
      RiDisk( -0.015, 0.485, 360., RI_NULL );
      break;
    }
    case TORUS: 
		{
      RiRotate( 45., 1., 0., 0. );
      RiTranslate( 0., 0., -0.05 );
      RiReverseOrientation();
      RiTorus( 0.3f, 0.2f, 0., 360., 360., RI_NULL );
      break;
    }
    case PLANE: 
		{
      RiScale( 0.5, 0.5, 0.5 );
      RiReverseOrientation();
      static RtPoint plane[4] = {
        { -1.,  1.,  0. },
        {  1.,  1.,  0. },
        { -1., -1.,  0. },
        {  1., -1.,  0. }
      };
      RiPatch( RI_BILINEAR, RI_P, (RtPointer) plane, RI_NULL );
      break;
    }
    case TEAPOT: 
		{
      RiTranslate( 0.06f, -0.18f, 0. );
      RiRotate( -120., 1., 0., 0. );
      RiRotate( 130., 0., 0., 1. );
      RiScale( 0.2f, 0.2f, 0.2f );
			RiArchiveRecord( RI_VERBATIM, "Geometry \"teapot\"" );
      break;
    }
    case CUBE: 
		{
      /* Lovely cube with rounded corners and edges */
      RiScale( 0.35f, 0.35f, 0.35f );
      RiRotate( 60., 1., 0., 0. );
      RiRotate( 60., 0., 0., 1. );

      RiTranslate( 0.11f, 0., -0.08f );

      RiReverseOrientation();

      static RtPoint top[ 4 ] = { { -0.95, 0.95, -1. }, { 0.95, 0.95, -1. }, { -0.95, -0.95, -1. },  { 0.95, -0.95, -1. } };
      RiPatch( RI_BILINEAR, RI_P, ( RtPointer ) top, RI_NULL );

      static RtPoint bottom[ 4 ] = { { 0.95, 0.95, 1. }, { -0.95, 0.95, 1. }, { 0.95, -0.95, 1. }, { -0.95, -0.95, 1. } };
      RiPatch( RI_BILINEAR, RI_P, ( RtPointer ) bottom, RI_NULL );

      static RtPoint right[ 4 ] = { { -0.95, -1., -0.95 }, { 0.95, -1., -0.95 }, { -0.95, -1., 0.95 }, { 0.95, -1., 0.95 } };
      RiPatch( RI_BILINEAR, RI_P, ( RtPointer ) right, RI_NULL );

      static RtPoint left[ 4 ] = { { 0.95, 1., -0.95 }, { -0.95, 1., -0.95 }, { 0.95, 1., 0.95 }, { -0.95, 1., 0.95 } };
      RiPatch( RI_BILINEAR, RI_P, ( RtPointer ) left, RI_NULL );

      static RtPoint front[ 4 ] = { {-1., 0.95, -0.95 }, { -1., -0.95, -0.95 }, { -1., 0.95, 0.95 }, { -1., -0.95, 0.95 } };
      RiPatch( RI_BILINEAR, RI_P, ( RtPointer ) front, RI_NULL );

      static RtPoint back[ 4 ] = { { 1., -0.95, -0.95 }, { 1., 0.95, -0.95 }, { 1., -0.95, 0.95 }, { 1., 0.95, 0.95 } };
      RiPatch( RI_BILINEAR, RI_P, ( RtPointer ) back, RI_NULL );

      RiTransformBegin();
      RiTranslate( 0.95, 0.95, 0. );
      RiCylinder( 0.05, -0.95, 0.95, 90., RI_NULL );
      RiTransformEnd();

      RiTransformBegin();
      RiTranslate( 0.95, -0.95, 0. );
      RiRotate( -90., 0., 0., 1. );
      RiCylinder( 0.05, -0.95, 0.95, 90., RI_NULL );
      RiTransformEnd();

      RiTransformBegin();
      RiTranslate( -0.95, 0.95, 0. );
      RiRotate( 90., 0., 0., 1. );
      RiCylinder( 0.05, -0.95, 0.95, 90., RI_NULL );
      RiTransformEnd();

      RiTransformBegin();
      RiTranslate( -0.95, -0.95, 0. );
      RiRotate( 180., 0., 0., 1. );
      RiCylinder( 0.05, -0.95, 0.95, 90., RI_NULL );
      RiTransformEnd();

      RiTransformBegin();
      RiTranslate( 0., 0., 0.95 );

      RiTransformBegin();

      RiTransformBegin();
      RiTranslate( 0.95, 0.95, 0. );
      RiSphere( 0.05, 0., 0.05, 90., RI_NULL );
      RiTransformEnd();

      RiTransformBegin();
      RiTranslate( 0.95, -0.95, 0. );
      RiRotate( -90., 0., 0., 1. );
      RiSphere( 0.05, 0., 0.05, 90., RI_NULL );
      RiTransformEnd();

      RiRotate( 180., 0., 0., 1. );

      RiTransformBegin();
      RiTranslate( 0.95, 0.95, 0. );
      RiSphere( 0.05, 0., 0.05, 90., RI_NULL );
      RiTransformEnd();

      RiTransformBegin();
      RiTranslate( 0.95, -0.95, 0. );
      RiRotate( -90., 0., 0., 1. );
      RiSphere( 0.05, 0., 0.05, 90., RI_NULL );
      RiTransformEnd();

      RiTransformEnd();

      RiRotate( 90., 1., 0., 0. );

      RiTransformBegin();
      RiTranslate( 0.95, 0., 0. );
      RiCylinder( 0.05, -0.95, 0.95, 90., RI_NULL );
      RiTransformEnd();

      RiTransformBegin();
      RiTranslate( -0.95, 0., 0. );
      RiRotate( 90., 0., 0., 1. );
      RiCylinder( 0.05, -0.95, 0.95, 90., RI_NULL );
      RiTransformEnd();

      RiRotate( 90., 0., 1., 0. );

      RiTransformBegin();
      RiTranslate( 0.95, 0.,  0. );
      RiCylinder( 0.05, -0.95, 0.95, 90., RI_NULL );
      RiTransformEnd();

      RiTransformBegin();
      RiTranslate( -0.95, 0., 0. );
      RiRotate( 90., 0., 0., 1. );
      RiCylinder( 0.05, -0.95, 0.95, 90., RI_NULL );
      RiTransformEnd();

      RiTransformEnd();

      RiTransformBegin();
      RiTranslate( 0., 0., -0.95 );

      RiTransformBegin();

      RiTransformBegin();
      RiTranslate( 0.95, 0.95, 0. );
      RiSphere( 0.05, -0.05, 0., 90., RI_NULL );
      RiTransformEnd();

      RiTransformBegin();
      RiTranslate( 0.95, -0.95, 0. );
      RiRotate( -90., 0., 0., 1. );
      RiSphere( 0.05, -0.05, 0., 90., RI_NULL );
      RiTransformEnd();

      RiRotate( 180., 0., 0., 1. );

      RiTransformBegin();
      RiTranslate( 0.95, 0.95, 0. );
      RiSphere( 0.05, -0.05, 0., 90., RI_NULL );
      RiTransformEnd();

      RiTransformBegin();
      RiTranslate( 0.95, -0.95, 0. );
      RiRotate( -90., 0., 0., 1. );
      RiSphere( 0.05, -0.05, 0., 90., RI_NULL );
      RiTransformEnd();

      RiTransformEnd();

      RiRotate( 90., 1., 0., 0. );

      RiTransformBegin();
      RiTranslate( -0.95, 0.,  0. );
      RiRotate( 180., 0., 0., 1. );
      RiCylinder( 0.05, -0.95, 0.95, 90., RI_NULL );
      RiTransformEnd();

      RiTransformBegin();
      RiTranslate( 0.95, 0.,  0. );
      RiRotate( -90., 0., 0., 1. );
      RiCylinder( 0.05, -0.95, 0.95, 90., RI_NULL );
      RiTransformEnd();

      RiRotate( 90., 0., 1., 0. );

      RiTransformBegin();
      RiTranslate( 0.95, 0.,  0. );
      RiRotate( -90., 0., 0., 1. );
      RiCylinder( 0.05, -0.95, 0.95, 90., RI_NULL );
      RiTransformEnd();

      RiTransformBegin();
      RiTranslate( -0.95, 0.,  0. );
      RiRotate( 180., 0., 0., 1. );
      RiCylinder( 0.05, -0.95, 0.95, 90., RI_NULL );
      RiTransformEnd();

      RiTransformEnd();

      break;
    }
    case CUSTOM: 
		{
      //cout <<"custom : "<<options.customRibFile<<endl;
      if ( fileExists( options.customRibFile.c_str() ) ) 
			{
        RiReadArchive( const_cast< RtToken >( options.customRibFile.c_str() ), NULL, RI_NULL );
      }
      break;
    }
    case SPHERE:
    default: 
		{
      RiRotate( 60., 1., 0., 0. );
      RiReverseOrientation();
      RiSphere( 0.5, -0.5, 0.5, 360., RI_NULL );
      break;
    }
  }

  RiAttributeEnd();
  /*
   * Backplane
   */
  if( options.backPlane ) 
	{
    if ( options.customBackplane.empty() ) 
		{
      RiAttributeBegin();
      RiScale( 0.91, 0.91, 0.91 );
      if( MString("displacement")==shader_type_TempForRefactoring/*SHADER_TYPE_DISPLACEMENT == currentShader.shader_type*/ ) //  [2/14/2012 yaoyansi]
			{
        RtColor bg = { 0.698, 0.698, 0. };
        RiColor( bg );
      } else 
        RiSurface( const_cast< RtToken >( options.backPlaneShader.c_str() ), RI_NULL );




      static RtPoint backplane[4] = {
        { -1.,  1.,  2. },
        {  1.,  1.,  2. },
        { -1., -1.,  2. },
        {  1., -1.,  2. }
      };
      RiPatch( RI_BILINEAR, RI_P, (RtPointer) backplane, RI_NULL );
      RiAttributeEnd();
    } 
		else 
		{
      if ( fileExists( options.customBackplane.c_str() ) ) 
			{
        RiAttributeBegin();
          RiScale( 1., 1., -1. );
          RiReadArchive( const_cast< RtString >( options.customBackplane.c_str() ), NULL, RI_NULL );
        RiAttributeEnd();
      }
    }
  }

  RiWorldEnd();

/* this caused maya to hang up under windoof - Alf
#ifdef _WIN32
//	Wait until the renderer is done
	while( !fileFullyAccessible( options.displayName.c_str() ) );
#endif
*/
  RiEnd();
  if(liqglo.m_logMsgFlush)
  {
	fflush( NULL );
  }
	}
Esempio n. 6
0
int main( int argc, char** argv ){

#if (CISST_OS == CISST_LINUX_XENOMAI)
  mlockall(MCL_CURRENT | MCL_FUTURE);
  RT_TASK task;
  rt_task_shadow( &task, "GroupTest", 99, 0 );
#endif

  cmnLogger::SetMask( CMN_LOG_ALLOW_ALL );
  cmnLogger::SetMaskFunction( CMN_LOG_ALLOW_ALL );
  cmnLogger::SetMaskDefaultLog( CMN_LOG_ALLOW_ALL );

  if( argc != 2 ){
    std::cout << "Usage: " << argv[0] << " can[0-1]" << std::endl;
    return -1;
  }

#if (CISST_OS == CISST_LINUX_XENOMAI)
  osaRTSocketCAN can( argv[1], osaCANBus::RATE_1000 );
#else
  osaSocketCAN can( argv[1], osaCANBus::RATE_1000 );
#endif

  if( can.Open() != osaCANBus::ESUCCESS ){
    CMN_LOG_RUN_ERROR << argv[0] << "Failed to open " << argv[1] << std::endl;
    return -1;
  }

  osaWAM WAM( &can );

  if( WAM.Initialize() != osaWAM::ESUCCESS ){
    CMN_LOG_RUN_ERROR << "Failed to initialize WAM" << std::endl;
    return -1;
  }

  vctDynamicVector<double> qinit( 7, 0.0 );
  qinit[1] = -cmnPI_2;
  qinit[3] =  cmnPI;

  if( WAM.SetPositions( qinit ) != osaWAM::ESUCCESS ){
    CMN_LOG_RUN_ERROR << "Failed to set position: " << qinit << std::endl;
    return -1;
  }

  cmnPath path;
  path.AddRelativeToCisstShare("/models/WAM");
  std::string fname = path.Find("wam7.rob", cmnPath::READ);

  // Rotate the base
  vctMatrixRotation3<double> Rw0(  0.0,  0.0, -1.0,
                                   0.0,  1.0,  0.0,
                                   1.0,  0.0,  0.0 );
  vctFixedSizeVector<double,3> tw0(0.0);
  vctFrame4x4<double> Rtw0( Rw0, tw0 );

  // Gain matrices
  vctDynamicMatrix<double> Kp(7, 7, 0.0), Kd(7, 7, 0.0);
  Kp[0][0] = 250;     Kd[0][0] = 3.0;
  Kp[1][1] = 250;     Kd[1][1] = 3.0;
  Kp[2][2] = 250;     Kd[2][2] = 3.0;
  Kp[3][3] = 200;     Kd[3][3] = 3;
  Kp[4][4] = 50;      Kd[4][4] = 0.8;
  Kp[5][5] = 50;      Kd[5][5] = 0.8;
  Kp[6][6] = 10;      Kd[6][6] = .1;

  osaPDGC PDGC( fname, Rtw0, Kp, Kd, qinit );

  std::cout << "Activate the WAM" << std::endl;
  bool activated = false;

  double t1 = osaGetTime();

  while( 1 ){

    // Get the positions
    vctDynamicVector<double> q;
    if( WAM.GetPositions( q ) != osaWAM::ESUCCESS ){
      CMN_LOG_RUN_ERROR << "Failed to get positions" << std::endl;
      return -1;
    }

    // Check if the pucks are activated
    if( !activated ) {
      osaWAM::Mode mode;
      if( WAM.GetMode( mode ) != osaWAM::ESUCCESS ){
	CMN_LOG_RUN_ERROR << "Failed to get mode" << std::endl;
	return -1;
      }
      if( mode == osaWAM::MODE_ACTIVATED )
	{ activated = true; }
    }

    // if pucks are activated, run the controller
    vctDynamicVector<double> tau( q.size(), 0.0 );
    double t2 = osaGetTime();
    if( activated ){
      if( PDGC.Evaluate( qinit, q, tau, t2-t1 ) != osaPDGC::ESUCCESS ){
	CMN_LOG_RUN_ERROR << "Failed to evaluate controller" << std::endl;
	return -1;
      }
    }
    t1 = t2;

    // apply torques
    if( WAM.SetTorques( tau ) != osaWAM::ESUCCESS ){
      CMN_LOG_RUN_ERROR << "Failed to set torques" << std::endl;
      return -1;
    }

    std::cout << "q:   " << q << std::endl;
    std::cout << "tau: " << tau << std::endl;

  }

  return 0;
}
Esempio n. 7
0
int main( int argc, char** argv ){

#if (CISST_OS == CISST_LINUX_XENOMAI)
  mlockall(MCL_CURRENT | MCL_FUTURE);
  RT_TASK task;
  rt_task_shadow( &task, "mtsWAMPDGCExample", 40, 0 );
#endif

  cmnLogger::SetMask( CMN_LOG_ALLOW_ALL );
  cmnLogger::SetMaskFunction( CMN_LOG_ALLOW_ALL );
  cmnLogger::SetMaskDefaultLog( CMN_LOG_ALLOW_ALL );

  if( argc != 3 ){
    std::cout << "Usage: " << argv[0] << " can[0-1] GCMIP" << std::endl;
    return -1;
  }

  std::string process( "Slave" );
  mtsManagerLocal* taskManager = NULL;

  try{ taskManager = mtsTaskManager::GetInstance( argv[2], process ); }
  catch( ... ){
    std::cerr << "Failed to connect to GCM: " << argv[2] << std::endl;
    taskManager = mtsManagerLocal::GetInstance();
  }

  mtsKeyboard kb;
  kb.SetQuitKey( 'q' );
  kb.AddKeyWriteFunction( 'C', "PDGCEnable", "Enable", true );
  kb.AddKeyWriteFunction( 'C', "TrajEnable", "Enable", true );
  kb.AddKeyWriteFunction( 'M', "MoveEnable", "Enable", true );
  taskManager->AddComponent( &kb );

  // Initial configuration
  vctDynamicVector<double> qinit( 7, 0.0 );
  qinit[1] = -cmnPI_2;
  qinit[3] =  cmnPI-0.01;  
  qinit[5] = -cmnPI_2;

#if (CISST_OS == CISST_LINUX_XENOMAI)
  osaRTSocketCAN can( argv[1], osaCANBus::RATE_1000 );
#else
  osaSocketCAN can( argv[1], osaCANBus::RATE_1000 );
#endif

  if( can.Open() != osaCANBus::ESUCCESS ){
    CMN_LOG_RUN_ERROR << argv[0] << "Failed to open " << argv[1] << std::endl;
    return -1;
  }

  mtsWAM WAM( "WAM", &can, osaWAM::WAM_7DOF, OSA_CPU4, 80 );
  WAM.Configure();
  WAM.SetPositions( qinit );
  taskManager->AddComponent( &WAM );

  cmnPath path;
  path.AddRelativeToCisstShare("models/WAM");

  // Rotate the base
  vctMatrixRotation3<double> Rw0(  0.0,  0.0, -1.0,
                                   0.0,  1.0,  0.0,
                                   1.0,  0.0,  0.0 );
  vctFixedSizeVector<double,3> tw0(0.0);
  vctFrame4x4<double> Rtw0( Rw0, tw0 );

  // Gain matrices
  vctDynamicMatrix<double> Kp(7, 7, 0.0), Kd(7, 7, 0.0);
  Kp[0][0] = 250;     Kd[0][0] = 3.0;
  Kp[1][1] = 250;     Kd[1][1] = 3.0;
  Kp[2][2] = 250;     Kd[2][2] = 3.0;
  Kp[3][3] = 200;     Kd[3][3] = 3;
  Kp[4][4] = 50;      Kd[4][4] = 0.8;
  Kp[5][5] = 50;      Kd[5][5] = 0.8;
  Kp[6][6] = 10;      Kd[6][6] = .1;

  mtsPDGC PDGC( "PDGC",
		0.00125,
		path.Find( "wam7cutter.rob" ),
		Rtw0,
		Kp,
		Kd,
		qinit,
		OSA_CPU3 );
  taskManager->AddComponent( &PDGC );

  mtsTrajectory traj( "trajectory",
		      0.002,
		      path.Find( "wam7cutter.rob" ), 
		      Rtw0, 
		      qinit );
  taskManager->AddComponent( &traj );

  SetPoints setpoints( path.Find( "wam7cutter.rob" ), Rtw0, qinit );
  taskManager->AddComponent( &setpoints );

  // Connect the keyboard
  if( !taskManager->Connect( kb.GetName(),  "PDGCEnable",
			     PDGC.GetName(),"Control") ){
    std::cout << "Failed to connect: "
	      << kb.GetName()   << "::PDGCEnable to "
	      << PDGC.GetName() << "::Control" << std::endl;
    return -1;
  }

  if( !taskManager->Connect( kb.GetName(),  "TrajEnable",
			     traj.GetName(),"Control") ){
    std::cout << "Failed to connect: "
	      << kb.GetName()   << "::TrajEnable to "
	      << traj.GetName() << "::Control" << std::endl;
    return -1;
  }

  if( !taskManager->Connect( kb.GetName(),       "MoveEnable",
			     setpoints.GetName(),"Control") ){
    std::cout << "Failed to connect: "
	      << kb.GetName()        << "::TrajEnable to "
	      << setpoints.GetName() << "::Control" << std::endl;
    return -1;
  }



  // connect the trajectory with setpoints
  if( !taskManager->Connect( traj.GetName(),      "Input",
			     setpoints.GetName(), "Output" ) ){
    std::cout << "Failed to connect: "
	      << traj.GetName()      << "::Input to "
	      << setpoints.GetName() << "::Output" << std::endl;
    return -1;
  }



  // connect the trajectory to the controller
  if( !taskManager->Connect( traj.GetName(), "Output",
			     PDGC.GetName(), "Input") ){
    std::cout << "Failed to connect: "
	      << traj.GetName() << "::Output to "
	      << PDGC.GetName() << "::Input" << std::endl;
    return -1;
  }



  // connect the controller to the WAM
  if( !taskManager->Connect( WAM.GetName(), "Input",
			     PDGC.GetName(), "Output" ) ){
    std::cout << "Failed to connect: "
	      << WAM.GetName()  << "::Input to "
	      << PDGC.GetName() << "::Output" << std::endl;
    return -1;
  }

  if( !taskManager->Connect( WAM.GetName(),  "Output",
			     PDGC.GetName(), "Feedback" ) ){
    std::cout << "Failed to connect: "
	      << WAM.GetName()  << "::Output to "
	      << PDGC.GetName() << "::Feedback" << std::endl;
    return -1;
  }




  taskManager->CreateAll();
  taskManager->StartAll();

  std::cout << "Press 'q' to exit." << std::endl;
  pause();

  return 0;
}
Esempio n. 8
0
void
beam2d02::setDomain(Domain *theDomain)
{
    // first set the node pointers
    int Nd1 = connectedExternalNodes(0);
    int Nd2 = connectedExternalNodes(1);
    theNodes[0] = theDomain->getNode(Nd1);
    theNodes[1] = theDomain->getNode(Nd2);	
    if (theNodes[0] == 0) {
	opserr << "WARNING beam2d02::setDomain(): Nd1: ";
	opserr << Nd1 << "does not exist in model for beam \n" << *this;
	return;
    }
    if (theNodes[1] == 0) {
	opserr << "WARNING beam2d02::setDomain(): Nd2: ";
	opserr << Nd2 << "does not exist in model for beam\n" << *this;
	return;
    }	
    
    // now verify the number of dof at node ends
    int dofNd1 = theNodes[0]->getNumberDOF();
    int dofNd2 = theNodes[1]->getNumberDOF();	
    if (dofNd1 != 3 && dofNd2 != 3) {
	opserr << "WARNING beam2d02::setDomain(): node " << Nd1;
	opserr << " and/or node " << Nd2 << " have/has incorrect number ";
	opserr << "of dof's at end for beam\n " << *this;
	return;
    }	

    // call the base class method
    this->DomainComponent::setDomain(theDomain);

    // determine length and direction cosines
    double dx,dy;
    const Vector &end1Crd = theNodes[0]->getCrds();
    const Vector &end2Crd = theNodes[1]->getCrds();	
    
    dx = end2Crd(0)-end1Crd(0);
    dy = end2Crd(1)-end1Crd(1);	
    
    L = sqrt(dx*dx + dy*dy);
    if (L == 0.0) {
	opserr << "WARNING beam2d02::setDomain(): beam " << this->getTag();
	opserr << " has zero length for beam\n" << *this;
	return;  
    }

    Kd(0,0) = E*A/L;
    Kd(0,1) = 0.0;
    Kd(0,2) = 0.0;    

    Kd(1,0) = 0.0;        
    Kd(1,1) = 4.0*E*I/L;
    Kd(1,2) = 2.0*E*I/L;

    Kd(2,0) = 0.0;    
    Kd(2,1) = 2.0*E*I/L;
    Kd(2,2) = 4.0*E*I/L;

    cs = dx/L;
    sn = dy/L;
    
    // set the mass variable equal to 1/2 tha mass of the beam = 0.5 * rho*A*L
    M = 0.5*M*A*L;    
}
Esempio n. 9
0
Localizer::Localizer(exchangeData *_commData, const unsigned int _period) :
                     RateThread(_period), commData(_commData), period(_period)
{
    iCubHeadCenter eyeC(commData->head_version>1.0?"right_v2":"right");
    eyeL=new iCubEye(commData->head_version>1.0?"left_v2":"left");
    eyeR=new iCubEye(commData->head_version>1.0?"right_v2":"right");

    // remove constraints on the links
    // we use the chains for logging purpose
    eyeL->setAllConstraints(false);
    eyeR->setAllConstraints(false);

    // release links
    eyeL->releaseLink(0); eyeC.releaseLink(0); eyeR->releaseLink(0);
    eyeL->releaseLink(1); eyeC.releaseLink(1); eyeR->releaseLink(1);
    eyeL->releaseLink(2); eyeC.releaseLink(2); eyeR->releaseLink(2);

    // add aligning matrices read from configuration file
    getAlignHN(commData->rf_cameras,"ALIGN_KIN_LEFT",eyeL->asChain(),true);
    getAlignHN(commData->rf_cameras,"ALIGN_KIN_RIGHT",eyeR->asChain(),true);

    // overwrite aligning matrices iff specified through tweak values
    if (commData->tweakOverwrite)
    {
        getAlignHN(commData->rf_tweak,"ALIGN_KIN_LEFT",eyeL->asChain(),true);
        getAlignHN(commData->rf_tweak,"ALIGN_KIN_RIGHT",eyeR->asChain(),true);
    }

    // get the absolute reference frame of the head
    Vector q(eyeC.getDOF(),0.0);
    eyeCAbsFrame=eyeC.getH(q);
    // ... and its inverse
    invEyeCAbsFrame=SE3inv(eyeCAbsFrame);

    // get the length of the half of the eyes baseline
    eyesHalfBaseline=0.5*norm(eyeL->EndEffPose().subVector(0,2)-eyeR->EndEffPose().subVector(0,2));

    bool ret;

    // get camera projection matrix
    ret=getCamPrj(commData->rf_cameras,"CAMERA_CALIBRATION_LEFT",&PrjL,true);
    if (commData->tweakOverwrite)
    {
        Matrix *Prj;
        if (getCamPrj(commData->rf_tweak,"CAMERA_CALIBRATION_LEFT",&Prj,true))
        {
            delete PrjL;
            PrjL=Prj;
        }
    }

    if (ret)
    {
        cxl=(*PrjL)(0,2);
        cyl=(*PrjL)(1,2);
        invPrjL=new Matrix(pinv(PrjL->transposed()).transposed());
    }
    else
        PrjL=invPrjL=NULL;

    // get camera projection matrix
    ret=getCamPrj(commData->rf_cameras,"CAMERA_CALIBRATION_RIGHT",&PrjR,true);
    if (commData->tweakOverwrite)
    {
        Matrix *Prj;
        if (getCamPrj(commData->rf_tweak,"CAMERA_CALIBRATION_RIGHT",&Prj,true))
        {
            delete PrjR;
            PrjR=Prj;
        }
    }

    if (ret)
    {
        cxr=(*PrjR)(0,2);
        cyr=(*PrjR)(1,2);
        invPrjR=new Matrix(pinv(PrjR->transposed()).transposed());
    }
    else
        PrjR=invPrjR=NULL;

    Vector Kp(1,0.001), Ki(1,0.001), Kd(1,0.0);
    Vector Wp(1,1.0),   Wi(1,1.0),   Wd(1,1.0);
    Vector N(1,10.0),   Tt(1,1.0);
    Matrix satLim(1,2);

    satLim(0,0)=0.05;
    satLim(0,1)=10.0;

    pid=new parallelPID(0.05,Kp,Ki,Kd,Wp,Wi,Wd,N,Tt,satLim);

    Vector z0(1,0.5);
    pid->reset(z0);
    dominantEye="left";

    port_xd=NULL;
}
Esempio n. 10
0
double TStringKernel::KDynamic(const TIntV& s, const TIntV& t, const TFltV& lc, const double& lb) {
    const int k = lc.Len() + 1;
    int x,y,i;

    int ls = s.Len(), lt = t.Len();
    
    //TVec<TFltVV> Kd(2);
    //for (i = 0; i < 2; i++) Kd[i].Gen(ls+1, lt+1);

    // s is on X-axis and t is on Y-axis
    TVec<double *> Kd(2);
    if ((ls+1)*(lt+1) > BufN) {
        if (Buf1 != NULL) delete[] Buf1;
        if (Buf2 != NULL) delete[] Buf2;
        BufN = (ls+2)*(lt+2) + 10;
        Buf1 = new double[BufN];
        Buf2 = new double[BufN];
    }
    Kd[0] = Buf1; Kd[1] = Buf2;
    double *Kdii, *Kdi; //ii == (i-1)%2, i == i%2

    // initialize Kd for i == 0
    int MxSize = (ls+1)*(lt+1) + 10;
    for (i = 0, Kdi = Kd[0]; i < MxSize; i++) Kdi[i] = 1.0;
    //for (x = 0; x <= ls; x++) {
    //    for (y = 0; y <= lt; y++) {
    //        Kd[0](x,y) = 1.0;
    //    }
    //}

    // calculate Kd for i == 1..k-1
    double K = 0.0; 
    for (i = 1; i < k; i++) {
        Kdi = Kd[i%2]; Kdii = Kd[(i-1)%2];
        for (x = 0; x <= ls; x++) Kdi[x*(lt+1) + (i-1)] = 0.0;
        for (y = 0; y <= lt; y++) Kdi[(i-1)*(lt+1) + y] = 0.0;

        //for (x = 0; x <= ls; x++) Kd[i%2](x,i-1) = 0.0;
        //for (y = 0; y <= lt; y++) Kd[i%2](i-1,y) = 0.0;

        double Ki = 0.0;
        for (x = i; x <= ls; x++) {
            double Kdd = 0.0; int u = s[x-1];
            for (y = i; y <= lt; y++) {
                if (u == t[y-1]) {
                    Kdd = lb * (Kdd + lb*Kdii[(x-1)*(lt+1) + (y-1)]);
                    Ki += lb*lb * Kdi[(x-1)*(lt+1) + (y-1)];
                    //Kdd = lb * (Kdd + lb*Kd[(i-1)%2](x-1,y-1));
                    //Ki += lb*lb * Kd[i%2](x-1, y-1);
                } else {
                    Kdd *= lb;
                }
                Kdi[x*(lt+1) + y] = lb*Kdi[(x-1)*(lt+1) + y] + Kdd;
                //Kd[i%2](x,y) = lb*Kd[i%2](x-1, y) + Kdd;
            }
        }
        K += lc[i-1] * Ki;
    }

    return K;
}
Esempio n. 11
0
void createLambertian(BSDF* bsdf, MemoryArena& arena) {
    Spectrum Kd(1);
    bsdf->Add(ARENA_ALLOC(arena, LambertianReflection)(Kd));
}
Esempio n. 12
0
//------------------------------------------------------------------------------------------------------------------------------------
// called when we want to draw the 3D data in our app.
//------------------------------------------------------------------------------------------------------------------------------------
void draw3D()
{
	// draw the grid on the floor
	setColour(0.25f, 0.25f, 0.25f);
	for(float i = -10.0f; i <= 10.1f; i += 1.0f)
	{
		Vec3 zmin(i, 0, -10);
		Vec3 zmax(i, 0,  10);
		Vec3 xmin(-10, 0, i);
		Vec3 xmax(10, 0, i);
		drawLine(xmin, xmax);
		drawLine(zmin, zmax);
	}

	// If using the GPU to compute the lighting (which is what you want to do!)
	if(!g_manualLighting)
	{
		// turn on lighting
		enableLighting();

		// set the diffuse material colour (this will be modulated by the effect of the lighting)
		setColour(1.0f, 1.0f, 1.0f);

		// draw the cube geometry
		drawPrimitives(g_pointsVN, 24, kQuads);

		// turn off lighting
		disableLighting();
	}
	else
	{
		// otherwise, compute the lighting manually. Don't ever do this in practice! It's insane! (But it may be useful for educational purposes)

		// The direction from the vertex to the light (effectively sunlight in this case!).
		Vec3 L(-0.6f, 1.0f, -0.2f);

		// make sure L has been normalised!
		L = normalize(L);

		// start drawing some quads
		begin(kQuads);

		// loop through each vertex normal
		for(int i = 0; i < 24; ++i)
		{
			// compute N.L
			// Make sure we clamp this to zero (so that we ignore any negative values).
			float N_dot_L = std::max(dot(L, g_pointsVN[i].n), 0.0f);

			// the ambient material colour (always gets added to the final colour)
			Vec3 Ka(0.2f, 0.2f, 0.2f);

			// the diffuse material colour
			Vec3 Kd(1.0f, 1.0f, 1.0f);

			// Compute the final colour
			Vec3 colour = Ka + (Kd * N_dot_L);

			// set the vertex colour 
			setColour(colour);

			// specify the vertex
			addVertex(g_pointsVN[i].v);
		}

		// finish drawing our quads
		end();
	}

	// if we are displaying normals
	if(g_displayNormals)
	{
		// make colour pink
		setColour(1.0f, 0.0f, 1.0f);

		// loop through each vertex
		for(int i = 0; i < 24; ++i)
		{
			// compute an offset (along the normal direction) from the vertex
			Vec3 pn = g_pointsVN[i].v + (g_pointsVN[i].n * 0.2f);

			// draw a line to show the normal
			drawLine(g_pointsVN[i].v, pn);
		}
	}
}