Orthographic Projection Clarification

Okay so I am using Bullet Physics with FreeGlut for rendering.
Bullet Physics uses meters for its units.
In order for me to perform orthographic projection, it seems like I would have to normalize the the vertex coordinates to be from -1 to 1 in the x direction and -1 to 1 in the y direction?
I also played around with the depth and it seems like I can only render things with a z-depth between 0 and 1. Is that correct?
I did this to set up my projection matrix
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2d(-1,1,-1,1); // This doesn’t seem to do anything (?)
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

To look at things I use
gluLookAt(m_cameraPosX, m_cameraPosY, 0.0, m_cameraPosX, m_cameraPosY, -1.0f, 0.0, 1.0, 0.0);

Does the above code mean that I am looking down the negative z axis? I can only see things with a z axis from 0 to 1, which I don’t understand.
Also, how does the aspect ratio fit into all this?
My window is 1024 width x768 height. If the viewport goes from [-1,1] x-direction and [-1,1] y-direction then does that mean that the 1024 pixels have to fit into 2 of the x-direction and 768 pixels have to fit into 2 in the y direction?
How can I make it so my viewport can match nicely with my resolution?
Also, is there a way that I can automatically render in units of meters without having to normalize between -1 to 1 to display into the viewport?

[QUOTE=jchen114;1282512]Okay so I am using Bullet Physics with FreeGlut for rendering.
Bullet Physics uses meters for its units.
In order for me to perform orthographic projection, it seems like I would have to normalize the the vertex coordinates to be from -1 to 1 in the x direction and -1 to 1 in the y direction?
[/QUOTE]
No, that’s essentially what an orthographic projection does for you. You pass the coordinates of the top/bottom/left/right edges in your chosen coordinate system to glOrtho() or gluOrtho2D() to generate a transformation which maps the given rectangle to the viewport.

gluOrtho2D() sets the near and far planes to Z=1 and Z=-1 respectively. If you want to use other values, use glOrtho() instead. As the name implies, gluOrtho2D() is designed for 2D rendering, where Z=0.

Calling gluOrtho2D() with those parameters almost creates an identity transformation, except that the Z direction is inverted. Conventionally, eye coordinates have negative Z in front of the viewpoint, positive Z behind. Clip coordinates and normalised device coordinates are the other way around, so the conventional projection transformations generated by glOrtho(), glFrustum(), gluOrtho2D() and gluPerspective() all invert the Z direction.

Yes.

It should be -1 to 1.

You’d normally choose the parameters to glOrtho() or gluOrtho2D() so that (right-left)/(top-bottom) has the same aspect ratio as the viewport. Ideally, you’d compute the aspect ratio based upon physical dimensions to allow for the case where you have non-square pixels (e.g. a full-screen window with a 5:4 or 4:3 aspect ratio being stretched to fit a wide-screen monitor), but if you don’t need to handle that case you can just use the aspect ratio in pixels.

Yes.

[QUOTE=jchen114;1282512]
How can I make it so my viewport can match nicely with my resolution?
Also, is there a way that I can automatically render in units of meters without having to normalize between -1 to 1 to display into the viewport?[/QUOTE]
The answer to both of these is to calculate the correct parameters for glOrtho() rather than using -1,1.

Hello.

So when using gluOrtho2D in my project, if I specify that the viewport be between -200,200 and -100,100 like :
gluOrtho2D(-200,200,-200,200);
I should be able to see a box that I created if it is say centered at (100,100) with a width of 50 and height of 100?
For some reason the gluOrtho2D still requires me to normalize everything between -1 and 1. When I take it out of the code it doesn’t have any effect either.
Are there any troubleshooting things that I could look out for? Is it possible that something can clear the viewport and reset it to be between -1 and 1?

First, you’re not using shaders, right? If you are, the matrix functions don’t (directly) have any effect.

Given that this should be a fairly basic program, it should be feasible to post the entire program (use

 tags to preserve formatting).

This is pretty much all the code I’m working with.
Heres my github repo that I’m working on: https://github.com/jchen114/Walking-Rag-Doll.git

The projection code is in CameraManager, but if anything else is weird I’d like to be aware of that too.
Thanks a lot!

// Falling Boxes.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "FreeGLUTCallbacks.h"
#include "RagDollApplication.h"



int main(int argc, char **argv)
{

	RagDollApplication ragDoll(ORTHOGRAPHIC);
	return glutmain(argc, argv, 1000, 1000, "Rag Doll", &ragDoll);
}

FreeGlutCallbacks.h:

#ifndef _FREEGLUTCALLBACKS_H_
#define _FREEGLUTCALLBACKS_H_

#include "BulletOpenGLApplication.h"

// global pointer to our application object
static BulletOpenGLApplication* g_pApp;

/** Various static functions that will be handed to FreeGLUT to be called
during various events (our callbacks). Each calls an equivalent function
in our (global) application object. **/
static void KeyboardCallback(unsigned char key, int x, int y) {
	g_pApp->Keyboard(key, x, y);
}
static void KeyboardUpCallback(unsigned char key, int x, int y) {
	g_pApp->KeyboardUp(key, x, y);
}
static void SpecialCallback(int key, int x, int y) {
	printf("Special key pressed
");
	g_pApp->Special(key, x, y);
}
static void SpecialUpCallback(int key, int x, int y) {
	g_pApp->SpecialUp(key, x, y);
}
static void ReshapeCallback(int w, int h) {
	g_pApp->Reshape(w, h);
}
static void IdleCallback() {
	g_pApp->Idle();
}
static void MouseCallback(int button, int state, int x, int y) {
	g_pApp->Mouse(button, state, x, y);
}
static void MotionCallback(int x, int y) {
	g_pApp->Motion(x, y);
}
static void DisplayCallback(void) {
	g_pApp->Display();
}

// our custom-built 'main' function, which accepts a reference to a 
// BulletOpenGLApplication object.
int glutmain(int argc, char **argv, int width, int height, const char* title, BulletOpenGLApplication* pApp) {
	// store the application object so we can
	// access it globally
	g_pApp = pApp;

	// initialize the window
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
	glutInitWindowPosition(0, 0);
	glutInitWindowSize(width, height);
	glutCreateWindow(title);
	glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_GLUTMAINLOOP_RETURNS);

	// perform custom initialization our of application
	g_pApp->SetScreenWidth(width);
	g_pApp->SetScreenHeight(height);
	g_pApp->Initialize();

	// give our static
	glutKeyboardFunc(KeyboardCallback);
	glutKeyboardUpFunc(KeyboardUpCallback);
	glutSpecialFunc(SpecialCallback);
	glutSpecialUpFunc(SpecialUpCallback);
	glutReshapeFunc(ReshapeCallback);
	glutIdleFunc(IdleCallback);
	glutMouseFunc(MouseCallback);
	glutPassiveMotionFunc(MotionCallback);
	glutMotionFunc(MotionCallback);
	glutDisplayFunc(DisplayCallback);

	// perform one render before we launch the application
	g_pApp->Idle();

	// hand application control over to the FreeGLUT library.
	// This function remains in a while-loop until the
	// application is exited.
	glutMainLoop();
	return 0;
}
#endif

RagDollApplication.h:

#pragma once
#include "BulletOpenGLApplication.h"

class RagDollApplication :
	public BulletOpenGLApplication
{
public:
	RagDollApplication();
	RagDollApplication(ProjectionMode mode);
	~RagDollApplication();

	virtual void InitializePhysics() override;
	virtual void ShutdownPhysics() override;
	
	void CreateRagDoll(const btVector3 &position);

	GameObject *Create2DBox(const btVector3 &halfSize, float mass, const btVector3 &color, const btVector3 &position);
	GameObject *Create3DBox(const btVector3 &halfSize, float mass, const btVector3 &color, const btVector3 &position);

	btVector3 GetRandomColor();

};

RagDollApplication.cpp:

#include "stdafx.h"
#include "RagDollApplication.h"


RagDollApplication::RagDollApplication()
{
}

RagDollApplication::RagDollApplication(ProjectionMode mode) :BulletOpenGLApplication(mode){}


RagDollApplication::~RagDollApplication()
{
}

void RagDollApplication::InitializePhysics() {

	// create the collision configuration
	m_pCollisionConfiguration = new btDefaultCollisionConfiguration();
	// create the dispatcher
	m_pDispatcher = new btCollisionDispatcher(m_pCollisionConfiguration);

	// Adding for 2D collisions and solving
	m_pDispatcher->registerCollisionCreateFunc(BOX_2D_SHAPE_PROXYTYPE, BOX_2D_SHAPE_PROXYTYPE, new btBox2dBox2dCollisionAlgorithm::CreateFunc());

	// create the broadphase
	m_pBroadphase = new btDbvtBroadphase();
	// create the constraint solver
	m_pSolver = new btSequentialImpulseConstraintSolver();
	// create the world
	m_pWorld = new btDiscreteDynamicsWorld(m_pDispatcher, m_pBroadphase, m_pSolver, m_pCollisionConfiguration);

	// Create ground
	btVector3 ground(1.0f, 25.0f, 10.0f);
	float mass = 0.0f;
	btVector3 position(0.0f, -10.0f, 0.0f);
	Create3DBox(ground, mass, GetRandomColor(), position);

	CreateRagDoll(btVector3(0, 3, 0.5));

}

void RagDollApplication::CreateRagDoll(const btVector3 &position) {

	// MASS
	float torso_mass = 70;
	float upper_leg_mass = 5;
	float lower_leg_mass = 4;
	float feet_mass = 1;

	// DIMENSIONS
	float torso_width = 1;
	float torso_height = 2.5;

	float upper_leg_height = 3.0f;
	float upper_leg_width = 0.7f;

	float lower_leg_height = 3.0f;
	float lower_leg_width = 0.5f;

	float foot_height = 0.3;
	float foot_width = 0.9;

	// Create a torso centered at the position
	btVector3 halfSize(torso_height/2, torso_width/2, 0.0);
	
	GameObject *torso = Create2DBox(halfSize, torso_mass, GetRandomColor(), position);

	// test box
	//Create2DBox(halfSize, mass, GetRandomColor(), btVector3(-4, 5, 0.7));
	//Create2DBox(halfSize, mass, GetRandomColor(), btVector3(4, 7, 0.5));

	// Create Upper legs
	halfSize = btVector3(upper_leg_height / 2, upper_leg_width / 2, 0.0f);
	btVector3 pos1 = position;
	pos1.setZ(pos1.getZ() - 0.25);
	GameObject *leftUpperLeg = Create2DBox(halfSize, upper_leg_mass, GetRandomColor(), pos1);
	btVector3 pos2 = position;
	pos2.setZ(pos2.getZ() + 0.25);
	GameObject *rightUpperLeg = Create2DBox(halfSize, upper_leg_mass, GetRandomColor(), pos2);

	// Create lower legs
	halfSize = btVector3(lower_leg_height / 2, lower_leg_width / 2, 0.0f);
	btVector3 pos3 = position;
	pos3.setZ(pos3.getZ() - 0.27);
	GameObject *leftLowerLeg = Create2DBox(halfSize, lower_leg_mass, GetRandomColor(), pos3);
	btVector3 pos4 = position;
	pos4.setZ(pos4.getZ() + 0.27);
	GameObject *rightLowerLeg = Create2DBox(halfSize, lower_leg_mass, GetRandomColor(), pos4);

	// Create feet
	halfSize = btVector3(foot_height / 2, foot_width / 2, 0.0f);
	btVector3 pos5 = position;
	pos5.setZ(pos5.getZ() - 0.28);
	GameObject *leftFoot = Create2DBox(halfSize, feet_mass, GetRandomColor(), pos5);
	halfSize = btVector3(foot_height / 2, foot_width / 2, 0.0f);
	btVector3 pos6 = position;
	pos6.setZ(pos6.getZ() + 0.28);
	GameObject *rightFoot = Create2DBox(halfSize, feet_mass, GetRandomColor(), pos6);

	// Connect torso to upper legs
	AddHingeConstraint(torso, leftUpperLeg, btVector3(-1, 0, 0), btVector3(1, 0, 0), btVector3(0, 0, 1), btVector3(0, 0, 1), Constants::GetInstance().DegreesToRadians(-30.0f), Constants::GetInstance().DegreesToRadians(-30.0f));
	AddHingeConstraint(torso, rightUpperLeg, btVector3(-1, 0, 0), btVector3(1, 0, 0), btVector3(0, 0, 1), btVector3(0, 0, 1), Constants::GetInstance().DegreesToRadians(30.0f), Constants::GetInstance().DegreesToRadians(30.0f));

	// Connect upper legs to lower legs
	AddHingeConstraint(leftUpperLeg, leftLowerLeg, btVector3(-1.5, 0, 0), btVector3(1, 0, 0), btVector3(0, 0, 1), btVector3(0, 0, 1), Constants::GetInstance().DegreesToRadians(0.0f), Constants::GetInstance().DegreesToRadians(0.0f));
	AddHingeConstraint(rightUpperLeg, rightLowerLeg, btVector3(-1.5, 0, 0), btVector3(1, 0, 0), btVector3(0, 0, 1), btVector3(0, 0, 1), Constants::GetInstance().DegreesToRadians(0.0f), Constants::GetInstance().DegreesToRadians(0.0f));

	// Connect feet to lower legs
	AddHingeConstraint(leftLowerLeg, leftFoot, btVector3(-lower_leg_height / 2, 0, 0), btVector3(0, foot_width / 2, 0), btVector3(0, 0, 1), btVector3(0, 0, 1), Constants::GetInstance().DegreesToRadians(20.0f), Constants::GetInstance().DegreesToRadians(20.0f));
	AddHingeConstraint(rightLowerLeg, rightFoot, btVector3(-lower_leg_height / 2, 0, 0), btVector3(0, foot_width / 2, 0), btVector3(0, 0, 1), btVector3(0, 0, 1), Constants::GetInstance().DegreesToRadians(20.0f), Constants::GetInstance().DegreesToRadians(20.0f));
}


void RagDollApplication::ShutdownPhysics() {

}

GameObject *RagDollApplication::Create2DBox(const btVector3 &halfSize, float mass, const btVector3 &color, const btVector3 &position) {

	GameObject *aBox = CreateGameObject(new btBox2dShape(halfSize), mass, color, position);
	return aBox;
}

GameObject *RagDollApplication::Create3DBox(const btVector3 &halfSize, float mass, const btVector3 &color, const btVector3 &position) {
	GameObject *aBox = CreateGameObject(new btBoxShape(halfSize), mass, color, position);
	return aBox;
}


btVector3 RagDollApplication::GetRandomColor() {
	return btVector3(((double)rand() / RAND_MAX), ((double)rand() / RAND_MAX), ((double)rand() / RAND_MAX));
}

BulletOpenGLApplication

#ifndef _BULLETOPENGLAPP_H_
#define _BULLETOPENGLAPP_H_

#include <Windows.h>
#include <gl\GL.h>
#include <freeglut\freeglut.h>

#include "BulletDynamics\Dynamics\btDynamicsWorld.h"

// Includes for 2D Boxes and collision between 2D Boxes
#include "BulletCollision\CollisionShapes\btBox2dShape.h"
#include "BulletCollision\CollisionDispatch\btBox2dBox2dCollisionAlgorithm.h"

// Our custom debug renderer
#include "DebugDrawer.h"

// Includes a custom motion state object
#include "OpenGLMotionState.h"

#include "CameraManager.h"

// Constants
#include "Constants.h"

#include "GameObject.h"
#include <vector>

class DebugDrawer;

typedef std::vector<GameObject*> GameObjects; // GameObjects is a data type for storing game objects

class BulletOpenGLApplication
{
public:
	BulletOpenGLApplication();
	BulletOpenGLApplication(ProjectionMode mode);

	~BulletOpenGLApplication();

	void Initialize();

	// FreeGLUT callbacks //
	virtual void Keyboard(unsigned char key, int x, int y);
	virtual void KeyboardUp(unsigned char key, int x, int y);
	virtual void Special(int key, int x, int y);
	virtual void SpecialUp(int key, int x, int y);
	virtual void Reshape(int w, int h);
	virtual void Idle();
	virtual void Mouse(int button, int state, int x, int y);
	virtual void PassiveMotion(int x, int y);
	virtual void Motion(int x, int y);
	virtual void Display();

	// rendering. Can be overrideen by derived classes
	virtual void RenderScene();

	// scene updating. Can be overridden by derived classes
	virtual void UpdateScene(float dt);

	// physics functions. Can be overridden by derived classes (like BasicDemo)
	virtual void InitializePhysics() {};
	virtual void ShutdownPhysics() {};

	// Drawing Functions
	void DrawBox(const btVector3 &halfSize);
	void DrawPlane(const btVector3 &halfSize);
	void DrawShape(btScalar *transform, const btCollisionShape *pShape, const btVector3 &color);
	void DrawWithTriangles(const btVector3 * vertices, const int *indices, int numberOfIndices);

	void SetScreenWidth(int width);
	void SetScreenHeight(int height);

	// Object Functions

	void AddHingeConstraint(
		GameObject *obj1, 
		GameObject *obj2, 
		const btVector3 &pivot1, 
		const btVector3 &pivot2, 
		const btVector3 &axis1, 
		const btVector3 &axis2,
		btScalar lowLimit,
		btScalar highLimit);

	GameObject *CreateGameObject(
		btCollisionShape *pShape, 
		const float &mass, 
		const btVector3 &color = btVector3(1.0f, 1.0f, 1.0f), 
		const btVector3 &initialPosition = btVector3(0.0f, 0.0f, 0.0f),
		const btQuaternion &initialRotation = btQuaternion(0, 0, 1, 1)
		);	

protected:

	// core Bullet Components
	btBroadphaseInterface *m_pBroadphase;
	btCollisionConfiguration *m_pCollisionConfiguration;
	btCollisionDispatcher *m_pDispatcher;
	btConstraintSolver *m_pSolver;
	btDynamicsWorld *m_pWorld;

	// clock for counting time
	btClock m_clock;

	// Array for game objects
	GameObjects m_objects;

	// Camera Manager
	CameraManager *m_cameraManager;

	// Debugging
	// debug renderer
	DebugDrawer* m_pDebugDrawer;

};

#endif

BulletOpenGLApplication.cpp:

#include "stdafx.h"
#include "BulletOpenGLApplication.h"
#include <iostream>

BulletOpenGLApplication::BulletOpenGLApplication()
{
	std::cout << "Constructing BulletOpenGLApplication and building camera" << std::endl;
	// Create Camera manager
	m_cameraManager = new CameraManager(
		btVector3(0.0f, 0.0f, 0.0f),	// Target
		30.0f,							// Distance
		20.0f,							// Pitch
		0.0f,							// Yaw
		btVector3(0.0f, 1.0f, 0.0f),	// Up Vector
		1.0f,							// near plane
		1000.0f);						// far plane
}

BulletOpenGLApplication::BulletOpenGLApplication(ProjectionMode mode) : BulletOpenGLApplication() {
	std::cout << "Constructing BulletOpenGLApplication and building camera" << std::endl;
	Constants::GetInstance().SetProjectionMode(mode);
}

BulletOpenGLApplication::~BulletOpenGLApplication() {
	// Shutdown physics system
	ShutdownPhysics();
}

void BulletOpenGLApplication::Initialize() {
	std::cout << "Initializing BulletOpenGLApplication" << std::endl;
	// this function is called inside glutmain() after
	// creating the window, but before handing control
	// to FreeGLUT

	// create some floats for our ambient, diffuse, specular and position
	GLfloat ambient[] = { 0.2f, 0.2f, 0.2f, 1.0f }; // dark grey
	GLfloat diffuse[] = { 1.0f, 1.0f, 1.0f, 1.0f }; // white
	GLfloat specular[] = { 1.0f, 1.0f, 1.0f, 1.0f }; // white
	GLfloat position[] = { 5.0f, 10.0f, 1.0f, 0.0f };

	// set the ambient, diffuse, specular and position for LIGHT0
	glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
	glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
	glLightfv(GL_LIGHT0, GL_SPECULAR, specular);
	glLightfv(GL_LIGHT0, GL_POSITION, position);

	glEnable(GL_LIGHTING); // enables lighting
	glEnable(GL_LIGHT0); // enables the 0th light
	glEnable(GL_COLOR_MATERIAL); // colors materials when lighting is enabled

	// enable specular lighting via materials
	glMaterialfv(GL_FRONT, GL_SPECULAR, specular);
	glMateriali(GL_FRONT, GL_SHININESS, 15);

	// enable smooth shading
	glShadeModel(GL_SMOOTH);

	// enable depth testing to be 'less than'
	glEnable(GL_DEPTH_TEST);
	glDepthFunc(GL_LESS);

	// Disable Culling
	glDisable(GL_CULL_FACE);

	// set the backbuffer clearing color to a lightish blue
	glClearColor(0.6, 0.65, 0.85, 0);

	// initialize the physics system
	InitializePhysics();

	// create the debug drawer
	m_pDebugDrawer = new DebugDrawer();
	// set the initial debug level to 0
	m_pDebugDrawer->setDebugMode(0);
	// add the debug drawer to the world
	m_pWorld->setDebugDrawer(m_pDebugDrawer);

}

void BulletOpenGLApplication::SetScreenWidth(int width) {
	Constants::GetInstance().SetScreenWidth(width);
}

void BulletOpenGLApplication::SetScreenHeight(int height) {
	Constants::GetInstance().SetScreenHeight(height);
}

void BulletOpenGLApplication::Keyboard(unsigned char key, int x, int y) {
	// This function is called by FreeGLUT whenever
	// generic keys are pressed down.
	// Common to all projection types
	switch (key)
	{
	case 'v': {
		// toggle wireframe debug drawing
		m_pDebugDrawer->ToggleDebugFlag(btIDebugDraw::DBG_DrawWireframe);
		printf("toggle debug wireframe
");
	}
		break;
	case 'b': {
		// toggle AABB debug drawing
		m_pDebugDrawer->ToggleDebugFlag(btIDebugDraw::DBG_DrawAabb);
		printf("toggle debug flag
");
	}
		break;
	case 'z': m_cameraManager->ZoomCamera(+CAMERA_STEP_SIZE); break;			// 'z' zooms in
	case 'x': m_cameraManager->ZoomCamera(-CAMERA_STEP_SIZE); break;			// 'x' zoom out
	case 'w': m_cameraManager->TranslateCamera(UP, CAMERA_STEP_SIZE); break;
	case 'a': m_cameraManager->TranslateCamera(LEFT, CAMERA_STEP_SIZE); break;
	case 's': m_cameraManager->TranslateCamera(DOWN, -CAMERA_STEP_SIZE); break;
	case 'd': m_cameraManager->TranslateCamera(RIGHT, -CAMERA_STEP_SIZE); break;

	default:
		break;
	}
	
}

void BulletOpenGLApplication::KeyboardUp(unsigned char key, int x, int y) {}

void BulletOpenGLApplication::Special(int key, int x, int y) {
	// This function is called by FreeGLUT whenever special keys
	// are pressed down, like the arrow keys, or Insert, Delete etc.
	printf("Received Special Key
");

	switch (key) {
		// the arrow keys rotate the camera up/down/left/right
	case GLUT_KEY_LEFT:
		m_cameraManager->RotateCamera(YAW, +CAMERA_STEP_SIZE); break;
	case GLUT_KEY_RIGHT:
		m_cameraManager->RotateCamera(YAW, -CAMERA_STEP_SIZE); break;
	case GLUT_KEY_UP:
		m_cameraManager->RotateCamera(PITCH, +CAMERA_STEP_SIZE); break;
	case GLUT_KEY_DOWN:
		m_cameraManager->RotateCamera(PITCH, -CAMERA_STEP_SIZE); break;
	}
	
}

void BulletOpenGLApplication::SpecialUp(int key, int x, int y) {}

void BulletOpenGLApplication::Reshape(int w, int h) {
	printf("BulletOpenGLApplication Reshape called
");
	// this function is called once during application intialization
	// and again every time we resize the window

	// set the viewport
	glViewport(0, 0, w, h);

	Constants::GetInstance().SetScreenWidth(w);
	Constants::GetInstance().SetScreenHeight(h);

	// update the camera
	m_cameraManager->UpdateCamera();
	//m_cameraManager->PrintCameraLocation();
	
}

void BulletOpenGLApplication::Idle() {
	// this function is called frequently, whenever FreeGlut
	// isn't busy processing its own events. It should be used
	// to perform any updating and rendering tasks

	// clear the backbuffer
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	// get the time since the last iteration
	float dt = m_clock.getTimeMilliseconds();
	// reset the clock to 0
	m_clock.reset();
	// update the scene (convert ms to s)
	UpdateScene(dt / 1000.0f);

	m_cameraManager->UpdateCamera();

	// render the scene
	RenderScene();

	// swap the front and back buffers
	glutSwapBuffers();
}

void BulletOpenGLApplication::Mouse(int button, int state, int x, int y) {}
void BulletOpenGLApplication::PassiveMotion(int x, int y) {}
void BulletOpenGLApplication::Motion(int x, int y) {}
void BulletOpenGLApplication::Display() {}

void BulletOpenGLApplication::DrawBox(const btVector3 &halfSize) {
	float halfWidth = halfSize.x();
	float halfHeight = halfSize.y();
	float halfDepth = halfSize.z();

	// Create vertex positions
	btVector3 vertices[8] = {
		btVector3(halfWidth, halfHeight, halfDepth),
		btVector3(halfWidth, halfHeight, -halfDepth),
		btVector3(halfWidth, -halfHeight, halfDepth),
		btVector3(halfWidth, -halfHeight, -halfDepth),
		btVector3(-halfWidth, halfHeight, halfDepth),
		btVector3(-halfWidth, halfHeight, -halfDepth),
		btVector3(-halfWidth, -halfHeight, halfDepth),
		btVector3(-halfWidth, -halfHeight, -halfDepth)
	};

	// create the indexes for each triangle, using the 
	// vertices above. Make it static so we don't waste 
	// processing time recreating it over and over again
	static int indices[36] = {
			0, 1, 2,
			3, 2, 1,
			4, 0, 6,
			6, 0, 2,
			5, 1, 4,
			4, 1, 0,
			7, 3, 1,
			7, 1, 5,
			5, 4, 7,
			7, 4, 6,
			7, 2, 3,
			7, 6, 2 };

	DrawWithTriangles(vertices, indices, 36);
}

void BulletOpenGLApplication::DrawPlane(const btVector3 &halfSize) {
	

	float halfWidth = halfSize.x();
	float halfHeight = halfSize.y();
	float halfDepth = halfSize.z(); // No depth

	// Create Vector
	btVector3 vertices[4] = {
		btVector3(-halfWidth, -halfHeight, 0.0f),
		btVector3(-halfWidth, halfHeight, 0.0f),
		btVector3(halfWidth, -halfHeight, 0.0f),
		btVector3(halfWidth, halfHeight, 0.0f),
	};

	// NORMALIZE VERTICES TO DRAW IN ORTHOGRAPHIC (?)
	if (Constants::GetInstance().GetProjectionMode() == ORTHOGRAPHIC)
	{
		// Normalize vertices between -1 and 1
		for (int index = 0; index < 4; index++) {

			btVector3 *vec = &vertices[index];
			vec->setX(Constants::GetInstance().Normalize(vec->getX(), 0, HEIGHT));
			vec->setY(Constants::GetInstance().Normalize(vec->getY(), 0, WIDTH));
			//printf("(x,y) = (%f,%f)
", vec->getX(), vec->getY());

		}
	}

	// create the indexes for each triangle, using the 
	// vertices above. Make it static so we don't waste 
	// processing time recreating it over and over again
	static int indices[6] = {
		0, 1, 2,
		3, 2, 1
	};

	DrawWithTriangles(vertices, indices, 6);
}

void BulletOpenGLApplication::DrawWithTriangles(const btVector3 *vertices, const int *indices, int numberOfIndices) {

	// start processing vertices as triangles
	glBegin(GL_TRIANGLES);

	// increment the loop by 3 each time since we create a 
	// triangle with 3 vertices at a time.

	for (int i = 0; i < numberOfIndices; i+=3) {
		// get the three vertices for the triangle based
		// on the index values set above
		// use const references so we don't copy the object
		// (a good rule of thumb is to never allocate/deallocate
		// memory during *every* render/update call. This should 
		// only happen sporadically)
		const btVector3 &vert1 = vertices[indices[i]];
		const btVector3 &vert2 = vertices[indices[i + 1]];
		const btVector3 &vert3 = vertices[indices[i + 2]];

		// create a normal that is perpendicular to the 
		// face (use the cross product)
		btVector3 normal = (vert3 - vert1).cross(vert2 - vert1);
		normal.normalize();

		// set the normal for the subsequent vertices
		glNormal3f(normal.getX(), normal.getY(), normal.getZ());

		// create the vertices
		glVertex3f(vert1.x(), vert1.y(), vert1.z());
		glVertex3f(vert2.x(), vert2.y(), vert2.z());
		glVertex3f(vert3.x(), vert3.y(), vert3.z());
	}
	glEnd();
}


void BulletOpenGLApplication::RenderScene() {

	// create an array of 16 floats (representing a 4x4 matrix)
	btScalar transform[16];

	// iterate through all of the objects in our world
	//printf("number of objects = %d
", m_objects.size());
	for (GameObjects::iterator i = m_objects.begin(); i != m_objects.end(); ++i) {
		// get the object from the iterator
		GameObject* pObj = *i;

		// read the transform
		pObj->GetTransform(transform);

		// get data from the object and draw it
		DrawShape(transform, pObj->GetShape(), pObj->GetColor());
	}

	// after rendering all game objects, perform debug rendering
	// Bullet will figure out what needs to be drawn then call to
	// our DebugDrawer class to do the rendering for us
	m_pWorld->debugDrawWorld();

}

void BulletOpenGLApplication::UpdateScene(float dt) {
	// check if the world object exists
	if (m_pWorld) {
		// step the simulation through time. This is called
		// every update and the amount of elasped time was 
		// determined back in ::Idle() by our clock object.
		m_pWorld->stepSimulation(dt);
	}
}

void BulletOpenGLApplication::DrawShape(btScalar *transform, const btCollisionShape *pShape, const btVector3 &color) {


	if (Constants::GetInstance().GetProjectionMode() == ORTHOGRAPHIC)
	{
		// normalize translations
		// ASSUMPTION: Scene and camera located on z-plane at 0
		btScalar *x_trans = &transform[12];
		btScalar *y_trans = &transform[13];
		//printf("Translate (x,y) = (%f,%f)
", *x_trans, *y_trans);
		*x_trans = Constants::GetInstance().Normalize(*x_trans, 0, HEIGHT);
		*y_trans = Constants::GetInstance().Normalize(*y_trans, 0, WIDTH);
		//printf("Normalized (x,y) = (%f,%f)
", *x_trans, *y_trans);
	}

	glColor3f(color.x(), color.y(), color.z());

	// push the matrix stack

	glPushMatrix();
	glMultMatrixf(transform);

	// make a different draw call based on object type
	switch (pShape->getShapeType())
	{
	case BOX_SHAPE_PROXYTYPE: {
		// assume the shape is a box, and typecast it
		const btBoxShape *box = static_cast<const btBoxShape*>(pShape);
		// get halfSize of the box
		btVector3 halfSize = box->getHalfExtentsWithMargin();
		// draw the box
		DrawBox(halfSize);
	}
	case BOX_2D_SHAPE_PROXYTYPE: {
		// assume the shape is a 2d box (plane) and typecast it
		const btBox2dShape *plane = static_cast<const btBox2dShape*> (pShape);
		btVector3 halfSize = plane->getHalfExtentsWithMargin();
		DrawPlane(halfSize);
	}
	default:
		// unsupported type
		break;
	}

	glPopMatrix();

}


GameObject* BulletOpenGLApplication::CreateGameObject(
	btCollisionShape *pShape, 
	const float &mass, 
	const btVector3 &color, 
	const btVector3 &initialPosition, 
	const btQuaternion &initialRotation) {

	GameObject* pObject = new GameObject(pShape, mass, color, initialPosition, initialRotation);
	// push it to the back of the list

	switch (pObject->GetShape()->getShapeType())
	{
	case BOX_2D_SHAPE_PROXYTYPE: {
		// assume the shape is a 2d box (plane) and typecast it
		btRigidBody *body = pObject->GetRigidBody();
		// ASSUMPTION: Limit motion along x-y plane
		printf("Allow in x y direction, disallow in z direction 
");
		body->setLinearFactor(btVector3(1, 1, 0));
		body->setAngularFactor(btVector3(0, 0, 1));
	}
	default:
		break;
	}

	m_objects.push_back(pObject);
	printf("Created Object and pushed to world
");
	// check if the world object is valid
	if (m_pWorld) {
		// add the object's rigid body to the world
		m_pWorld->addRigidBody(pObject->GetRigidBody());

	}

	return pObject;
}

void BulletOpenGLApplication::AddHingeConstraint(
	GameObject *obj1, 
	GameObject *obj2, 
	const btVector3 &pivot1, 
	const btVector3 &pivot2, 
	const btVector3 &axis1, 
	const btVector3 &axis2,
	btScalar lowLimit,
	btScalar highLimit) {

	btRigidBody *body1 = obj1->GetRigidBody();
	btRigidBody *body2 = obj2->GetRigidBody();

	btHingeConstraint *hc = new btHingeConstraint(*body1, *body2, pivot1, pivot2, axis1, axis2);
	hc->setDbgDrawSize(btScalar(5.0f));
	hc->setLimit(lowLimit, highLimit);

	if (m_pWorld) {
		m_pWorld->addConstraint(hc, true);
	}
}

GameObject.h:

#ifndef _GAMEOBJECT_H_
#define _GAMEOBJECT_H_

#include "btBulletDynamicsCommon.h"

#include "OpenGLMotionState.h"

class GameObject
{
public:
	// Constructor + Destructor
	GameObject(btCollisionShape *pShape,
		float mass,
		const btVector3 &color,
		const btVector3 &initialPosition = btVector3(0, 0, 0),
		const btQuaternion &initialRotation = btQuaternion(0, 0, 1, 1));
	~GameObject();

	// accessors
	btCollisionShape *GetShape() { return m_pShape; }
	btRigidBody *GetRigidBody() { return m_pBody; }
	btMotionState *GetMotionState() { return m_pMotionState; }

	void GetTransform(btScalar *transform) {
		if (m_pMotionState) {
			m_pMotionState->GetWorldTransform(transform);
		}
	}

	btVector3 GetColor() { return m_color; }

protected:
	btCollisionShape *m_pShape;
	btRigidBody *m_pBody;
	OpenGLMotionState *m_pMotionState;
	btVector3 m_color;
};
#endif


GameObject.cpp:

#include "stdafx.h"
#include "GameObject.h"

GameObject::GameObject(	btCollisionShape *pShape,
						float mass,
						const btVector3 &color,
						const btVector3 &initialPosition,
						const btQuaternion &initialRotation) {

	m_pShape = pShape;	// Store the shape 
	m_color = color;	// Store the color

	// Create initial transform
	btTransform transform;
	transform.setIdentity();
	transform.setOrigin(initialPosition);
	transform.setRotation(initialRotation);

	// Create Motion State from the initial Transform
	m_pMotionState = new OpenGLMotionState(transform);
	
	// Calculate the local inertia
	btVector3 localInertia(0, 0, 0);

	// Objects of infinite mass can't move or rotate
	if (mass != 0.0f) {
		pShape->calculateLocalInertia(mass, localInertia);
	}

	// create the rigid body construction info using mass, motion state, and shape
	btRigidBody::btRigidBodyConstructionInfo cInfo(mass, m_pMotionState, pShape, localInertia);

	// create the rigid body
	m_pBody = new btRigidBody(cInfo);
}


GameObject::~GameObject()
{
	delete m_pBody;
	delete m_pMotionState;
	delete m_pShape;
}

CameraManager.h:

#ifndef _CAMERAMANAGER_H_
#define _CAMERAMANAGER_H_

#include <Windows.h>

#include "BulletDynamics\Dynamics\btDynamicsWorld.h"
#include <gl\GL.h>
#include <freeglut\freeglut.h>

// CONSTANTS
#include "Constants.h"

enum RotationType {YAW, PITCH, ROLL};
enum TranslateDirection{UP, DOWN, LEFT, RIGHT};

class CameraManager
{
public:
	CameraManager(const btVector3 &target, float distance, float pitch, float yaw, const btVector3 &upVector, float nearPlane, float farPlane);
	~CameraManager();

	void UpdateCamera();
	void RotateCamera(RotationType type, float value);
	void ZoomCamera(float distance);
	void TranslateCamera(TranslateDirection direction, float value);
	void PrintCameraLocation();
	btVector3 GetCameraLocation();


protected:

	void SetupPerspectiveCamera();
	void SetupOrthographicCamera();
	void SetupPerspectiveModelView();
	void SetupOrthographicModelView();


	btVector3 m_cameraPosition;
	btVector3 m_cameraTarget;
	float m_nearPlane;
	float m_farPlane;
	btVector3 m_upVector;
	float m_cameraDistance;
	float m_cameraPitch;
	float m_cameraYaw;

	float m_cameraPosX;
	float m_cameraPosY;

};

#endif

CameraManager.cpp:

#include "stdafx.h"
#include "CameraManager.h"

// Some constants for 3D math and the camera speed
#define RADIANS_PER_DEGREE 0.01745329f


CameraManager::CameraManager(
	const btVector3 &target, 
	float distance, 
	float pitch, 
	float yaw, 
	const btVector3 &upVector, 
	float nearPlane, 
	float farPlane)
{
	m_cameraTarget = target;
	m_cameraDistance = distance;
	m_cameraPitch = pitch;
	m_cameraYaw = yaw;
	m_upVector = upVector;
	m_nearPlane = nearPlane;
	m_farPlane = farPlane;

	m_cameraPosX = 0;
	m_cameraPosY = 0;
	
}

void CameraManager::UpdateCamera() {

	// exit in erroneous situations
	if (Constants::GetInstance().GetScreenWidth() == 0 && Constants::GetInstance().GetScreenHeight() == 0)
		return;

	switch (Constants::GetInstance().GetProjectionMode())
	{
	case ORTHOGRAPHIC:
		//SetupModelView();
		//SetupOrthographicModelView();
		SetupOrthographicCamera();
		break;
	case PERSPECTIVE:
		SetupPerspectiveCamera();
		break;
	default:
		break;
	}

}

void CameraManager::SetupOrthographicCamera() {
	//printf("Setting up orthographic camera
");

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	//float aspectRatio = m_screenWidth / (float)m_screenHeight;

	// create a viewing frustum based on the aspect ratio and the
	// boundaries of the camera
	//glOrtho(0, 1, -1, 1, 1, 100);
	gluOrtho2D(-1, 1, -1, 1);
	//TEST_MODEL_VIEW_ORTHO();
	SetupOrthographicModelView();
}

void CameraManager::SetupOrthographicModelView() {

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	// Translation
	gluLookAt(m_cameraPosX, m_cameraPosY, 0.0, m_cameraPosX, m_cameraPosY, -1.0f, 0.0, 1.0, 0.0);
	
}


void CameraManager::SetupPerspectiveCamera() {

	// select the projection matrix
	glMatrixMode(GL_PROJECTION);
	// set it to the matrix-equivalent of 1
	glLoadIdentity();
	// determine the aspect ratio of the screen
	float aspectRatio = Constants::GetInstance().GetScreenWidth() / (float)Constants::GetInstance().GetScreenHeight();
	// create a viewing frustum based on the aspect ratio and the
	// boundaries of the camera
	glFrustum(-aspectRatio * m_nearPlane, aspectRatio * m_nearPlane, -m_nearPlane, m_nearPlane, m_nearPlane, m_farPlane);
	// the projection matrix is now set
	SetupPerspectiveModelView();
}

void CameraManager::SetupPerspectiveModelView() {

	// select the view matrix
	glMatrixMode(GL_MODELVIEW);
	// set it to '1'
	glLoadIdentity();

	// our values represent the angles in degrees, but 3D 
	// math typically demands angular values are in radians.
	float pitch = m_cameraPitch * RADIANS_PER_DEGREE;
	float yaw = m_cameraYaw * RADIANS_PER_DEGREE;

	// create a quaternion defining the angular rotation 
	// around the up vector
	btQuaternion rotation(m_upVector, yaw);

	// set the camera's position to 0,0,0, then move the 'z' 
	// position to the current value of m_cameraDistance.
	btVector3 cameraPosition(0, 0, 0);
	//cameraPosition[2] = -m_cameraDistance;
	cameraPosition[2] = m_cameraDistance;

	// Translation
	m_cameraTarget[0] = m_cameraPosX;
	m_cameraTarget[1] = m_cameraPosY;

	// create a Bullet Vector3 to represent the camera 
	// position and scale it up if its value is too small.
	btVector3 forward(cameraPosition[0], cameraPosition[1], cameraPosition[2]);
	if (forward.length2() < SIMD_EPSILON) {
		forward.setValue(1.f, 0.f, 0.f);
	}

	// figure out the 'right' vector by using the cross 
	// product on the 'forward' and 'up' vectors
	btVector3 right = m_upVector.cross(forward);

	// create a quaternion that represents the camera's roll
	btQuaternion roll(right, -pitch);

	// turn the rotation (around the Y-axis) and roll (around 
	// the forward axis) into transformation matrices and 
	// apply them to the camera position. This gives us the 
	// final position
	cameraPosition = btMatrix3x3(rotation) * btMatrix3x3(roll) * cameraPosition;

	// save our new position in the member variable, and 
	// shift it relative to the target position (so that we 
	// orbit it)
	m_cameraPosition[0] = cameraPosition.getX();
	m_cameraPosition[1] = cameraPosition.getY();
	m_cameraPosition[2] = cameraPosition.getZ();
	m_cameraPosition += m_cameraTarget;

	// create a view matrix based on the camera's position and where it's
	// looking
	//printf("Camera Position = %f, %f, %f
", cameraPosition[0], cameraPosition[1], cameraPosition[2]);
	// the view matrix is now set
	gluLookAt(m_cameraPosition[0], m_cameraPosition[1], m_cameraPosition[2], m_cameraTarget[0], m_cameraTarget[1], m_cameraTarget[2], m_upVector.getX(), m_upVector.getY(), m_upVector.getZ());

}

/* CAMERA MOVEMENT METHODS */

void CameraManager::RotateCamera(RotationType type, float value) {
	// change the value (it is passed by reference, so we
	// can edit it here)

	float *angle = nullptr;

	switch (type) {
	case YAW:
		angle = &m_cameraYaw;
		break;
	case PITCH:
		angle = &m_cameraPitch;
		break;
	case ROLL:
		break;
	default:
		break;
	}

	*angle -= value;
	// keep the value within bounds
	if (*angle < 0) *angle += 360;
	if (*angle >= 360) *angle -= 360;
	// update the camera since we changed the angular value
	UpdateCamera();
	PrintCameraLocation();
}

void CameraManager::ZoomCamera(float distance) {
	// change the distance value
	m_cameraDistance -= distance;
	// prevent it from zooming in too far
	//if (m_cameraDistance < 0.1f) m_cameraDistance = 0.1f;
	// update the camera since we changed the zoom distance
	UpdateCamera();
	PrintCameraLocation();
}

void CameraManager::TranslateCamera(TranslateDirection direction, float value) {

	float *positionValue = nullptr;

	switch (direction)
	{
	case UP: {
		positionValue = &m_cameraPosY;
		*positionValue += value;
	}
		break;
	case DOWN: {
		positionValue = &m_cameraPosY;
		*positionValue += value;
	}
		break;
	case LEFT: {
		positionValue = &m_cameraPosX;
		*positionValue -= value;
	}
		break;
	case RIGHT: {
		positionValue = &m_cameraPosX;
		*positionValue -= value;
	}
		break;
	default:
		break;
	}

	
	UpdateCamera();
	PrintCameraLocation();
}

void CameraManager::PrintCameraLocation() {
	printf("Camera Position = %f, %f, %f
", m_cameraPosition[0], m_cameraPosition[1], m_cameraPosition[2]);
	printf("Camera Target = %f, %f, %f 
", m_cameraTarget[0], m_cameraTarget[1], m_cameraTarget[2]);
}

btVector3 CameraManager::GetCameraLocation() {
	return m_cameraPosition;
}


CameraManager::~CameraManager()
{
}

Constants.h:

#pragma once


enum ProjectionMode{ ORTHOGRAPHIC, PERSPECTIVE };
enum Dimension{ HEIGHT, WIDTH };

#define CAMERA_STEP_SIZE 0.3f
#define Z_PLANE  0

#define DEG_2_RAD 0.0174533

class Constants
{
	
private:

	ProjectionMode m_projectionMode;
	int m_screenWidth;
	int m_screenHeight;

public:

	static Constants& GetInstance() {
		static Constants instance;
		return instance;
	}

	void SetScreenWidth(int width);
	void SetScreenHeight(int height);
	void SetProjectionMode(ProjectionMode mode);

	int GetScreenWidth();
	int GetScreenHeight();

	ProjectionMode GetProjectionMode();

	float GetPixelsToMeters(float dist2Camera);
	float Normalize(float meters, float dist2Camera, Dimension dimension);

	float DegreesToRadians(float degrees);

protected:

	Constants();
	~Constants();
};


Constants.cpp:

#include "stdafx.h"
#include "Constants.h"


Constants::Constants()
{
}

void Constants::SetScreenWidth(int width) {
	m_screenWidth = width;
}

void Constants::SetScreenHeight(int height) {
	m_screenHeight = height;
}


void Constants::SetProjectionMode(ProjectionMode mode) {
	m_projectionMode = mode;
}

int Constants::GetScreenWidth() {
	return m_screenWidth;
}

int Constants::GetScreenHeight() {
	return m_screenHeight;
}

ProjectionMode Constants::GetProjectionMode() {
	return m_projectionMode;
}

float Constants::GetPixelsToMeters(float dist2Camera) {
	// ASSUMPTION: Found this empirically;
	return 0.00162*dist2Camera + 0.0261;

}

float Constants::Normalize(float meters, float dist2Camera, Dimension dimension) {
	float p2m = GetPixelsToMeters(dist2Camera);
	float m2p = 1 / p2m;

	float pix = meters * m2p;

	switch (dimension)
	{
	case HEIGHT:
		return pix / ((float)m_screenHeight / 2);
		break;
	case WIDTH: {

		float width_proportion = pix / (m_screenWidth / 2);
		float aspectRatio = m_screenWidth / (float)m_screenHeight;
		return width_proportion * aspectRatio;
		//return pix / (m_screenWidth / 2);
	}
		break;
	default:
		break;
	}
}

float Constants::DegreesToRadians(float degrees) {

	return degrees * DEG_2_RAD;

}

Constants::~Constants()
{
}

Note that using OOP and multiple source files significantly reduces the chances that anyone else is going to look at your code.

Sorry about that.

I’m just wondering if gluOrtho2D needs to be declared at a particular instance in my pipeline.
Does gluortho2d need to be declared right after initializing glu?
Pretty much at every simulation step I update the camera. Does gluOrtho2D just need to be initialized once with the desired clippings?

[QUOTE=jchen114;1282575]
I’m just wondering if gluOrtho2D needs to be declared at a particular instance in my pipeline.
Does gluortho2d need to be declared right after initializing glu?
Pretty much at every simulation step I update the camera. Does gluOrtho2D just need to be initialized once with the desired clippings?[/QUOTE]
The projection matrix will only change if you call matrix functions (e.g. gluOrtho2D()) while the projection matrix is active (glMatrixMode(GL_PROJECTION)).

If you use the same projection matrix for the lifetime of the program, you can set it as soon as the context is bound (for GLUT, this is as soon as glutCreateWindow() has returned). But it’s more typical to set the projection matrix according to the window’s aspect ratio, in which case you’d normally set it either in the reshape function or at the start of the display function.

Your code sets the projection matrix via UpdateCamera() before rendering the scene, which is fine. You just need to change the -1,1,-1,1 there to more appropriate values.