/*
MainControl.cpp
Written by Matthew Fisher
MainControl includes everything that changes often between applications, such as what meshes to load,
and also determines what is rendered each frame.
See the appropriate header file for a description of what this class does.
*/
//All source files include Main.h
#include "Main.h"
const int ShapeCount = 3; //the number of shapes in the shape ring
const int TextureCount = 4; //the number of textures we're loading
void MainControl::InitShapes(GraphicsDevice &GD)
{
Shapes.Allocate(ShapeCount); //allocate room for 3 meshes
int i;
for(i=0;i<ShapeCount;i++)
Shapes[i].SetGD(GD); //associate the 3 meshes with the GD
//See BaseMesh.h for a full description of each shape creation functions
Shapes[0].CreatePlane(2.0f, 20, 20);
Shapes[0].Rotate(Vec3(1.0f,1.0f,1.0f)); //create and rotate a plane (rotation is not necessary.)
Shapes[1].CreateSphere(1.0f, 20, 20); //create a sphere using longitude/latitude slicing
Shapes[2].CreateCylinder(0.5f, 1.5f, 20, 20); //create a cylinder
//There is a problem with texture coordinates on the boundary of meshes. An edge may contain one edge
//with texture coordinates 0.99, and another edge with texture coordinates 0.0 (or something just above
//zero.) The graphics will interpret this as you want to go from 0.99 very, very rapidly to 0.0,
//while in fact you want to go from 0.99 to 1.0. A plane doesn't wrap around so this problem doesn't occur,
//and for a sphere or cylinder, the region where this occurs is well defined. Thus, to fix the problem
//we need to split the mesh along this edge, forcing it to duplicate vertices. More examples of the
//splitting functions will come in later examples. Comment out the lines up till "Shapes[2] += Temp2"
//if you want to see what the problem is.
Mesh Temp1, Temp2; //temporary meshes to store the intermediate splits
Plane p; //plane to split around
Temp1.SetGD(GD); Temp2.SetGD(GD); //associate the meshes with the graphics device
p.LoadPointNormal(Origin + eY*0.0001f, eY); //the plane to split about
//the eY*0.0001f is just some small epsilon to avoid equalities.
Shapes[1].PerfectSplit(p, Temp1, Temp2);
Shapes[1] = Temp1;
Shapes[1] += Temp2;
Shapes[2].PerfectSplit(p, Temp1, Temp2);
Shapes[2] = Temp1;
Shapes[2] += Temp2;
//we're going to arrange these 3 shapes on a ring.
for(i=0;i<ShapeCount;i++)
{
float Theta = i / float(ShapeCount) * 2.0f * PIf;
float Radius = 1.5f; //angle and radius around the ring
if(i != 0) //the plane already has a natural paramaterization
Shapes[i].TextureSphericalMap(0); //automatically generate texture coordinates for everything else;
//note that the cylinder should really use cylindrical coordinates
//but I haven't written such a function (although it's rather simple.)
Shapes[i].Translate(Vec3(cosf(Theta)*Radius,sinf(Theta)*Radius,0.0f)); //translate using polar coordinates
}
}
void MainControl::InitTextures(GraphicsDevice &GD)
{
Textures.Allocate(TextureCount);
Textures[0].Load(GD, "C:\\Code\\MyApps All2\\BaseCodeExamples\\texture1.bmp");
Textures[1].Load(GD, "C:\\Code\\MyApps All2\\BaseCodeExamples\\texture2.bmp");
Textures[2].Load(GD, "C:\\Code\\MyApps All2\\BaseCodeExamples\\texture3.bmp");
Textures[3].Load(GD, "C:\\Code\\MyApps All2\\BaseCodeExamples\\texture4.bmp"); //load the 4 textures
}
void MainControl::ReInit(GraphicsDevice &GD, WindowManager &WM)
{
if(GD.GetFullScreen()) C.Mouse(0.0f); //move the mouse to the middle of the screen
MC.Perspective.PerspectiveFov(60.0f * PIf / 180.0f, //the field of view = 60 degrees
float(WM.GetWidth()) / float(WM.GetHeight()), //the aspect ratio
0.1f, //near Z-plane
20.0f); //far Z-plane
InitTextures(GD); //inialize the textures. Since textures can be lost when the device loses focus or resizes,
//this goes inside ReInit, instead of Init.
}
void MainControl::Init(GraphicsDevice &GD, WindowManager &WM)
{
ReInit(GD, WM);
//initalize the camera
C.Reset(eX*4.0f, //the eye vector
eY, //the up vector
Origin); //the vector we're looking at
MC.World.Identity(); //zero the world and view matrices
MC.View.Identity();
InitShapes(GD); //initalize the shapes
CurTexture = 0; //start with the first texture
TotalRotation = Vec3(1.0f, 1.0f, 1.0f); //start with some simple rotation
CurrentVariable = 2; //start by rotating around the y-axis
SecondsUntilSwitch = 3.0f; //3 seconds until we switch the axis of rotation
Time = 0.0f; //reset the time to 0
}
void MainControl::Render(GraphicsDevice &GD, WindowManager &WM)
{
Time += T.SPF(); //advance the current time
if(KeyCheckOnce(KEY_F)) GD.ToggleWireframe(); //toggle wireframe if the user presses "F"
C.WindowKeyboard(1.0f,1.0f); //move based upon the keyboard
if(GD.GetFullScreen()) C.Mouse(0.001f); //move based upon the mouse, if we're in full-screen mode
C.Update(MC, GD); //update the camera and load it into the current graphics device
SecondsUntilSwitch -= T.SPF(); //decrement seconds left until we switch
if(SecondsUntilSwitch < 0.0f) //if we should switch this frame,
{
SecondsUntilSwitch = 3.0f; //reset the switch timer
CurrentVariable = rand() % 3; //change the variable
}
if(CurrentVariable == 0) TotalRotation.x += T.SPF();
if(CurrentVariable == 1) TotalRotation.y += T.SPF();
if(CurrentVariable == 2) TotalRotation.z += T.SPF(); //based upon the variable, update the rotation vector
Matrix RotationX, RotationY, RotationZ; //the 3 rotation matrices for the ring
RotationX.RotationX(TotalRotation.x);
RotationY.RotationY(TotalRotation.y);
RotationZ.RotationZ(TotalRotation.z); //load the rotation matrices
MC.World = RotationZ * RotationX * RotationY; //load the product of the 3 matrices as the world matrix,
GD.LoadMatrix(MC); //load this new matrix set into the graphics device
Textures[CurTexture].Set();
int i;
for(i=0;i<ShapeCount;i++)
Shapes[i].Render(); //draw all the shapes
//update CurTexture based upon keyboard input
if(KeyCheckOnce(KEY_NUMPADADD))
{
CurTexture++;
if(CurTexture == TextureCount) CurTexture = 0;
}
if(KeyCheckOnce(KEY_NUMPADSUBTRACT))
{
CurTexture--;
if(CurTexture < 0) CurTexture = TextureCount - 1;
}
GD.DrawVector("Camera - > ", C.VecEye, 0, 20); //draw the camera position as text on the screen
GD.DrawText("Use the + or - keys on the number pad to change the texture.", " ", 0, 40); //help
GD.DrawNumber("Current Texture -> ", CurTexture, 0, 60); //display the texture we're rendering
}
void MainControl::FreeMemory()
{
}