Objectives

Grid

#pragma once
#include "actor.h"

struct Grid: public Actor
{
  Grid()
  {}

  void render()
  {
    const float RANGE = 15.0f;
    glLineWidth(5);
    glColor3f(0.0,1.0,0.0);
    glBegin(GL_LINES);
    for(int i=-5; i<=5; ++i) {
      float offset = 0.2*float(i)*RANGE;
      glVertex3f(-RANGE, 0, offset);
      glVertex3f( RANGE, 0, offset);
      glVertex3f( offset, 0,-RANGE);
      glVertex3f( offset, 0, RANGE);
    }
    glEnd();
    glLineWidth(1);
  }
};

Scene

#pragma once
#include "libs.h"
#include "model.h"
#include "actor.h"

struct Scene
{
  Scene();
  void loadActors(Model*);

  virtual Actor* loadActor(GeometryMap::value_type &amp;value);
  virtual void render();
  virtual void tick(float secondsDelta) {}

  ActorMap         actors;
};
#include "scene.h"
#include "colourcube.h"
#include "jetplane.h"
#include "grid.h"

using namespace std;

Scene:: Scene()
{
}

void Scene::loadActors(Model*model)
{
  string actorName;
  foreach (GeometryMap::value_type &amp;value, model->entities)
  {
    Actor* actor = loadActor(value);
    if (actor)
    {
      actorName = value.first;
      actors.insert(actorName, actor);
    }
  }
  actorName = "grid";
  actors.insert (actorName, new Grid());
}

Actor* Scene::loadActor(GeometryMap::value_type &amp;value)
{
  return new Actor(&amp;value.second);
}

void Scene::render()
{
  foreach (ActorMap::value_type value, actors)
  {
    value->second->render();
  }
}
  Scene *scene = new Scene ();
  scene->loadActors(model);
  theWorld.scene = scene;

AnimateScene

#pragma once
#include "libs.h"
#include "scene.h"
#include "animateactor.h"
#include "forcegeneratorregistry.h"

struct AnimateScene : public Scene
{
  AnimateScene();
  Actor* loadActor(GeometryMap::value_type &amp;value);

  void tick(float secondsDelta);

  AnimateActorMap        animateActors;
  ForceGeneratorRegistry forceGeneratorRegistry;
};
#include "animatescene.h"
#include "sphereactor.h"

using namespace std;

AnimateScene :: AnimateScene()
{
}

Actor* AnimateScene::loadActor(GeometryMap::value_type &amp;value)
{
  Actor *actor = 0;
  if (value.first == "pSphere1")
  {
    PhysicsActor * sphere = new SphereActor(&amp;value.second);
    actor = dynamic_cast<Actor*> (sphere);
    // create an anchor
    Vector3 anchor = sphere->position + Vector3(0,5,0);
    // create force generator
    AnchoredSpringForceGenerator * fg =
    new AnchoredSpringForceGenerator(anchor, 1.0, 3.0);
    // add actor<->forceGenerator pair to registry
    forceGeneratorRegistry.add(sphere, fg);
  }
  else if (value.first == "pSphere2" || value.first == "pSphere3")
  {
    actor = new SphereActor(&amp;value.second);
  }
  else
  {
    return Scene::loadActor(value);
  }
  if (actor)
  {
    animateActors[value.first] = (AnimateActor*) actor;
  }
  return actor;
}

void AnimateScene::tick(float secondsDelta)
{
  forceGeneratorRegistry.applyForce(secondsDelta);

  foreach (AnimateActorMap::value_type value, animateActors)
  {
    value.second->integrate(secondsDelta);
  }
}
  Scene *scene = new AnimateScene ();
  Scene *scene = new Scene ();

Materials

#pragma once
#include "libs.h"

enum MaterialTypes {flatRed, flatYellow, flatBlue, flatGreen, flatGray, plasticRed, shinyWhite, brass, bronze,
  chrome, copper, gold, pewter, silver, polishSilver, plasticBlack} ;

void applyMaterial(MaterialTypes material);
#include "libs.h"
#include "materials.h"

struct Material
{
  GLfloat ambient[4];
  GLfloat diffuse[4];
  GLfloat specular[4];
  GLfloat shiny;
};

Material materials [] =
{
    { {0.8, 0.0, 0.0, 1.0}, // flatRed
      {0.8, 0.0, 0.0, 1.0},
      {0.8, 0.0, 0.0, 1.0}, 25.0 },

    { {0.8, 0.0, 0.0, 1.0}, //flatYellow
      {0.8, 0.0, 0.0, 1.0},
      {0.8, 0.0, 0.0, 1.0}, 25.0 },

    { {0.0, 0.0, 0.8, 1.0}, // flatblue
      {0.0, 0.0, 0.8, 1.0},
      {0.0, 0.0, 0.8, 1.0}, 25.0 },

    { {0.0, 0.8, 0.0, 1.0}, // flatgreen
      {0.0, 0.8, 0.0, 1.0},
      {0.0, 0.8, 0.0, 1.0}, 25.0 },

    { {0.5, 0.5, 0.5, 1.0}, // flatgrey
      {0.5, 0.5, 0.5, 1.0},
      {0.5, 0.5, 0.5, 1.0}, 25.0 },

    { {0.3, 0.0, 0.0, 1.0}, //plasticRed
      {0.6, 0.0, 0.0, 1.0},
      {0.8, 0.6, 0.6, 1.0}, 32.0 },

    { {1.0, 1.0, 1.0, 1.0}, //shinyWhite
      {1.0, 1.0, 1.01, 1.0},
      {1.0, 1.0, 1.0, 1.0}, 100.0 },

    { {0.329412, 0.223529, 0.027451, 1.0}, //brass
      {0.780392, 0.568627, 0.113725, 1.0},
      {0.9922157, 0.941176, 0.807843, 1.0}, 27.8974 },

    { {0.2125, 0.1275, 0.054, 1.0}, //bronze
      {0.714, 0.4284, 0.18144, 1.0},
      {0.303548, 0.271906, 0.106721, 1.0}, 25.6 },

    { {0.25, 0.25, 0.25, 1.0}, //chrome
      {0.4, 0.4, 0.4, 1.0},
      {0.774597, 0.774597, 0.774597, 1.0}, 76.8 },

    { {0.19125, 0.0735, 0.0225, 1.0}, //copper
      {0.7038, 0.27048, 0.0828, 1.0},
      {0.256777, 0.137622, 0.086014, 1.0},  12.8 },

    { {0.24725, 0.1995, 0.0745, 1.0},// gold
      {0.75164, 0.60648, 0.22658, 1.0},
      {0.628281, 0.555802, 0.366065, 1.0},  51.2 },

    { {0.10558, 0.058824, 0.113725, 1.0}, //pewter
      {0.427451, 0.470588, 0.541176, 1.0},
      {0.3333, 0.3333, 0.521569, 1.0}, 9.84615 },

    { {0.19225, 0.19225, 0.19225, 1.0}, //silver
      {0.50754, 0.50754, 0.50754, 1.0},
      {0.508273, 0.508273, 0.508273, 1.0}, 51.2 },

    { {0.23125, 0.23125, 0.23125, 1.0}, //polishSilver
      {0.2775, 0.2775, 0.2775, 1.0},
      {0.773911, 0.773911, 0.773911, 1.0}, 89.6 },

    { {0.0, 0.0, 0.0, 1.0}, //plasticBlack
      {0.01, 0.01, 0.01, 1.0},
      {0.50, 0.50, 0.50, 1.0},32.0 }
};


void applyMaterial(MaterialTypes material)
{
  glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT,   materials[material].ambient);
  glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE,   materials[material].diffuse);
  glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR,  materials[material].specular);
  glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, materials[material].shiny);
}

Light

#pragma once
#include "libs.h"
#include "vector3.h"

struct LightSetting
{
  float*  components;
  int     type;
};

struct lttype
{
  bool operator() (const LightSetting&amp; s1, const LightSetting&amp; s2) const
  {
    return (s1.type < s2.type);
  }
};

struct AmbientLight
{
  enum AmbientLightSetting {fullLight, halfLight, defaultLight};

  AmbientLight(AmbientLightSetting setting);
  void switchOn();

  AmbientLightSetting setting;
};

struct SpotLight
{
  SpotLight (GLenum id, Vector3 p);
  void augment(LightSetting &amp;setting);

  void switchOn();
  void reposition();

  GLenum  id;
  Vector3 position;
  std::set<LightSetting, lttype> lightSettings;
};

struct ltspotlight
{
  bool operator() (const SpotLight&amp; s1, const SpotLight&amp; s2) const
  {
    return (s1.id < s2.id);
  }
};
typedef std::set<SpotLight, ltspotlight> SpotLightSet;
#include "light.h"

float settingTable[][4] =
{
  { 1.0f, 1.0f, 1.0f, 1.0f }, // full
  { 0.5f, 0.5f, 0.5f, 1.0f }, // half
  { 0.2f, 0.2f, 0.2f, 1.0f }  // default
};

AmbientLight::AmbientLight(AmbientLightSetting setting)
: setting(setting)
{
}

void AmbientLight::switchOn()
{
  glLightModelfv(GL_LIGHT_MODEL_AMBIENT, settingTable[setting]);
}

SpotLight::SpotLight (GLenum id, Vector3 p)
: id(id), position(p)
{
}

void SpotLight::augment(LightSetting &amp;setting)
{
  lightSettings.insert(setting);
}

void SpotLight::switchOn()
{
  foreach (LightSetting setting, lightSettings)
  {
    glLightfv(id, setting.type, setting.components);
  }
  glEnable(id);
}

void SpotLight::reposition()
{
  float pos[4];
  pos[0] = position.X;
  pos[1] = position.Y;
  pos[2] = position.Z;
  pos[3] = 1;

  glLightfv(id, GL_POSITION, pos);
}

LightingModel

#pragma once
#include "libs.h"
#include "light.h"

struct LightingModel
{
  LightingModel();
  void switchOnLights();
  void positionLights();

  SpotLightSet spotLights;
  AmbientLight ambientLight;
};
#include "lightingmodel.h"

float  ambientLightModerate[] = { 0.3f, 0.3f, 0.3f, 1.0f };
float  diffuseLightModerate[] = { 0.7f, 0.7f, 0.7f, 1.0f };

LightingModel::LightingModel()
: ambientLight(AmbientLight::fullLight)
{
  SpotLight spotLight0 ((GLenum)GL_LIGHT0, Vector3(-50, 50, 0));

  LightSetting setting1 = {ambientLightModerate, GL_AMBIENT};
  LightSetting setting2 = {diffuseLightModerate, GL_DIFFUSE};

  spotLight0.augment(setting1);
  spotLight0.augment(setting2);

  spotLights.insert(spotLight0);
}

void LightingModel::switchOnLights()
{
  ambientLight.switchOn();
  foreach (SpotLight spotLight, spotLights)
  {
    spotLight.switchOn();
  }
  glEnable(GL_NORMALIZE);
}

void LightingModel::positionLights()
{
  foreach (SpotLight spotLight, spotLights)
  {
    spotLight.reposition();
  }
}

World

  LightingModel  lightingModel;
void World::initialize(string name, int width, int height)
{
  int argc=0;
  char** argv;
  glutInit(&amp;argc, argv);

  glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
  glutInitWindowSize(width, height);
  glutCreateWindow(name.c_str());

  Color::Black.renderClear();
  glEnable(GL_DEPTH_TEST);
  glFrontFace(GL_CCW);
  glPolygonMode(GL_FRONT,GL_LINE);
  glPolygonMode(GL_BACK,GL_LINE);

  glutKeyboardFunc(keyboard);
  glutReshapeFunc(reshape);
  glutDisplayFunc(renderScene);
  glutSpecialFunc(keyboardSpecial);
  glutPassiveMotionFunc(::mouseMovement);

  glEnable(GL_LIGHTING);
  lightingModel.switchOnLights();
}
void World::render()
{
  Color::Blue.renderClear();
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  if (projectors.isPerspective())
  {
    glLoadIdentity();
    cameras.currentCamera->render();
  }
  lightingModel.positionLights();

  scene->render();

  glutSwapBuffers();
}
void Scene::loadActors(Model*model)
{
  //....
  actorName = "jet";
  actors.insert (actorName, new JetPlane());
}

Exercises

Solution:

Externalise Light Settings