This is an archive of lab07a_wavefront_2:
but if you completed the lab, you should have this code already.
Clone that project, and call the new project lab07b_wavefront_3
Verify that the project runs and loads multiply object OBJ files.
typedef std::pair<float, float> Range;
struct Projection
{
Range windowSize;
void resize(Range size);
virtual void render()=0;
};
void Projection::resize(Range size)
{
windowSize = size;
}
With have to derived projections:
(1) Orthographic:
struct Orthographic: public Projection
{
Range xRange;
Range yRange;
Range zRange;
Orthographic(Range x, Range y, Range z);
void render();
};
struct Perspective : public Projection
{
float fovy;
Range zRange;
float zDistance;
Perspective (float fovy, Range zRange, float zDistance);
void render();
};
Orthographic::Orthographic(Range x, Range y, Range z)
: xRange(x), yRange(y), zRange(z)
{
}
void Orthographic::render()
{
glLoadIdentity();
glViewport(0, 0, windowSize.first, windowSize.second);
glMatrixMode ( GL_PROJECTION);
glLoadIdentity();
glOrtho(xRange.first, xRange.second, yRange.first, yRange.second, zRange.first, zRange.second);
glMatrixMode ( GL_MODELVIEW);
}
Perspective::Perspective (float fovy, Range zRange, float zDistance)
: fovy(fovy), zRange(zRange), zDistance(zDistance)
{
}
void Perspective::render()
{
glLoadIdentity();
glViewport(0, 0, windowSize.first, windowSize.second);
glMatrixMode (GL_PROJECTION);
glLoadIdentity();
gluPerspective(fovy, windowSize.first/windowSize.second, zRange.first, zRange.second);
glMatrixMode (GL_MODELVIEW);
Vector3(0,0,zDistance).translate();
}
class World
{
public:
static World& GetInstance();
void setCmdlineParams(int*argc, char **argv);
void initialize(int width, int height, std::string name);
void start();
void loadModel (std::string modelName);
void render();
void keyPress(unsigned char ch);
private:
static World* s_World;
Model theModel;
int *argc;
char **argv;
};
struct World
{
static World& GetInstance();
void setCmdlineParams(int*argc, char **argv);
void initialize(int width, int height, std::string name);
void start();
void loadModel (std::string modelName);
void render();
void keyPress(unsigned char ch);
static World* s_World;
Model theModel;
Projection *currentProjection;
ProjectionMap projections;
int *argc;
char **argv;
};
Introduce a new member, which will be the current projection in force:
///
Projection *currentProjection;
///
void reshape(int w, int h)
{
theWorld.currentProjection->resize(Range(w,h));
theWorld.currentProjection->render();
}
int main(int argc, char* argv[])
{
theWorld.setCmdlineParams(&argc, argv);
theWorld.initialize(800,600, "First World");
theWorld.loadModel("model.obj");
theWorld.currentProjection = new Orthographic (Range(-10,10), Range(-10,10), Range(-10,10));
theWorld.start();
return 0;
}
Run and verify the projection is Orthographic
We could replace the projection model, recompile, and run again with the following:
//theWorld.currentProjection = new Orthographic (Range(-10,10), Range(-10,10), Range(-10,10));
theWorld.currentProjection = new Perspective(60, Range(1,1000), -10);
struct Orthographic: public Projection
{
Range xRange;
Range yRange;
Range zRange;
Vector3 axis;
int angle;
Orthographic(Range x, Range y, Range z, int angle, Vector3 axis);
void render();
};
Orthographic::Orthographic(Range x, Range y, Range z, int theAngle, Vector3 theAxis)
: xRange(x), yRange(y), zRange(z), angle(theAngle), axis(theAxis)
{
}
void Orthographic::render()
{
glLoadIdentity();
glViewport(0, 0, windowSize.first, windowSize.second);
glMatrixMode ( GL_PROJECTION);
glLoadIdentity();
glOrtho(xRange.first, xRange.second, yRange.first, yRange.second, zRange.first, zRange.second);
glMatrixMode ( GL_MODELVIEW);
axis.rotate(angle);
}
Projection *projection1 = new Orthographic (Range(-10,10), Range(-10,10), Range(-10,10), 90, Vector3::UnitX);
Projection *projection2 = new Orthographic (Range(-10,10), Range(-10,10), Range(-10,10), 90, Vector3::UnitY);
Projection *projection3 = new Orthographic (Range(-10,10), Range(-10,10), Range(-10,10), 90, Vector3::UnitZ);
Devise a design to have the projections switched at runtime by pressing key 1-4 along the following lines:
'1': Perspective
'2': Orthographic - viewing from above
'3': Orthographic - viewing from the left
'4': Orthographic - viewing from the right
All of this should be possible by just adjusting these two functions:
void reshape(int w, int h)
{
theWorld.currentProjection->resize(Range(w,h));
theWorld.currentProjection->render();
}
void World::keyPress(unsigned char ch)
{
///
glutPostRedisplay();
}
With some of the initialisation taking place in main.
Just to get this working, use a simple array or a vector
For a more sophisticated solution, see if you can implement a solution whereby you maintain a std::map of Projections, a reference to the current projection, and a simple mechanism for switching projections by retrieving a keyed element from the map.
Install the boost libraries:
Instructions here:
http://www.boost.org/doc/libs/1_49_0/more/getting_started/windows.html
http://www.boost.org/doc/libs/1_49_0/more/getting_started/unix-variants.html
For what we need, there may not even be a requirement to compile - but proceed through the build process - only if it goes smoothly.
However, if it doesnt, then we can still use the majority of the boost features - the so-called 'header only' components:
http://www.boost.org/doc/libs/1_33_1/?view=filtered_header-only
Try one of the examples here to verify that it builds successfully:
Have a look at this loop here in our model class:
void Model::render()
{
for (MeshMapIterator iter = entities.begin(); iter ##= entities.end(); iter++)
{
iter->second.render(defaultGroup.vertices);
}
}
Can you find a way of using foreach to replace this loop?
We are particularly interested in this component here:
http://www.boost.org/doc/libs/1_49_0/libs/ptr_container/doc/tutorial.html
See if you can build some of the example code in this tutorial