- Viewing Profile: Reputation: pondwater
Awesome job so far everyone! Please give us your feedback on how our article efforts are going. We still need more finished articles for our May contest theme: Remake the Classics
Community Stats
- Group Members
- Active Posts 83
- Profile Views 1,819
- Member Title Member
- Age Age Unknown
- Birthday Birthday Unknown
-
Gender
Not Telling
#5001833 skeletal animations and suitable formats
Posted by pondwater
on 17 November 2012 - 02:31 PM
Here is the link you were talking about:
http://www.wazim.com..._Tutorial_1.htm
In any case, you want to have some sort of asset conditioning pipeline where you take in an interchange format like .dae and bring it into your own runtime format for your game/engine. How your engine manages its content at runtime is another story.
I attempted to go the approach you did and write my own collada parser. I got it working, but it wasn't robust at all. I find the incredible amount of a variance in the .dae format extremely frustrating and ended up switching to using Assimp for my .dae models. It is great. Nice clean interface, very robust, and much faster than my own parser for optimizing vertex indices. I'd recommend attempting to roll your own like I did, once you get it working for just 1 instance of the .dae format you will understand the format so much more and will feel more comfortable transitioning to Assimp.
Here is a fantastic tutorial if you decide to switch to Assimp:
http://ogldev.atspac...tutorial38.html
It also teaches you how to skin on the GPU, instead of the CPU like wazim's.
http://www.wazim.com..._Tutorial_1.htm
In any case, you want to have some sort of asset conditioning pipeline where you take in an interchange format like .dae and bring it into your own runtime format for your game/engine. How your engine manages its content at runtime is another story.
I attempted to go the approach you did and write my own collada parser. I got it working, but it wasn't robust at all. I find the incredible amount of a variance in the .dae format extremely frustrating and ended up switching to using Assimp for my .dae models. It is great. Nice clean interface, very robust, and much faster than my own parser for optimizing vertex indices. I'd recommend attempting to roll your own like I did, once you get it working for just 1 instance of the .dae format you will understand the format so much more and will feel more comfortable transitioning to Assimp.
Here is a fantastic tutorial if you decide to switch to Assimp:
http://ogldev.atspac...tutorial38.html
It also teaches you how to skin on the GPU, instead of the CPU like wazim's.
#4977794 Mesh and Skeleton organization
Posted by pondwater
on 07 September 2012 - 01:43 PM
Originally my models would consist of a set of meshes and a single global skeleton. Each frame I would iterate through every bone and calculate the skinning matrices then pass these to the skinning shader for each meshes draw call.
Now I realize that while multiple meshes may use the same skeleton, the bones may have different inverse bind transforms depending on the mesh (i guess this is why Assimp and COLLADA store the inverse binds independantly for each mesh).
Is it common to have unique inverse binds or each mesh?
If so, what is a recommended way to store them? I was thinking of having a global skeleton that contains the bone heirarchy. Any pose can be applied to this skeleton, then when skinning, the inverse binds from the respective mesh can be used to construct the skinning palette.
Now I realize that while multiple meshes may use the same skeleton, the bones may have different inverse bind transforms depending on the mesh (i guess this is why Assimp and COLLADA store the inverse binds independantly for each mesh).
Is it common to have unique inverse binds or each mesh?
If so, what is a recommended way to store them? I was thinking of having a global skeleton that contains the bone heirarchy. Any pose can be applied to this skeleton, then when skinning, the inverse binds from the respective mesh can be used to construct the skinning palette.
#4959764 GPU skinning, passing indices, weights and joints
Posted by pondwater
on 16 July 2012 - 03:40 PM
Thank you both for your replies! I will use VBO to store my indices and weights.
I interweave my vertices, normals, texture coords into a single VBO. Since my weights and indices are static, should I interweave them within the same VBO or would you recommend using seperate buffer?
I interweave my vertices, normals, texture coords into a single VBO. Since my weights and indices are static, should I interweave them within the same VBO or would you recommend using seperate buffer?
#4844719 Penetration depth and direction
Posted by pondwater
on 04 August 2011 - 03:24 PM
That will not work in general. Consider this 2d example:
well i figure if i know the direction im casting, i can find the plane by seaching for the 3 points on the minkowski difference farthest in the direction.It's just a regular old geometry test. Googling ray-plane intersection or line-plane intersection should come up with plenty of resources.I guess what im asking is how do i intersect the ray with that plane.
bugger... just when i thought it was going to be easy...
Im trying to think of a way to find the plane that would be intersected for my arbitrary direction. From what i understand MPR would give me a plane closests to the origin on the outside of the minkowski difference.
But in my case where i simply want to intersect the farthest plane in a certain direction, it wont necessarily be the plane given by MPR, because it may not be the closest plane to the origin, for example:

In this case i would still need to determine which plane would be intersected.
I guess what im trying to ask is a) can i use my boolean GJK test to first determine whether a intersection has occuredand then go about ray casting and determining the plane that will be intersected? Do i have to use an MPR implementation?
Is there a way to find which plane it would be intersecting wittout MPR?
#4844213 Penetration depth and direction
Posted by pondwater
on 03 August 2011 - 02:49 PM
So i've finished up my GJK algorithm and now im attempting to implement the EPA algorithm to determine penetration depth. From what i understand it returns a vector representing the direction and magnitude of the smallest penetration.
For me this isnt exactly what i want. I need an algorithm that would return the penetration depth for a specific direction. For example:

Lets says i have an object moving in a particular direction, i want to determine the penetration depth in that direction so i can rectify the proper position as seen in A, verses B which gives the minimum penetration depth.
I assume this would be simpler than the typical EPA algorithm in that it only needs to search in a particular direction to find the distance from the origin to the hull of the minkowski difference. Any suggestions about finding the distance as precisely as possible?
Im thinking something along the lines of searching for the farthest point in the opposite direction the object is travelling in. However that is confined to vertices and wont be too accurate in some cases. Any ideas?
For me this isnt exactly what i want. I need an algorithm that would return the penetration depth for a specific direction. For example:

Lets says i have an object moving in a particular direction, i want to determine the penetration depth in that direction so i can rectify the proper position as seen in A, verses B which gives the minimum penetration depth.
I assume this would be simpler than the typical EPA algorithm in that it only needs to search in a particular direction to find the distance from the origin to the hull of the minkowski difference. Any suggestions about finding the distance as precisely as possible?
Im thinking something along the lines of searching for the farthest point in the opposite direction the object is travelling in. However that is confined to vertices and wont be too accurate in some cases. Any ideas?
#4798221 OpenGL Superbible Chapter 13 issues
Posted by pondwater
on 13 April 2011 - 07:06 PM
Okay so im having issues trying to the get wglChoosePixelFormatARB functions to work properly. For some reason it cannot find any suitable pixel format... I have a decent graphics card (NVIDIA GeForce GTS 250) and have updated the drivers, I dont see why its having an issue. There are no issues with glew as far as i know. I dont understand why i'm having this issue.
I've inluded the code, its taken straight from the google code project superbible 5th edition source.
This is a screenshot of my console showing the error messages the code produces: http://imgur.com/G0bAA
Any ideas as to what could be causing the issue?
Code:
I've inluded the code, its taken straight from the google code project superbible 5th edition source.
This is a screenshot of my console showing the error messages the code produces: http://imgur.com/G0bAA
Any ideas as to what could be causing the issue?
Code:
// SphereWorld_redux.cpp
// OpenGL SuperBible Chapter 13
// New and improved (performance) sphere world
// Program by Richard S. Wright Jr. and Nicholas Haemel
#include <gltools.h>
#include <GLShaderManager.h>
#include <GLFrustum.h>
#include <GLBatch.h>
#include <GLMatrixStack.h>
#include <GLGeometryTransform.h>
#include <Stopwatch.h>
#include <gl\wglew.h>
#include <math.h>
#include <stdio.h>
#include <iostream>
GLShaderManager shaderManager; // Shader Manager
GLMatrixStack modelViewMatrix; // Modelview Matrix
GLMatrixStack projectionMatrix; // Projection Matrix
GLFrustum viewFrustum; // View Frustum
GLGeometryTransform transformPipeline; // Geometry Transform Pipeline
GLFrame cameraFrame; // Camera frame
GLTriangleBatch torusBatch;
GLTriangleBatch sphereBatch;
GLBatch groundBatch;
GLBatch floorBatch;
GLuint uiTextures[3];
static const TCHAR g_szAppName[] = TEXT("Sphere World Redux");
static const TCHAR g_szClassName[50] = TEXT("OGL_CLASS");
static const int g_nWinWidth = 800;
static const int g_nWinHeight = 600;
HWND g_hWnd;
HGLRC g_hRC;
HDC g_hDC;
HINSTANCE g_hInstance;
WNDCLASS g_windClass;
RECT g_windowRect;
bool g_ContinueRendering;
bool g_InFullScreen;
void DrawSongAndDance(GLfloat yRot) // Called to draw dancing objects
{
static GLfloat vWhite[] = { 1.0f, 1.0f, 1.0f, 1.0f };
static GLfloat vLightPos[] = { 0.0f, 3.0f, 0.0f, 1.0f };
// Get the light position in eye space
M3DVector4f vLightTransformed;
M3DMatrix44f mCamera;
modelViewMatrix.GetMatrix(mCamera);
m3dTransformVector4(vLightTransformed, vLightPos, mCamera);
// Draw the light source
modelViewMatrix.PushMatrix();
modelViewMatrix.Translatev(vLightPos);
shaderManager.UseStockShader(GLT_SHADER_FLAT,
transformPipeline.GetModelViewProjectionMatrix(),
vWhite);
sphereBatch.Draw();
modelViewMatrix.PopMatrix();
// Song and dance
modelViewMatrix.Translate(0.0f, 0.2f, -2.5f);
modelViewMatrix.PushMatrix(); // Saves the translated origin
modelViewMatrix.Rotate(yRot, 0.0f, 1.0f, 0.0f);
// Draw stuff relative to the camera
glBindTexture(GL_TEXTURE_2D, uiTextures[1]);
shaderManager.UseStockShader(GLT_SHADER_TEXTURE_POINT_LIGHT_DIFF,
modelViewMatrix.GetMatrix(),
transformPipeline.GetProjectionMatrix(),
vLightTransformed,
vWhite,
0);
torusBatch.Draw();
modelViewMatrix.PopMatrix(); // Erased the rotate
modelViewMatrix.Rotate(yRot * -2.0f, 0.0f, 1.0f, 0.0f);
modelViewMatrix.Translate(0.8f, 0.0f, 0.0f);
glBindTexture(GL_TEXTURE_2D, uiTextures[2]);
shaderManager.UseStockShader(GLT_SHADER_TEXTURE_POINT_LIGHT_DIFF,
modelViewMatrix.GetMatrix(),
transformPipeline.GetProjectionMatrix(),
vLightTransformed,
vWhite,
0);
sphereBatch.Draw();
}
bool LoadTGATexture(const char *szFileName, GLenum minFilter, GLenum magFilter, GLenum wrapMode)
{
GLbyte *pBits;
int nWidth, nHeight, nComponents;
GLenum eFormat;
// Read the texture bits
pBits = gltReadTGABits(szFileName, &nWidth, &nHeight, &nComponents, &eFormat);
if(pBits == NULL)
return false;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapMode);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapMode);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);
if(minFilter == GL_LINEAR_MIPMAP_LINEAR ||
minFilter == GL_LINEAR_MIPMAP_NEAREST ||
minFilter == GL_NEAREST_MIPMAP_LINEAR ||
minFilter == GL_NEAREST_MIPMAP_NEAREST)
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
glTexImage2D(GL_TEXTURE_2D, 0, nComponents, nWidth, nHeight, 0,
eFormat, GL_UNSIGNED_BYTE, pBits);
free(pBits);
return true;
}
//////////////////////////////////////////////////////////////////
// This function does any needed initialization on the rendering
// context.
void SetupRC()
{
// Initialze Shader Manager
shaderManager.InitializeStockShaders();
glEnable(GL_DEPTH_TEST);
glEnable(GL_MULTISAMPLE);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
// This makes a torus
gltMakeTorus(torusBatch, 0.4f, 0.15f, 20, 20);
// This makes a sphere
gltMakeSphere(sphereBatch, 0.1f, 26, 13);
// This makes the ground lines
groundBatch.Begin(GL_LINES, 328);
for(GLfloat x = -20.0f; x <= 20.0f; x+= 0.5f)
{
groundBatch.Vertex3f(x, -0.4f, 20.0f); // Parallel to X, cross the z axis
groundBatch.Vertex3f(x, -0.4f, -20.0f);
groundBatch.Vertex3f(20.0f, -0.4f, x); // Parallel to Z, cross the x axis
groundBatch.Vertex3f(-20.0f, -0.4f, x);
}
groundBatch.End();
// Make the solid ground
GLfloat alpha = 0.25f;
GLfloat texSize = 10.0f;
floorBatch.Begin(GL_TRIANGLE_FAN, 4, 1);
floorBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
floorBatch.Color4f(1.0f, 1.0f, 1.0f, alpha);
floorBatch.Vertex3f(-20.0f, -0.41f, 20.0f);
floorBatch.MultiTexCoord2f(0, texSize, 0.0f);
floorBatch.Color4f(1.0f, 1.0f, 1.0f, alpha);
floorBatch.Vertex3f(20.0f, -0.41f, 20.0f);
floorBatch.MultiTexCoord2f(0, texSize, texSize);
floorBatch.Color4f(1.0f, 1.0f, 1.0f, alpha);
floorBatch.Vertex3f(20.0f, -0.41f, -20.0f);
floorBatch.MultiTexCoord2f(0, 0.0f, texSize);
floorBatch.Color4f(1.0f, 1.0f, 1.0f, alpha);
floorBatch.Vertex3f(-20.0f, -0.41f, -20.0f);
floorBatch.End();
// Make 3 texture objects
glGenTextures(3, uiTextures);
// Load the Marble
glBindTexture(GL_TEXTURE_2D, uiTextures[0]);
LoadTGATexture("marble.tga", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR, GL_REPEAT);
// Load Mars
glBindTexture(GL_TEXTURE_2D, uiTextures[1]);
LoadTGATexture("marslike.tga", GL_LINEAR_MIPMAP_LINEAR,
GL_LINEAR, GL_CLAMP_TO_EDGE);
// Load Moon
glBindTexture(GL_TEXTURE_2D, uiTextures[2]);
LoadTGATexture("moonlike.tga", GL_LINEAR_MIPMAP_LINEAR,
GL_LINEAR, GL_CLAMP_TO_EDGE);
}
void CheckErrors(GLuint progName = 0)
{
GLenum error = glGetError();
if (error != GL_NO_ERROR)
{
fprintf(stderr, "A GL Error has occured\n");
}
GLenum fboStatus = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
if(fboStatus != GL_FRAMEBUFFER_COMPLETE)
{
switch (fboStatus)
{
case GL_FRAMEBUFFER_UNDEFINED:
// Oops, no window exists?
break;
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
// Check the status of each attachment
break;
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
// Attach at least one buffer to the FBO
break;
case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
// Check that all attachments enabled via
// glDrawBuffers exist in FBO
case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
// Check that the buffer specified via
// glReadBuffer exists in FBO
break;
case GL_FRAMEBUFFER_UNSUPPORTED:
// Reconsider formats used for attached buffers
break;
case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
// Make sure the number of samples for each
// attachment is the same
break;
//case GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS:
// Make sure the number of layers for each
// attachment is the same
//break;
}
fprintf(stderr,"The framebuffer is not complete\n");
}
if (progName != 0)
{
glValidateProgram(progName);
int iIsProgValid = 0;
glGetProgramiv(progName, GL_VALIDATE_STATUS, &iIsProgValid);
if(iIsProgValid == 0)
{
fprintf(stderr,"The current program is not valid\n");
}
}
}
// Called to draw scene
void RenderScene(void)
{
if(!g_ContinueRendering)
return;
static CStopWatch rotTimer;
float yRot = rotTimer.GetElapsedSeconds() * 60.0f;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
modelViewMatrix.PushMatrix();
M3DMatrix44f mCamera;
cameraFrame.GetCameraMatrix(mCamera);
modelViewMatrix.MultMatrix(mCamera);
// Draw the world upside down
modelViewMatrix.PushMatrix();
modelViewMatrix.Scale(1.0f, -1.0f, 1.0f); // Flips the Y Axis
modelViewMatrix.Translate(0.0f, 0.8f, 0.0f); // Scootch the world down a bit...
glFrontFace(GL_CW);
DrawSongAndDance(yRot);
glFrontFace(GL_CCW);
modelViewMatrix.PopMatrix();
// Draw the solid ground
glEnable(GL_BLEND);
glBindTexture(GL_TEXTURE_2D, uiTextures[0]);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
static GLfloat vFloorColor[] = { 1.0f, 1.0f, 1.0f, 0.75f};
shaderManager.UseStockShader(GLT_SHADER_TEXTURE_MODULATE,
transformPipeline.GetModelViewProjectionMatrix(),
vFloorColor,
0);
floorBatch.Draw();
glDisable(GL_BLEND);
DrawSongAndDance(yRot);
modelViewMatrix.PopMatrix();
// Do the buffer Swap
SwapBuffers(g_hDC);
CheckErrors();
}
// Respond to arrow keys by moving the camera frame of reference
void SpecialKeys(int key)
{
float linear = 0.1f;
float angular = float(m3dDegToRad(5.0f));
if(key == VK_UP)
cameraFrame.MoveForward(linear);
if(key == VK_DOWN)
cameraFrame.MoveForward(-linear);
if(key == VK_LEFT)
cameraFrame.RotateWorld(angular, 0.0f, 1.0f, 0.0f);
if(key == VK_RIGHT)
cameraFrame.RotateWorld(-angular, 0.0f, 1.0f, 0.0f);
if(key == VK_ESCAPE ||key == 'q' || key == 'Q')
{
g_ContinueRendering = false;
PostQuitMessage(0);
}
}
void ChangeSize(int nWidth, int nHeight)
{
glViewport(0, 0, nWidth, nHeight);
transformPipeline.SetMatrixStacks(modelViewMatrix, projectionMatrix);
viewFrustum.SetPerspective(35.0f, float(nWidth)/float(nHeight), 1.0f, 100.0f);
projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());
modelViewMatrix.LoadIdentity();
}
///////////////////////////////////////////////////////////////////////////////
// Callback functions to handle all window functions this app cares about.
// Once complete, pass message on to next app in the hook chain.
LRESULT CALLBACK WndProc( HWND hWnd, // Handle For This Window
UINT uMsg, // Message For This Window
WPARAM wParam, // Additional Message Information
LPARAM lParam) // Additional Message Information
{
// Handle relevant messages individually
switch(uMsg)
{
case WM_ACTIVATE:
case WM_SETFOCUS:
RenderScene();
return 0;
case WM_SIZE:
ChangeSize(LOWORD(lParam),HIWORD(lParam));
RenderScene();
break;
case WM_CLOSE:
g_ContinueRendering = false;
PostQuitMessage(0);
return 0;
case WM_KEYDOWN:
SpecialKeys((unsigned int)wParam);
return 0;
default:
// Nothing to do now
break;
}
// Pass All Unhandled Messages To DefWindowProc
return DefWindowProc(hWnd,uMsg,wParam,lParam);
}
///////////////////////////////////////////////////////////////////////////////
// Setup the actual window and related state.
// Create the window, find a pixel format, create the OpenGL context
bool SetupWindow(int nWidth, int nHeight, bool bUseFS)
{
bool bRetVal = true;
int nWindowX = 0;
int nWindowY = 0;
int nPixelFormat = -1;
PIXELFORMATDESCRIPTOR pfd;
DWORD dwExtStyle;
DWORD dwWindStyle;
HINSTANCE g_hInstance = GetModuleHandle(NULL);
// setup window class
g_windClass.lpszClassName = g_szClassName; // Set the name of the Class
g_windClass.lpfnWndProc = (WNDPROC)WndProc;
g_windClass.hInstance = g_hInstance; // Use this module for the module handle
g_windClass.hCursor = LoadCursor(NULL, IDC_ARROW);// Pick the default mouse cursor
g_windClass.hIcon = LoadIcon(NULL, IDI_WINLOGO);// Pick the default windows icons
g_windClass.hbrBackground = NULL; // No Background
g_windClass.lpszMenuName = NULL; // No menu for this window
g_windClass.style = CS_HREDRAW | CS_OWNDC | // set styles for this class, specifically to catch
CS_VREDRAW; // window redraws, unique DC, and resize
g_windClass.cbClsExtra = 0; // Extra class memory
g_windClass.cbWndExtra = 0; // Extra window memory
// Register the newly defined class
if(!RegisterClass( &g_windClass ))
bRetVal = false;
dwExtStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
dwWindStyle = WS_OVERLAPPEDWINDOW;
ShowCursor(TRUE);
g_windowRect.left = nWindowX;
g_windowRect.right = nWindowX + nWidth;
g_windowRect.top = nWindowY;
g_windowRect.bottom = nWindowY + nHeight;
// Setup window width and height
AdjustWindowRectEx(&g_windowRect, dwWindStyle, FALSE, dwExtStyle);
//Adjust for adornments
int nWindowWidth = g_windowRect.right - g_windowRect.left;
int nWindowHeight = g_windowRect.bottom - g_windowRect.top;
// Create window
g_hWnd = CreateWindowEx(dwExtStyle, // Extended style
g_szClassName, // class name
g_szAppName, // window name
dwWindStyle |
WS_CLIPSIBLINGS |
WS_CLIPCHILDREN,// window stlye
nWindowX, // window position, x
nWindowY, // window position, y
nWindowWidth, // height
nWindowHeight, // width
NULL, // Parent window
NULL, // menu
g_hInstance, // instance
NULL); // pass this to WM_CREATE
// now that we have a window, setup the pixel format descriptor
g_hDC = GetDC(g_hWnd);
// Set a dummy pixel format so that we can get access to wgl functions
SetPixelFormat( g_hDC, 1,&pfd);
// Create OGL context and make it current
g_hRC = wglCreateContext( g_hDC );
wglMakeCurrent( g_hDC, g_hRC );
if (g_hDC == 0 ||
g_hDC == 0)
{
bRetVal = false;
printf("!!! An error occured creating an OpenGL window.\n");
}
// Setup GLEW which loads OGL function pointers
GLenum err = glewInit();
if (GLEW_OK != err)
{
/* Problem: glewInit failed, something is seriously wrong. */
bRetVal = false;
printf("Error: %s\n", glewGetErrorString(err));
}
const GLubyte *oglVersion = glGetString(GL_VERSION);
printf("This system supports OpenGL Version %s.\n", oglVersion);
// Now that extensions are setup, delete window and start over picking a real format.
wglMakeCurrent(NULL, NULL);
wglDeleteContext(g_hRC);
ReleaseDC(g_hWnd, g_hDC);
DestroyWindow(g_hWnd);
if(bUseFS)
{
// Prepare for a mode set to the requested resolution
DEVMODE dm;
memset(&dm,0,sizeof(dm));
dm.dmSize=sizeof(dm);
dm.dmPelsWidth = nWidth;
dm.dmPelsHeight = nHeight;
dm.dmBitsPerPel = 32;
dm.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;
long error = ChangeDisplaySettings(&dm, CDS_FULLSCREEN);
if (error != DISP_CHANGE_SUCCESSFUL)
{
// Oops, something went wrong, let the user know.
if (MessageBox(NULL, "Could not set fullscreen mode.\n"
"Your video card may not support the requested mode.\n"
"Use windowed mode instead?",
g_szAppName, MB_YESNO|MB_ICONEXCLAMATION)==IDYES)
{
g_InFullScreen = false;
dwExtStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
dwWindStyle = WS_OVERLAPPEDWINDOW;
}
else
{
MessageBox(NULL, "Program will exit.", "ERROR", MB_OK|MB_ICONSTOP);
return false;
}
}
else
{
// Mode set passed, setup the styles for fullscreen
g_InFullScreen = true;
dwExtStyle = WS_EX_APPWINDOW;
dwWindStyle = WS_POPUP;
ShowCursor(FALSE);
}
}
AdjustWindowRectEx(&g_windowRect, dwWindStyle, FALSE, dwExtStyle);
// Create the window again
g_hWnd = CreateWindowEx(dwExtStyle, // Extended style
g_szClassName, // class name
g_szAppName, // window name
dwWindStyle |
WS_CLIPSIBLINGS |
WS_CLIPCHILDREN,// window stlye
nWindowX, // window position, x
nWindowY, // window position, y
nWindowWidth, // height
nWindowHeight, // width
NULL, // Parent window
NULL, // menu
g_hInstance, // instance
NULL); // pass this to WM_CREATE
g_hDC = GetDC(g_hWnd);
int nPixCount = 0;
// Specify the important attributes we care about
int pixAttribs[] = { WGL_SUPPORT_OPENGL_ARB, 1, // Must support OGL rendering
WGL_DRAW_TO_WINDOW_ARB, 1, // pf that can run a window
WGL_ACCELERATION_ARB, 1, // must be HW accelerated
WGL_COLOR_BITS_ARB, 24, // 8 bits of each R, G and B
WGL_DEPTH_BITS_ARB, 16, // 16 bits of depth precision for window
WGL_DOUBLE_BUFFER_ARB, GL_TRUE, // Double buffered context
WGL_SAMPLE_BUFFERS_ARB, GL_TRUE, // MSAA on
WGL_SAMPLES_ARB, 8, // 8x MSAA
WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB, // pf should be RGBA type
0}; // NULL termination
// Ask OpenGL to find the most relevant format matching our attribs
// Only get one format back.
wglChoosePixelFormatARB(g_hDC, &pixAttribs[0], NULL, 1, &nPixelFormat, (UINT*)&nPixCount);
if(nPixelFormat == -1)
{
printf("!!! An error occurred trying to find a MSAA pixel format with the requested attribs.\n");
// Try again without MSAA
pixAttribs[15] = 1;
wglChoosePixelFormatARB(g_hDC, &pixAttribs[0], NULL, 1, &nPixelFormat, (UINT*)&nPixCount);
if(nPixelFormat == -1)
{
// Couldn't find a format, perhaps no 3D HW or drivers are installed
g_hDC = 0;
g_hDC = 0;
bRetVal = false;
printf("!!! An error occurred trying to find a pixel format with the requested attribs.\n");
}
}
if(nPixelFormat != -1)
{
// Check for MSAA
int attrib[] = { WGL_SAMPLES_ARB };
int nResults = 0;
wglGetPixelFormatAttribivARB(g_hDC, nPixelFormat, 0, 1, attrib, &nResults);
printf("Chosen pixel format is MSAA with %d samples.\n", nResults);
// Got a format, now set it as the current one
SetPixelFormat( g_hDC, nPixelFormat, &pfd );
GLint attribs[] = {WGL_CONTEXT_MAJOR_VERSION_ARB, 3,
WGL_CONTEXT_MINOR_VERSION_ARB, 3,
0 };
g_hRC = wglCreateContextAttribsARB(g_hDC, 0, attribs);
if (g_hRC == NULL)
{
printf("!!! Could not create an OpenGL 3.3 context.\n");
attribs[3] = 2;
g_hRC = wglCreateContextAttribsARB(g_hDC, 0, attribs);
if (g_hRC == NULL)
{
printf("!!! Could not create an OpenGL 3.2 context.\n");
attribs[3] = 1;
g_hRC = wglCreateContextAttribsARB(g_hDC, 0, attribs);
if (g_hRC == NULL)
{
printf("!!! Could not create an OpenGL 3.1 context.\n");
attribs[3] = 0;
g_hRC = wglCreateContextAttribsARB(g_hDC, 0, attribs);
if (g_hRC == NULL)
{
printf("!!! Could not create an OpenGL 3.0 context.\n");
printf("!!! OpenGL 3.0 and higher are not supported on this system.\n");
}
}
}
}
wglMakeCurrent( g_hDC, g_hRC );
}
if (g_hDC == 0 ||
g_hDC == 0)
{
bRetVal = false;
printf("!!! An error occured creating an OpenGL window.\n");
}
// If everything went as planned, display the window
if( bRetVal )
{
ShowWindow( g_hWnd, SW_SHOW );
SetForegroundWindow( g_hWnd );
SetFocus( g_hWnd );
g_ContinueRendering = true;
}
return bRetVal;
}
///////////////////////////////////////////////////////////////////////////////
// Cleanup window, OGL context and related state
// Called on exit and on error
bool KillWindow( )
{
bool bRetVal = true;
glDeleteTextures(3,uiTextures);
if (g_InFullScreen)
{
ChangeDisplaySettings(NULL,0);
ShowCursor(TRUE);
}
//Cleanup OGL RC
if(g_hRC)
{
wglMakeCurrent(NULL, NULL);
wglDeleteContext(g_hRC);
g_hRC = NULL;
}
// release the DC
if(g_hDC)
{
ReleaseDC(g_hWnd, g_hDC);
g_hDC = NULL;
}
// Destroy the window
if(g_hWnd)
{
DestroyWindow(g_hWnd);
g_hWnd = NULL;;
}
// Delete the window class
UnregisterClass(g_szClassName, g_hInstance);
g_hInstance = NULL;
ShowCursor(TRUE);
return bRetVal;
}
///////////////////////////////////////////////////////////////////////////////
// Main rendering loop
// Check for window messages and handle events, also draw scene
void mainLoop()
{
MSG msg;
// Check for waiting mssgs
if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
if (msg.message==WM_QUIT)
{
g_ContinueRendering = false;
}
else
{
// Deal with mssgs
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
else
{
RenderScene();
}
}
///////////////////////////////////////////////////////////////////////////////
// Main program function, called on startup
// First setup the window and OGL state, then enter rendering loop
int main(int argc, char* argv[])
{
gltSetWorkingDirectory(argv[0]);
bool bUseFS = false;
if (MessageBox(NULL, "Would you like to run in Fullscreen Mode?", g_szAppName, MB_YESNO|MB_ICONEXCLAMATION)==IDYES)
{
bUseFS = true;
}
if(SetupWindow(g_nWinWidth, g_nWinHeight, bUseFS))
{
SetupRC();
ChangeSize(g_nWinWidth, g_nWinHeight);
while (g_ContinueRendering)
{
mainLoop();
Sleep(0);
}
}
KillWindow();
system("PAUSE");
return 0;
}
- Home
- » Viewing Profile: Reputation: pondwater

Find content