Reorganized code quite a bit. Resizing is deactivated currently.

This commit is contained in:
Fabian Klemp 2014-11-14 16:47:47 +01:00
parent 4231866d40
commit 7b331edff9
4 changed files with 206 additions and 193 deletions

View File

@ -1,100 +1,151 @@
#include "graphics.hh" #include "graphics.hh"
#include <iostream>
#include <fstream>
#include <iomanip>
#include <sstream>
#include <ACGL/OpenGL/glloaders/extensions.hh>
#include <ACGL/Utils/FileHelpers.hh>
#include <ACGL/Utils/StringHelpers.hh>
#include "model.hh" #include "model.hh"
#include <ACGL/OpenGL/Creator/ShaderProgramCreator.hh>
using namespace std; using namespace std;
ACGL::OpenGL::SharedShaderProgram shader; Graphics::Graphics() {
Level level;
// gets called after the OpenGL window is prepared:
void initCustomResources()
{
// define where shaders and textures can be found:
ACGL::Base::Settings::the()->setResourcePath("../");
ACGL::Base::Settings::the()->setShaderPath("Shader/");
ACGL::Base::Settings::the()->setTexturePath("Geometry/");
ACGL::Base::Settings::the()->setGeometryPath("Geometry/");
// load Model to give shader correct Attribute locations
// TODO look up if this is really necessary, since this looks really stupid.
Model model = Model("Bunny.obj");
// look up all shader files starting with 'phong' and build a ShaderProgram from it:
shader = ACGL::OpenGL::ShaderProgramCreator("phong").attributeLocations(
model.getReference()->getAttributeLocations()).create();
shader->use();
// load Level
level.load(shader);
// just in case: check for errors
openGLCriticalError();
} }
void deleteCustomResources() GLFWwindow* Graphics::getWindow() {
{ return window;
// we have memory management via reference counting, so nothing to do here
} }
void draw(float runTime) void Graphics::setGLFWHintsForOpenGLVersion( unsigned int _version )
{ {
// update Level first TODO: move this with the rest of the stuff that doesn't belong here to main #ifdef __APPLE__
level.update(runTime); #if (ACGL_OPENGL_VERSION >= 30)
// request OpenGL 3.2, will return a 4.1 context on Mavericks
glfwWindowHint( GLFW_CONTEXT_VERSION_MAJOR, 3 );
glfwWindowHint( GLFW_CONTEXT_VERSION_MINOR, 2 );
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif
#else
// non-apple
glfwWindowHint( GLFW_CONTEXT_VERSION_MAJOR, _version / 10 );
glfwWindowHint( GLFW_CONTEXT_VERSION_MINOR, _version % 10 );
#ifdef ACGL_OPENGL_PROFILE_CORE
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#endif
#endif
}
bool Graphics::createWindow()
{
/////////////////////////////////////////////////////////////////////////////////////
// Initialise GLFW
//
if ( !glfwInit() )
{
ACGL::Utils::error() << "Failed to initialize GLFW" << endl;
exit( -1 );
}
/////////////////////////////////////////////////////////////////////////////////////
// Configure OpenGL context
//
setGLFWHintsForOpenGLVersion( ACGL_OPENGL_VERSION );
// activate multisampling (second parameter is the number of samples):
//glfwWindowHint( GLFW_SAMPLES, 8 );
// request an OpenGL debug context:
glfwWindowHint( GLFW_OPENGL_DEBUG_CONTEXT, true );
// define whether the window can get resized:
glfwWindowHint(GLFW_RESIZABLE, false);
// non-decorated windows can be used as splash screens:
//glfwWindowHint( GLFW_DECORATED, false );
/////////////////////////////////////////////////////////////////////////////////////
// try to create an OpenGL context in a window and check the supported OpenGL version:
// R,G,B,A, Depth,Stencil
window = glfwCreateWindow(windowSize.x, windowSize.y, "SWP MarbleGame Group C", NULL, NULL);
if (!getWindow()) {
ACGL::Utils::error() << "Failed to open a GLFW window - requested OpenGL: " << ACGL_OPENGL_VERSION << endl;
return false;
}
glfwMakeContextCurrent(window);
ACGL::init();
return true;
}
Graphics::Graphics(glm::uvec2 windowSize, float nearPlane, float farPlane) {
this->windowSize = windowSize;
this->nearPlane = nearPlane;
this->farPlane = farPlane;
}
void Graphics::render(Level* level, ACGL::OpenGL::SharedShaderProgram shader)
{
// clear the framebuffer: // clear the framebuffer:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//set view and projection matrix //set view and projection matrix
shader->setUniform("projectionMatrix", buildFrustum(75.0, 0.1, 100.0, (float)g_windowSize.x/(float)g_windowSize.y) ); shader->setUniform("projectionMatrix", buildFrustum(75.0f, 0.1f, 100.0f, (float)windowSize.x/(float)windowSize.y) );
// the + (0,1,0) compensates bunny doesn't have its center at it's center shader->setUniform("viewMatrix", buildViewMatrix(level));
shader->setUniform("viewMatrix", buildViewMatrix());
//set lighting parameters //set lighting parameters
if (level.getLights().size() > 0) { if (level->getLights().size() > 0) {
shader->setUniform("lightCount", (int) level.getLights().size()); shader->setUniform("lightCount", (int) level->getLights().size());
// TODO look into doing this less often // TODO look into doing this less often
// Build light position array // Build light position array
glm::vec3 lightSources[level.getLights().size()]; glm::vec3 lightSources[level->getLights().size()];
for(unsigned int i = 0; i<level.getLights().size(); i++) { for(unsigned int i = 0; i<level->getLights().size(); i++) {
lightSources[i] = level.getLights()[i].getPosition(); lightSources[i] = level->getLights()[i].getPosition();
} }
glUniform3fv(shader->getUniformLocation("lightSources"), glUniform3fv(shader->getUniformLocation("lightSources"),
sizeof(lightSources), (GLfloat*) lightSources); sizeof(lightSources), (GLfloat*) lightSources);
// Build light colour array // Build light colour array
glm::vec3 lightColours[level.getLights().size()]; glm::vec3 lightColours[level->getLights().size()];
for(unsigned int i = 0; i<level.getLights().size(); i++) { for(unsigned int i = 0; i<level->getLights().size(); i++) {
lightColours[i] = level.getLights()[i].getColour(); lightColours[i] = level->getLights()[i].getColour();
} }
glUniform3fv(shader->getUniformLocation("lightColors"), glUniform3fv(shader->getUniformLocation("lightColors"),
sizeof(lightColours), (GLfloat*) lightColours); sizeof(lightColours), (GLfloat*) lightColours);
// Build light attenuation array // Build light attenuation array
float lightIntensities[level.getLights().size()]; float lightIntensities[level->getLights().size()];
for(unsigned int i = 0; i<level.getLights().size(); i++) { for(unsigned int i = 0; i<level->getLights().size(); i++) {
lightIntensities[i] = level.getLights()[i].getIntensity(); lightIntensities[i] = level->getLights()[i].getIntensity();
} }
glUniform1fv(shader->getUniformLocation("lightIntensities"), glUniform1fv(shader->getUniformLocation("lightIntensities"),
sizeof(lightIntensities), (GLfloat*) lightIntensities); sizeof(lightIntensities), (GLfloat*) lightIntensities);
} }
// set Material Parameters // set Material Parameters
shader->setUniform("ambientColor", level.getAmbientLight()); shader->setUniform("ambientColor", level->getAmbientLight());
shader->setUniform("camera", glm::vec3(0.0f, 0.0f, 0.0f)); shader->setUniform("camera", glm::vec3(0.0f, 0.0f, 0.0f));
// render the level(currently only a bunny): // render the level(currently only a bunny):
level.render(); level->render();
} }
void resizeCallback( GLFWwindow *, int newWidth, int newHeight ) void Graphics::setWindowSize(glm::uvec2 windowSize) {
this->windowSize = windowSize;
}
void resizeCallback(Graphics* graphics, int newWidth, int newHeight)
{ {
// store the new window size and adjust the viewport: // store the new window size and adjust the viewport:
g_windowSize = glm::uvec2( newWidth, newHeight); graphics->setWindowSize(glm::uvec2( newWidth, newHeight));
glViewport( 0, 0, g_windowSize.x, g_windowSize.y ); glViewport( 0, 0, newWidth, newHeight);
} }
glm::mat4 buildFrustum( float phiInDegree, float _near, float _far, float aspectRatio) { glm::mat4 Graphics::buildFrustum( float phiInDegree, float _near, float _far, float aspectRatio) {
float phiHalfInRadians = 0.5*phiInDegree * (M_PI/180.0); float phiHalfInRadians = 0.5*phiInDegree * (M_PI/180.0);
float top = _near * tan( phiHalfInRadians ); float top = _near * tan( phiHalfInRadians );
@ -105,12 +156,12 @@ glm::mat4 buildFrustum( float phiInDegree, float _near, float _far, float aspect
return glm::frustum(left, right, bottom, top, _near, _far); return glm::frustum(left, right, bottom, top, _near, _far);
} }
glm::mat4 buildViewMatrix() { glm::mat4 Graphics::buildViewMatrix(Level* level) {
glm::vec4 cameraVector = glm::vec4(0.0f, 0.0f, level.getCamera().getDistance(), 0.0f); glm::vec4 cameraVector = glm::vec4(0.0f, 0.0f, level->getCamera().getDistance(), 0.0f);
// rotate vector // rotate vector
glm::mat4 rotationMatrix = glm::rotate<float>(level.getCamera().getRotation()[0], glm::vec3(1.0f, 0.0f, 0.0f)) * glm::mat4 rotationMatrix = glm::rotate<float>(level->getCamera().getRotation()[0], glm::vec3(1.0f, 0.0f, 0.0f)) *
glm::rotate<float>(level.getCamera().getRotation()[1], glm::vec3(0.0f, 1.0f, 0.0f)) * glm::rotate<float>(level.getCamera().getRotation()[2], glm::vec3(0.0f, 0.0f, 1.0f)); glm::rotate<float>(level->getCamera().getRotation()[1], glm::vec3(0.0f, 1.0f, 0.0f)) * glm::rotate<float>(level->getCamera().getRotation()[2], glm::vec3(0.0f, 0.0f, 1.0f));
cameraVector = rotationMatrix * cameraVector; cameraVector = rotationMatrix * cameraVector;
//construct lookAt (cameraPosition = cameraCenter + cameraVector //construct lookAt (cameraPosition = cameraCenter + cameraVector
return glm::lookAt(level.getCameraCenter()->getPosition() + glm::vec3(cameraVector), level.getCameraCenter()->getPosition(), glm::vec3(0.0f, 1.0f, 0.0f)); return glm::lookAt(level->getCameraCenter()->getPosition() + glm::vec3(cameraVector), level->getCameraCenter()->getPosition(), glm::vec3(0.0f, 1.0f, 0.0f));
} }

View File

@ -1,26 +1,33 @@
#ifndef GRAPHICS_HH_INCLUDED #ifndef GRAPHICS_HH_INCLUDED
#define GRAPHICS_HH_INCLUDED #define GRAPHICS_HH_INCLUDED
#include <ACGL/OpenGL/GL.hh>
#include "main.hh" #include <GLFW/glfw3.h>
#include <ACGL/Base/Settings.hh>
#include <ACGL/Math/Math.hh> #include <ACGL/Math/Math.hh>
#include "level.hh"
// gets called after the OpenGL window is prepared, init of example specific stuff: class Graphics {
void initCustomResources(); public:
Graphics(glm::uvec2 windowSize, float nearPlane, float farPlane);
Graphics();
void render(Level* level, ACGL::OpenGL::SharedShaderProgram shader);
// gets called at window resize:
void resizeCallback( GLFWwindow *, int newWidth, int newHeight );
// to build the projection matrix:
glm::mat4 buildFrustum( float phiInDegree, float near, float far, float aspectRatio);
glm::mat4 buildViewMatrix(Level* level);
glm::uvec2 getWindowSize();
bool createWindow();
GLFWwindow* getWindow();
void setWindowSize(glm::uvec2 windowSize);
private:
void setGLFWHintsForOpenGLVersion( unsigned int _version );
glm::uvec2 windowSize;
float nearPlane;
float farPlane;
GLFWwindow* window;
};
// gets called at application shutdown: void resizeCallback(Graphics* graphics, int newWidth, int newHeight);
void deleteCustomResources();
// gets called ech frame, runTime is in seconds:
void draw(float runTime);
// gets called at window resize:
void resizeCallback( GLFWwindow *, int newWidth, int newHeight );
// to build the projection matrix:
glm::mat4 buildFrustum( float phiInDegree, float near, float far, float aspectRatio);
glm::mat4 buildViewMatrix();
#endif #endif

154
main.cc
View File

@ -10,108 +10,63 @@
#include <ACGL/Math/Math.hh> #include <ACGL/Math/Math.hh>
#include <ACGL/Utils/FileHelpers.hh> #include <ACGL/Utils/FileHelpers.hh>
#include <ACGL/Utils/StringHelpers.hh> #include <ACGL/Utils/StringHelpers.hh>
#include <ACGL/OpenGL/Objects/VertexArrayObject.hh>
#include <ACGL/OpenGL/Creator/ShaderProgramCreator.hh>
#include <ACGL/OpenGL/glloaders/extensions.hh> #include <ACGL/OpenGL/glloaders/extensions.hh>
#include <ACGL/Base/Settings.hh>
#include "model.hh"
using namespace std; using namespace std;
using namespace ACGL::OpenGL; using namespace ACGL::OpenGL;
using namespace ACGL::Base; using namespace ACGL::Base;
using namespace ACGL::Utils; using namespace ACGL::Utils;
glm::uvec2 g_windowSize( 1024, 786 ); Application::Application() {
float g_nearPlane = 0.1f; graphics = Graphics(glm::uvec2(1024, 786), 0.1f, 100.0f);
float g_farPlane = 100.0f; }
bool glfwWindowClosed = false;
GLFWwindow* g_window; Graphics* Application::getGraphics() {
return &graphics;
}
void setGLFWHintsForOpenGLVersion( unsigned int _version ) Level* Application::getLevel() {
return &level;
}
ACGL::OpenGL::SharedShaderProgram Application::getShader() {
return shader;
}
void Application::init()
{ {
#ifdef __APPLE__ // define where shaders and textures can be found:
#if (ACGL_OPENGL_VERSION >= 30) ACGL::Base::Settings::the()->setResourcePath("../");
// request OpenGL 3.2, will return a 4.1 context on Mavericks ACGL::Base::Settings::the()->setShaderPath("Shader/");
glfwWindowHint( GLFW_CONTEXT_VERSION_MAJOR, 3 ); ACGL::Base::Settings::the()->setTexturePath("Geometry/");
glfwWindowHint( GLFW_CONTEXT_VERSION_MINOR, 2 ); ACGL::Base::Settings::the()->setGeometryPath("Geometry/");
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // load Model to give shader correct Attribute locations
#endif // TODO look up if this is really necessary, since this looks really stupid.
#else Model model = Model("Bunny.obj");
// non-apple
glfwWindowHint( GLFW_CONTEXT_VERSION_MAJOR, _version / 10 ); // look up all shader files starting with 'phong' and build a ShaderProgram from it:
glfwWindowHint( GLFW_CONTEXT_VERSION_MINOR, _version % 10 ); shader = ACGL::OpenGL::ShaderProgramCreator("phong").attributeLocations(
#ifdef ACGL_OPENGL_PROFILE_CORE model.getReference()->getAttributeLocations()).create();
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); shader->use();
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#endif // load Level
#endif level.load(shader);
// just in case: check for errors
openGLCriticalError();
} }
/********************************************************************************************************************** /**********************************************************************************************************************
* Returns true if a window with the desired context could get created. * Returns true if a window with the desired context could get created.
* Requested OpenGL version gets set by ACGL defines. * Requested OpenGL version gets set by ACGL defines.
*/ */
bool createWindow()
{
/////////////////////////////////////////////////////////////////////////////////////
// Initialise GLFW
//
if ( !glfwInit() )
{
error() << "Failed to initialize GLFW" << endl;
exit( -1 );
}
/////////////////////////////////////////////////////////////////////////////////////
// Configure OpenGL context
//
setGLFWHintsForOpenGLVersion( ACGL_OPENGL_VERSION );
// activate multisampling (second parameter is the number of samples):
//glfwWindowHint( GLFW_SAMPLES, 8 );
// request an OpenGL debug context:
glfwWindowHint( GLFW_OPENGL_DEBUG_CONTEXT, true );
// define whether the window can get resized:
//glfwWindowHint( GLFW_RESIZABLE, true );
// non-decorated windows can be used as splash screens:
//glfwWindowHint( GLFW_DECORATED, false );
// request an sRGB framebuffer:
//glfwWindowHint( GLFW_SRGB_CAPABLE, true );
//glfwWindowHint( , true );
//glfwWindowHint( , true );
//glfwWindowHint( , true );
//glfwWindowHint( , true );
/////////////////////////////////////////////////////////////////////////////////////
// try to create an OpenGL context in a window and check the supported OpenGL version:
// R,G,B,A, Depth,Stencil
g_window = glfwCreateWindow( g_windowSize.x, g_windowSize.y, "ACGL GLFWExamples", NULL, NULL);
if (!g_window) {
error() << "Failed to open a GLFW window - requested OpenGL: " << ACGL_OPENGL_VERSION << endl;
return false;
}
glfwMakeContextCurrent(g_window);
ACGL::init();
/////////////////////////////////////////////////////////////////////////////////////
// Init debug-extension
//
if (ACGL_ARB_debug_output()) {
//debug() << "GL_ARB_DEBUG_OUTPUT is supported, register callback" << endl;
//glDebugMessageCallbackARB( debugCallback, NULL);
// filter out the strange performance warnings about shader recompiles:
//glDebugMessageControlARB( GL_DEBUG_SOURCE_API_ARB, GL_DEBUG_TYPE_PERFORMANCE_ARB, GL_DEBUG_SEVERITY_MEDIUM_ARB, 0, NULL, GL_FALSE );
} else {
//debug() << "GL_ARB_DEBUG_OUTPUT is missing!" << endl;
}
return true;
}
static void keyCallback(GLFWwindow* _window, int _key, int, int _action, int) static void keyCallback(GLFWwindow* _window, int _key, int, int _action, int)
{ {
@ -121,15 +76,14 @@ static void keyCallback(GLFWwindow* _window, int _key, int, int _action, int)
} }
/**********************************************************************************************************************
* Generic main for different example apps
*/
int main( int argc, char *argv[] ) int main( int argc, char *argv[] )
{ {
Application app = Application();
///////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////
// Create OpenGL capable window: // Create OpenGL capable window:
// //
if ( !createWindow() ) { if ( !app.getGraphics()->createWindow() ) {
glfwTerminate(); glfwTerminate();
exit( -1 ); exit( -1 );
} }
@ -138,11 +92,11 @@ int main( int argc, char *argv[] )
// Set window title to binary name (without the path): // Set window title to binary name (without the path):
// //
std::vector<std::string> tmp = StringHelpers::split( std::string( argv[0] ), '/' ); std::vector<std::string> tmp = StringHelpers::split( std::string( argv[0] ), '/' );
glfwSetWindowTitle( g_window, tmp[tmp.size()-1].c_str() ); glfwSetWindowTitle(app.getGraphics()->getWindow(), tmp[tmp.size()-1].c_str() );
// Ensure we can capture the escape key being pressed below // Ensure we can capture the escape key being pressed below
glfwSetInputMode( g_window, GLFW_STICKY_KEYS, 1 ); glfwSetInputMode(app.getGraphics()->getWindow(), GLFW_STICKY_KEYS, 1 );
glfwSetWindowSizeCallback( g_window, resizeCallback ); //glfwSetWindowSizeCallback(app.getGraphics(), resizeCallback);
glfwSetKeyCallback( g_window, keyCallback ); glfwSetKeyCallback(app.getGraphics()->getWindow(), keyCallback );
// Enable vertical sync (on cards that support it) with parameter 1 - 0 means off // Enable vertical sync (on cards that support it) with parameter 1 - 0 means off
glfwSwapInterval( 0 ); glfwSwapInterval( 0 );
@ -152,7 +106,7 @@ int main( int argc, char *argv[] )
// //
glClearColor( 0.0, 0.0, 0.0, 1.0 ); glClearColor( 0.0, 0.0, 0.0, 1.0 );
glEnable( GL_DEPTH_TEST ); glEnable( GL_DEPTH_TEST );
initCustomResources(); app.init();
int frameCount = 0; int frameCount = 0;
@ -167,23 +121,23 @@ int main( int argc, char *argv[] )
stringstream sstream (stringstream::in | stringstream::out); stringstream sstream (stringstream::in | stringstream::out);
sstream << setprecision(1) << std::fixed sstream << setprecision(1) << std::fixed
<< tmp[tmp.size()-1] << " - FPS: " << frameCount / (now-showNextFPS + FPSdelay) << " " << 1000 * (now-showNextFPS + FPSdelay)/frameCount << " msec"; << tmp[tmp.size()-1] << " - FPS: " << frameCount / (now-showNextFPS + FPSdelay) << " " << 1000 * (now-showNextFPS + FPSdelay)/frameCount << " msec";
glfwSetWindowTitle( g_window, sstream.str().c_str() ); glfwSetWindowTitle(app.getGraphics()->getWindow(), sstream.str().c_str() );
showNextFPS = now + FPSdelay; showNextFPS = now + FPSdelay;
frameCount = 0; frameCount = 0;
} }
draw( now - startTimeInSeconds ); app.getLevel()->update(now - startTimeInSeconds);
app.getGraphics()->render(app.getLevel(), app.getShader());
openGLCriticalError(); openGLCriticalError();
// MacOS X will not swap correctly is another FBO is bound: // MacOS X will not swap correctly is another FBO is bound:
glBindFramebuffer( GL_FRAMEBUFFER, 0 ); glBindFramebuffer( GL_FRAMEBUFFER, 0 );
glfwSwapBuffers( g_window ); glfwSwapBuffers(app.getGraphics()->getWindow());
glfwPollEvents(); glfwPollEvents();
frameCount++; frameCount++;
} // Check if the window was closed } // Check if the window was closed
while( !glfwWindowShouldClose( g_window ) ); while( !glfwWindowShouldClose(app.getGraphics()->getWindow()) );
deleteCustomResources();
glfwTerminate(); glfwTerminate();
exit(0); exit(0);

35
main.hh
View File

@ -1,27 +1,28 @@
/////////////////////////////////////////////////////////////////////////////////////////////////// #ifndef MAIN_HH_INCLUDED
// #define MAIN_HH_INCLUDED
// headers needed:
//
#include <ACGL/Math/Math.hh>
#include <ACGL/OpenGL/GL.hh> #include <ACGL/OpenGL/GL.hh>
#include <ACGL/Math/Math.hh>
#include <GLFW/glfw3.h> #include <GLFW/glfw3.h>
#include <ACGL/OpenGL/Objects/ArrayBuffer.hh> #include <ACGL/OpenGL/Objects/ArrayBuffer.hh>
// ////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////
#include "physics.hh" #include "physics.hh"
#include "graphics.hh" #include "graphics.hh"
#include "level.hh" #include "level.hh"
/////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
// class Application {
// implement the following functions: public:
// Application();
Graphics* getGraphics();
Level* getLevel();
ACGL::OpenGL::SharedShaderProgram getShader();
void init();
private:
Graphics graphics;
Level level;
ACGL::OpenGL::SharedShaderProgram shader;
};
// global variables exported by the generic main: #endif
extern glm::uvec2 g_windowSize;
extern float g_nearPlane;
extern float g_farPlane;
//
///////////////////////////////////////////////////////////////////////////////////////////////////