Unable to glTranslate() light source - c++

I am having a problem translating the light source.
I have coded a program that accepts up, down, left, and right keys to increase/decrease the x, y, and z values to reposition the light source. But the problem right now is the x, y, and z value does change but the light source remains in the same place. I believe the problem shall be somewhere inside the void lighting() function.
below is my code:
#include <Windows.h>
#include <gl/GL.h>
#include <math.h>
#include <gl/GLU.h>
#pragma comment (lib, "OpenGL32.lib") //link library
#pragma comment(lib, "Winmm.lib")
#define WINDOW_TITLE "Lighting"
bool isOrtho = true;
float ONear = -10.0, OFar = 10.0; //Ortho Near & Far
float PNear = 1.0, PFar = 21.0; //Perspective Near & Far
float exeDif[3] = { 1.0,0.0,0.0 }; //Red diffuse light
float x =6 , y=0, z=0;
float exePosD[3] = { 6,0,0 };
float exeDifM[3] = { 1.0,0.0,0.0 };
bool isLightOn = false; //is light on?
LRESULT WINAPI WindowProcedure(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_DESTROY:
PostQuitMessage(0);//quit application
break;
case WM_KEYDOWN:
if (wParam == VK_ESCAPE) PostQuitMessage(0);
else if (wParam == VK_SPACE) {
isLightOn = !isLightOn;
}
else if (wParam == VK_UP) {
y = y + 1.0;
}
else if (wParam == VK_DOWN) {
y = y - 1.0;
}
else if (wParam == VK_LEFT) {
x = x - 1.0;
}
else if (wParam == VK_RIGHT) {
x = x + 1.0;
}
else if (wParam == 'Q') {
z = z - 1.0;
}
else if (wParam == 'E') {
z = z + 1.0;
}
break;
default:
break;
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}
bool initPixelFormat(HDC hdc)
{
PIXELFORMATDESCRIPTOR pfd;
ZeroMemory(&pfd, sizeof(PIXELFORMATDESCRIPTOR));
pfd.cAlphaBits = 8;
pfd.cColorBits = 32;
pfd.cDepthBits = 24;
pfd.cStencilBits = 0;
pfd.dwFlags = PFD_DOUBLEBUFFER | PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW;
pfd.iLayerType = PFD_MAIN_PLANE;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
pfd.nVersion = 1;
// choose pixel format returns the number most similar pixel format available
int n = ChoosePixelFormat(hdc, &pfd);
// set pixel format returns whether it sucessfully set the pixel format
if (SetPixelFormat(hdc, n, &pfd))
{
return true;
}
else
{
return false;
}
}
void lighting() {
if (isLightOn) {
glEnable(GL_LIGHTING); //Turon on lighting for the whole scene
}
else {
//Turn off lighting for the whole screen
glDisable(GL_LIGHTING);
}
glPushMatrix();
glTranslatef(x, y, z);
glLightfv(GL_LIGHT0, GL_POSITION, exePosD);
glPopMatrix();
glLightfv(GL_LIGHT0, GL_DIFFUSE, exeDif);
glEnable(GL_LIGHT0);
}
void projection() {
glMatrixMode(GL_PROJECTION); //refer to projection matrix
glLoadIdentity(); //reset projection matrix
if (isOrtho) {
//Ortho View
glOrtho(-10.0, 10.0, -10.0, 10.0, ONear, OFar); //Ortho view
}
else {
//Perspective view
gluPerspective(20, 1.0, -1.0, 1.0);
glFrustum(-10.0, 10.0, -10.0, 10.0, PNear, PFar);
}
}
void drawSphere(double r) {
GLUquadricObj* sphere = NULL;
sphere = gluNewQuadric();
gluQuadricDrawStyle(sphere, GLU_FILL);
gluSphere(sphere, r, 30, 30);
gluDeleteQuadric(sphere);
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
projection(); //projection
lighting();
glMatrixMode(GL_MODELVIEW); //refer to modelview matrix
glLoadIdentity(); //reset
drawSphere(3.0);
//red color diffuse
glMaterialfv(GL_FRONT, GL_DIFFUSE, exeDifM);
glColor3f(0.0, 0.0, 1.0); //blue
drawSphere(3.0);
}
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR, int nCmdShow)
{
WNDCLASSEX wc;
ZeroMemory(&wc, sizeof(WNDCLASSEX));
wc.cbSize = sizeof(WNDCLASSEX);
wc.hInstance = GetModuleHandle(NULL);
wc.lpfnWndProc = WindowProcedure;
wc.lpszClassName = WINDOW_TITLE;
wc.style = CS_HREDRAW | CS_VREDRAW;
if (!RegisterClassEx(&wc)) return false;
HWND hWnd = CreateWindow(WINDOW_TITLE, WINDOW_TITLE, WS_OVERLAPPEDWINDOW,
720, 10, 300, 300,
NULL, NULL, wc.hInstance, NULL);
//--------------------------------
// Initialize window for OpenGL
//--------------------------------
HDC hdc = GetDC(hWnd);
// initialize pixel format for the window
initPixelFormat(hdc);
// get an openGL context
HGLRC hglrc = wglCreateContext(hdc);
// make context current
if (!wglMakeCurrent(hdc, hglrc)) return false;
//--------------------------------
// End initialization
//--------------------------------
ShowWindow(hWnd, nCmdShow);
MSG msg;
ZeroMemory(&msg, sizeof(msg));
while (true)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT) break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
display();
SwapBuffers(hdc);
}
UnregisterClass(WINDOW_TITLE, wc.hInstance);
return true;
}
This is the output screen:

The light position is transformed with the modelview matrix, but not with the projection matrix. Therefore you need to switch to the modelview matrix after projection() and before lighting():
projection(); //projection
glMatrixMode(GL_MODELVIEW); //refer to modelview matrix
glLoadIdentity();
lighting();

Related

Double buffering in Direct2D?

I'm very new to Direct2D programming and have been following a tutorial. I've adapted the example given in the tutorial to a slightly more complicated program that bounces a ball off the boundaries of the window.
My main program (main.cpp):
#include "Graphics.h"
Graphics* graphics;
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
// Exit handler
if (uMsg == WM_DESTROY)
{
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE prevInstance, LPWSTR cmd, int nCmdShow)
{
WNDCLASSEX windowClass;
SecureZeroMemory(&windowClass, sizeof(WNDCLASSEX));
// Set up window
windowClass.cbSize = sizeof(WNDCLASSEX);
windowClass.hbrBackground = (HBRUSH)COLOR_WINDOW;
windowClass.hInstance = hInstance;
windowClass.lpfnWndProc = WindowProc;
windowClass.lpszClassName = "MainWindow";
windowClass.style = CS_HREDRAW | CS_VREDRAW;
// Register window class and handle
RegisterClassEx(&windowClass);
RECT rect = { 0, 0, 800, 600 };
AdjustWindowRectEx(&rect, WS_OVERLAPPEDWINDOW, false, WS_EX_OVERLAPPEDWINDOW);
HWND windowHandle = CreateWindowEx(WS_EX_OVERLAPPEDWINDOW, "MainWindow", "Test Window", WS_OVERLAPPEDWINDOW, 100, 100,
rect.right - rect.left, rect.bottom - rect.top, NULL, NULL, hInstance, 0);
if (!windowHandle)
return -1;
graphics = new Graphics();
if (!graphics->Init(windowHandle))
{
delete graphics;
return -1;
}
ShowWindow(windowHandle, nCmdShow);
// Message loop
float x = 51.0, xSpeed = 5.0f, y = 0.0, ySpeed = 5.0f;
MSG message;
message.message = WM_NULL;
while (message.message != WM_QUIT)
{
if (PeekMessage(&message, NULL, 0, 0, PM_REMOVE))
DispatchMessage(&message);
else
{
// Ball physics
//xSpeed += 0.6f;
x += xSpeed;
ySpeed += 0.2f;
y += ySpeed;
if (y > rect.bottom - 50)
{
ySpeed = -ySpeed;
}
if (x > rect.right - 50)
{
xSpeed = -xSpeed;
}
else if (x < 50)
{
xSpeed = -xSpeed;
}
// Redraw ball
graphics->beginDraw();
graphics->clearScreen(0.0f, 0.0f, 0.5f);
graphics->drawCircle(x, y, 50.0f, 1.0f, 1.0f, 1.0f, 1.0f);
graphics->endDraw();
}
}
delete graphics;
return 0;
}
My header file (Graphics.h):
#pragma once
#include <Windows.h>
#include <d2d1.h>
class Graphics
{
ID2D1Factory* factory;
ID2D1HwndRenderTarget* renderTarget;
ID2D1SolidColorBrush* brush;
public:
Graphics();
~Graphics();
bool Init(HWND windowHandle);
void beginDraw() { renderTarget->BeginDraw(); }
void endDraw() { renderTarget->EndDraw(); }
void clearScreen(float r, float g, float b);
void drawCircle(float x, float y, float radius, float r, float g, float b, float a);
};
My graphics functions (Graphics.cpp):
#include "Graphics.h"
#define CHECKRES if (res != S_OK) return false
Graphics::Graphics()
{
factory = NULL;
renderTarget = NULL;
brush = NULL;
}
Graphics::~Graphics()
{
if (factory)
factory->Release();
if (renderTarget)
renderTarget->Release();
if (brush)
brush->Release();
}
bool Graphics::Init(HWND windowHandle)
{
HRESULT res = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &factory);
CHECKRES;
RECT rect;
GetClientRect(windowHandle, &rect);
res = factory->CreateHwndRenderTarget(
D2D1::RenderTargetProperties(),
D2D1::HwndRenderTargetProperties(windowHandle, D2D1::SizeU(rect.right, rect.bottom)),
&renderTarget
);
CHECKRES;
res = renderTarget->CreateSolidColorBrush(D2D1::ColorF(0, 0, 0, 0), &brush);
CHECKRES;
return true;
}
void Graphics::clearScreen(float r, float g, float b)
{
renderTarget->Clear(D2D1::ColorF(r, g, b));
}
void Graphics::drawCircle(float x, float y, float radius, float r, float g, float b, float a)
{
brush->SetColor(D2D1::ColorF(r, g, b, a));
renderTarget->DrawEllipse(D2D1::Ellipse(D2D1::Point2F(x, y), radius, radius), brush, 3.0f);
}
While this program does work fine, there is some minor tearing on the ball's bounce. I have seen this question which lead me to this MSDN article. Despite reading the article, I do still not fully understand how to implement double buffering, to hopefully reduce tearing. Can someone provide a concise example and explanation of the ID2D1RenderTarget::CreateCompatibleRenderTarget, as this high level Windows programming is quite different from what I'm used to?
Check article here. ID2D1HwndRenderTarget objects are double buffered by nature and drawing is done to the offscreen buffer first and when drawing ends it will be blitted to the screen.

OpenGL primitives in Win32 window distorted according to window size

I've made a simple OpenGL program in C that draws a triangle rotating inside a box. The triangle is supposed to be equilateral but even when the window width and height are the same the triangles vertices contract and extrude when they go along the width and length of the window. I can tell because I made a static equiangular box and the vertices of the triangle go outside of it. Here's a short clip of what it's doing: https://edwardseverinsen1717-gmail.tinytake.com/sf/NDg5NjQ0XzI2MDQzMDM Excuse the lag at some moments.
And here's my code:
#include <windows.h>
#include <gl/gl.h>
#include <gl/glu.h>
LRESULT CALLBACK WindowProc(HWND, UINT, WPARAM, LPARAM);
void EnableOpenGL(HWND hwnd, HDC*, HGLRC*);
void DisableOpenGL(HWND, HDC, HGLRC);
void DrawTriangle(float theta);
void DrawBox(void);
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
WNDCLASSEX wcex;
HWND hwnd;
HDC hDC;
HGLRC hRC;
MSG msg;
BOOL bQuit = FALSE;
float theta = 0.0f;
int i;
/* register window class */
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_OWNDC;
wcex.lpfnWndProc = WindowProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = "GLSample";
wcex.hIconSm = LoadIcon(NULL, IDI_APPLICATION);;
if (!RegisterClassEx(&wcex))
return 0;
/* create main window */
hwnd = CreateWindowEx(0,
"GLSample",
"OpenGL Sample",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
500,
500,
NULL,
NULL,
hInstance,
NULL);
ShowWindow(hwnd, nCmdShow);
/* enable OpenGL for the window */
EnableOpenGL(hwnd, &hDC, &hRC);
/* program main loop */
while (!bQuit)
{
/* check for messages */
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
/* handle or dispatch messages */
if (msg.message == WM_QUIT)
{
bQuit = TRUE;
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
else
{
/* OpenGL animation code goes here */
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
DrawTriangle(theta);
DrawBox();
SwapBuffers(hDC);
theta += 1.0f;
Sleep (1);
}
}
/* shutdown OpenGL */
DisableOpenGL(hwnd, hDC, hRC);
/* destroy the window explicitly */
DestroyWindow(hwnd);
return msg.wParam;
}
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_CLOSE:
PostQuitMessage(0);
break;
case WM_DESTROY:
return 0;
case WM_KEYDOWN:
{
switch (wParam)
{
case VK_ESCAPE:
PostQuitMessage(0);
break;
}
}
break;
default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
return 0;
}
void EnableOpenGL(HWND hwnd, HDC* hDC, HGLRC* hRC)
{
PIXELFORMATDESCRIPTOR pfd;
int iFormat;
/* get the device context (DC) */
*hDC = GetDC(hwnd);
/* set the pixel format for the DC */
ZeroMemory(&pfd, sizeof(pfd));
pfd.nSize = sizeof(pfd);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW |
PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 24;
pfd.cDepthBits = 16;
pfd.iLayerType = PFD_MAIN_PLANE;
iFormat = ChoosePixelFormat(*hDC, &pfd);
SetPixelFormat(*hDC, iFormat, &pfd);
/* create and enable the render context (RC) */
*hRC = wglCreateContext(*hDC);
wglMakeCurrent(*hDC, *hRC);
}
void DisableOpenGL (HWND hwnd, HDC hDC, HGLRC hRC)
{
wglMakeCurrent(NULL, NULL);
wglDeleteContext(hRC);
ReleaseDC(hwnd, hDC);
}
void DrawTriangle(float theta)
{
glPushMatrix();
if(theta != 0)
{
glRotatef(theta, 0.0f, 0.0f, 1.0f);
}
if(theta == 1)
{
glRotatef(89, 0.0f, 0.0f, 1.0f);
}
glBegin(GL_TRIANGLES);
glColor3f(1.0f, 0.0f, 0.0f); glVertex2f(0.0f, 0.50f);
glColor3f(1.0f, 0.0f, 0.0f); glVertex2f(0.45f, -0.50f);
glColor3f(1.0f, 0.0f, 0.0f); glVertex2f(-0.45f, -0.50f);
glEnd();
glPopMatrix();
}
void DrawBox(void)
{
glPushMatrix();
glBegin(GL_LINE_LOOP);
glColor3f(1.0f, 0.0f, 0.0f); glVertex2f(0.45f, 0.5f); /*I decremented each x value by 0.05 to compensate for the bullshit with the window throwing off scale*/
glColor3f(1.0f, 0.0f, 0.0f); glVertex2f(0.45f, -0.5f);
glColor3f(1.0f, 0.0f, 0.0f); glVertex2f(-0.45f, -0.5f);
glColor3f(1.0f, 0.0f, 0.0f); glVertex2f(-0.45f, 0.5f);
glEnd();
glPopMatrix();
}
The coordinates you use do not span a equilateral triangle. Equilateral triangles always have three sides with the same length. In your example, the bottom side has a length of 0.9, but the other two have a length of sqrt(0.45^2 + 1.0^2) = 1.097. Even when assuming that you took 0.45 instead of 0.5, this is still not equilateral. (Bottom = 1.0, Other sides = sqrt(0.5^2 + 1.0^2) = 1.12)
As you have already noted, you have to compensate for the aspect ratio of the renderable area (which is not quadratic when passing 500x500 to CreateWindowEx since titlebar and borders are included here). This is normally done by defining a projection matrix with the correct aspect ratio of the client area. Have a look at GetClientRect to query the client area size and glOrtho to specify the projection matrix.

gluPerspective not working

I use gluPerspective to mainly increase the draw distance, but it doesn't seem to work.
This is how it shows in my code:
gluPerspective(0, 70/70, 0, 4333);
ratio: The window Width and Height is both 700 and they are constant, in case of wondering.
fovy: I put 0 because, "they" say that using 45 is very nice to draw, but it stops drawing on the screen.
This is the full code:
#include <Windows.h>
#include <gl\GL.h>
#include <gl/glut.h>
WNDCLASSEX wclass;
MSG msg;
HWND hwnd;
HDC hdc;
HDC p_hdc;
float t;
int red, green, blue, x, y, z;
void update()
{
RECT rec;
GetClientRect(hwnd, &rec);
InvalidateRect(hwnd, &rec, false);
UpdateWindow(hwnd);
t += 0.5f;
}
void game()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(0, 0, 0, 0);
float norm = 1;
float z = 0;
red = 255;
green = 255;
glPushMatrix();
glRotatef(t, 0, 1, 1);
glBegin(GL_TRIANGLES);
glColor3f(255, 0, 0);
glVertex3f(-norm, norm, z);
glVertex3f(norm, norm, z);
glColor3f(0, 110, 10);
glVertex3f(-norm, -norm, z);
glEnd();
gluPerspective(45, 70/70, 0.01f, 4333);
glPopMatrix();
SwapBuffers(hdc);
}
HGLRC hrc;
LRESULT CALLBACK WinProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
void EnableOpenGL(HWND hwnd, HDC* hDC, HGLRC* hRC);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpstr, int nCmdShow)
{
wclass.cbSize = sizeof(WNDCLASSEX);
wclass.style = 0;
wclass.lpfnWndProc = WinProc;
wclass.cbClsExtra = 0;
wclass.cbWndExtra = 0;
wclass.hInstance = hInstance;
wclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wclass.hbrBackground = (HBRUSH) (COLOR_WINDOW);
wclass.lpszMenuName = NULL;
wclass.lpszClassName = "CLASS";
wclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
if(!RegisterClassEx(&wclass))
{
MessageBox(0, "Windows Class Registration Failure Detected!\nProgram Can't Be Initialized..", "Failure Detected", MB_ICONERROR | MB_OK);
return 0;
}
hwnd = CreateWindowEx(
0, "CLASS", "OPENGL WORLD", WS_OVERLAPPEDWINDOW,
0, 0, 700, 700,
HWND_DESKTOP, NULL, hInstance, NULL
);
EnableOpenGL(hwnd, &hdc, &hrc);
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
if(hwnd == NULL)
{
MessageBox(0, "Windows Form Creation Failure..", "Failure", MB_ICONERROR | MB_OK);
}
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK WinProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_CREATE:
SetTimer(hwnd, 1, 1, NULL);
break;
case WM_DESTROY:
PostQuitMessage (0);
break;
case WM_TIMER:
game();
update();
break;
case WM_PAINT:
PAINTSTRUCT ps;
HDC win;
win = BeginPaint(hwnd, &ps);
p_hdc = win;
game();
EndPaint(hwnd, &ps);
break;
default:
return DefWindowProc (hwnd, msg, wParam, lParam);
}
return 0;
}
void EnableOpenGL(HWND hwnd, HDC* hDC, HGLRC* hRC)
{
PIXELFORMATDESCRIPTOR pfd;
int iFormat;
*hDC = GetDC(hwnd);
ZeroMemory(&pfd, sizeof(pfd));
pfd.nSize = sizeof(pfd);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW |
PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 24;
pfd.cDepthBits = 16;
pfd.iLayerType = PFD_MAIN_PLANE;
iFormat = ChoosePixelFormat(*hDC, &pfd);
SetPixelFormat(*hDC, iFormat, &pfd);
*hRC = wglCreateContext(*hDC);
wglMakeCurrent(*hDC, *hRC);
}
What to do?
EDIT: THE NEW CODE
#include <Windows.h>
#include <gl\GL.h>
#include <gl/glut.h>
WNDCLASSEX wclass;
MSG msg;
HWND hwnd;
HDC hdc;
HDC p_hdc;
float t;
int red, green, blue, x, y, z;
float cx, cy, cz;
void handle_resize()
{
RECT rec;
GetClientRect(hwnd, &rec);
long width = rec.right - rec.left;
long height = rec.top - rec.bottom;
float aspect = (float)width/(float)height;
glViewport(0, 0, 700, 700);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45, aspect, 0.01f, 99999);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void update()
{
RECT rec;
GetClientRect(hwnd, &rec);
InvalidateRect(hwnd, &rec, false);
UpdateWindow(hwnd);
t += 0.5f;
cz = -3;
}
void game()
{
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
float norm = 1;
float z = 0;
red = 255;
green = 255;
glPushMatrix();
glRotatef(t, 0, 1, 1);
glBegin(GL_TRIANGLES);
glColor3f(255, 0, 0);
glVertex3f(-norm, norm, z);
glVertex3f(norm, norm, z);
glColor3f(0, 110, 10);
glVertex3f(-norm, -norm, z);
glEnd();
glPopMatrix();
SwapBuffers(hdc);
}
HGLRC hrc;
LRESULT CALLBACK WinProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
void EnableOpenGL(HWND hwnd, HDC* hDC, HGLRC* hRC);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpstr, int nCmdShow)
{
wclass.cbSize = sizeof(WNDCLASSEX);
wclass.style = 0;
wclass.lpfnWndProc = WinProc;
wclass.cbClsExtra = 0;
wclass.cbWndExtra = 0;
wclass.hInstance = hInstance;
wclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wclass.hbrBackground = (HBRUSH) (COLOR_WINDOW);
wclass.lpszMenuName = NULL;
wclass.lpszClassName = "CLASS";
wclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
if(!RegisterClassEx(&wclass))
{
MessageBox(0, "Windows Class Registration Failure Detected!\nProgram Can't Be Initialized..", "Failure Detected", MB_ICONERROR | MB_OK);
return 0;
}
hwnd = CreateWindowEx(
0, "CLASS", "OPENGL WORLD", WS_OVERLAPPEDWINDOW,
0, 0, 700, 700,
HWND_DESKTOP, NULL, hInstance, NULL
);
EnableOpenGL(hwnd, &hdc, &hrc);
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
glMatrixMode(GL_PROJECTION);
glMatrixMode(GL_MODELVIEW);
if(hwnd == NULL)
{
MessageBox(0, "Windows Form Creation Failure..", "Failure", MB_ICONERROR | MB_OK);
}
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK WinProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_CREATE:
SetTimer(hwnd, 1, 1, NULL);
break;
case WM_DESTROY:
PostQuitMessage (0);
break;
case WM_TIMER:
game();
update();
break;
case WM_PAINT:
PAINTSTRUCT ps;
HDC win;
win = BeginPaint(hwnd, &ps);
p_hdc = win;
game();
EndPaint(hwnd, &ps);
break;
case WM_SIZE:
handle_resize();
break;
default:
return DefWindowProc (hwnd, msg, wParam, lParam);
}
return 0;
}
void EnableOpenGL(HWND hwnd, HDC* hDC, HGLRC* hRC)
{
PIXELFORMATDESCRIPTOR pfd;
int iFormat;
*hDC = GetDC(hwnd);
ZeroMemory(&pfd, sizeof(pfd));
pfd.nSize = sizeof(pfd);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW |
PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 24;
pfd.cDepthBits = 16;
pfd.iLayerType = PFD_MAIN_PLANE;
iFormat = ChoosePixelFormat(*hDC, &pfd);
SetPixelFormat(*hDC, iFormat, &pfd);
*hRC = wglCreateContext(*hDC);
wglMakeCurrent(*hDC, *hRC);
}
gluPerspective(0, 70/70, 0, 4333);
^ nope ^ nope
fovy and zNear must both be positive and non-zero.
Try this:
gluPerspective( 45, 70/70, 0.1, 4333 );
EDIT: Push your camera back a bit too:
#include <GL/glut.h>
float t = 0;
void timer( int val )
{
t += 0.5f;
glutTimerFunc( 10, timer, 0 );
glutPostRedisplay();
}
void display()
{
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
double w = glutGet( GLUT_WINDOW_WIDTH );
double h = glutGet( GLUT_WINDOW_HEIGHT );
gluPerspective( 45, w / h, 0.1, 4333.0 );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
glTranslatef( 0, 0, -5 );
float norm = 1;
float z = 0;
glPushMatrix();
glRotatef(t, 0, 1, 1);
glBegin(GL_TRIANGLES);
glColor3f(255, 0, 0);
glVertex3f(-norm, norm, z);
glVertex3f(norm, norm, z);
glColor3f(0, 110, 10);
glVertex3f(-norm, -norm, z);
glEnd();
glPopMatrix();
glutSwapBuffers();
}
int main( int argc, char **argv )
{
glutInit( &argc, argv );
glutInitDisplayMode( GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE );
glutInitWindowSize( 640, 480 );
glutCreateWindow( "GLUT" );
glutDisplayFunc( display );
glutTimerFunc( 0, timer, 0 );
glutMainLoop();
return 0;
}
As-per our comments, I made a few changes to your code that are necessary to properly deal with the perspective projection matrix and window sizing. There are still a number of things about this code that I do not like, such as drawing using a timer but this should at least address the small things.
New code:
void handle_resize (void)
{
RECT rec;
GetClientRect(hwnd, &rec);
long width = rec.right - rec.left;
long height = rec.top - rec.bottom;
float aspect = (float)width/(float)height;
glViewport (0, 0, width, height);
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
gluPerspective (45, aspect, 0.01f, 4333);
glMatrixMode (GL_MODELVIEW);
glLoadIdentity ();
}
void game()
{
glClearColor(0, 0, 0, 0); // Do this first
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
float norm = 1;
float z = 0;
red = 255;
green = 255;
glMatrixMode (GL_MODELVIEW);
glPushMatrix();
glRotatef(t, 0, 1, 1);
glBegin(GL_TRIANGLES);
glColor3ub(255, 0, 0);
glVertex3f(-norm, norm, z);
glVertex3f(norm, norm, z);
glColor3ub(0, 110, 10);
glVertex3f(-norm, -norm, z);
glEnd();
//gluPerspective(45, 70/70, 0.01f, 4333); // GET THIS OUT OF HERE!!!
glPopMatrix();
SwapBuffers(hdc);
}
Changes to your window message handler:
switch (msg)
{
case WM_CREATE:
SetTimer(hwnd, 1, 1, NULL);
break;
// NEW EVENT: Handle window size change
case WM_SIZE:
handle_resize ();
break;
Other things to note:
glColor3f clamps the floating-point value to the range [0.0,1.0], you were using values of 255 which is only appropriate if you use glColor3ub, which is essentially the same thing as glColor3f (1.0f, 1.0f, 1.0f).

Freedom of movement

I am a little stuck with making freedom of movement with the mouse in OpenGL, what I want is to have the controls of a 3D model making program. I am using Windows.
Here is my viewport structure, pretty standard:
struct viewport {
float x;
float y;
float z;
float angle[2];
};
struct viewport viewport;
My gluLookAt call:
glLoadIdentity();
gluLookAt(viewport.x, viewport.y, viewport.z, viewport.x + sin(viewport.angle[0] * M_PI / 180.0f), viewport.y + viewport.angle[1] * M_PI / 180.0f, viewport.z - cos(viewport.angle[0] * M_PI / 180.0f), 0.0f, 1.0f, 0.0f);
My WM_MOVE, to rotate the scene when the user holds down the right mouse button:
case WM_MOUSEMOVE:
if(GetAsyncKeyState(VK_RBUTTON)) {
viewport.angle[0] -= (GET_X_LPARAM(lParam) - lastMouseX) / 16.0f;
viewport.angle[1] += (GET_Y_LPARAM(lParam) - lastMouseY) / 16.0f;
}
lastMouseX = GET_X_LPARAM(lParam);
lastMouseY = GET_Y_LPARAM(lParam);
return 0;
My WM_MOUSEWHEEL, to zoom in and out the scene:
case WM_MOUSEWHEEL:
if(GET_WHEEL_DELTA_WPARAM(wParam) > 0) {
viewport.x += sin(GET_WHEEL_DELTA_WPARAM(wParam) / 120.0f);
viewport.y -= cos(GET_WHEEL_DELTA_WPARAM(wParam) / 120.0f);
}
else {
viewport.x += sin(GET_WHEEL_DELTA_WPARAM(wParam) / 120.0f);
viewport.y -= cos(GET_WHEEL_DELTA_WPARAM(wParam) / 120.0f);
}
return 0;
The zoom code really doesn't work, and I think my code to rotate on the Y axis is wrong, it looks weird.
I was able to get the zoom mostly working, the Y and X and Z aren't linked, but it works kind of. I post my full main.c this time so you can see more of the code:
#include "main.h"
#include <windowsx.h>
#include <math.h>
#define argc __argc
#define argv __argv
#define GRID_SIZE 50
short quit = 0;
short dead = 0;
HWND hWnd;
HDC hDC;
HGLRC hRC;
struct viewport {
float x;
float y[2];
float z;
float angle;
};
struct viewport viewport = { GRID_SIZE / 2.0f, { 1.0f, 1.0f }, GRID_SIZE / 2.0f, 180.0f };
float lastMouseX, lastMouseY = 0;
void die(void) {
if(!dead) {
quit = 1;
dead = 1;
deinitText();
deinitOpenGL();
DestroyWindow(hWnd);
}
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int iCmdShow) {
if(argc != 2) {
return 0;
}
WNDCLASS wc;
MSG msg;
wc.style = CS_OWNDC;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = "ObjectViewerC";
if(RegisterClass(&wc) == 0) {
die();
}
hWnd = CreateWindow("ObjectViewerC", argv[1], WS_CAPTION | WS_POPUPWINDOW | WS_VISIBLE, 0, 0, 512, 512, NULL, NULL, hInstance, NULL);
if(hWnd == NULL) {
die();
}
if(!initOpenGL()) {
die();
}
if(!initExtensions()) {
die();
}
if(!initTimer()) {
}
float frameStartTime = 0.0f;
float frameEndTime = 0.0f;
initText();
lookNice();
set3D();
while(!quit) {
if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
if(msg.message == WM_QUIT) {
quit = 1;
}
else {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
else {
frameStartTime = getTime();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
gluLookAt(viewport.x, viewport.y[0], viewport.z, viewport.x + sin(viewport.angle * M_PI / 180.0f), viewport.y[1], viewport.z - cos(viewport.angle * M_PI / 180.0f), 0.0f, 1.0f, 0.0f);
glColor3f(1, 1, 1);
glBegin(GL_LINES);
int i = 0;
for(i = 0; i <= GRID_SIZE; i++) {
glVertex3f(i, 0, 0);
glVertex3f(i, 0, GRID_SIZE);
glVertex3f(0, 0, i);
glVertex3f(GRID_SIZE, 0, i);
};
glEnd();
SwapBuffers(hDC);
do {
frameEndTime = getTime();
} while(frameEndTime < frameStartTime + framerate);
}
}
die();
return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
switch(message) {
case WM_CREATE:
return 0;
case WM_CLOSE:
PostQuitMessage(0);
return 0;
case WM_DESTROY:
die();
return 0;
case WM_KEYDOWN:
switch(wParam) {
case VK_ESCAPE:
PostQuitMessage(0);
return 0;
}
return 0;
case WM_LBUTTONDOWN:
return 0;
case WM_LBUTTONUP:
return 0;
case WM_MOUSEMOVE:
if(GetAsyncKeyState(VK_RBUTTON)) {
viewport.angle -= (GET_X_LPARAM(lParam) - lastMouseX) / 11.2f;
viewport.y[1] += ((GET_Y_LPARAM(lParam) - lastMouseY) / 580.0f);
}
lastMouseX = GET_X_LPARAM(lParam);
lastMouseY = GET_Y_LPARAM(lParam);
return 0;
case WM_MOUSEWHEEL:
if(GET_WHEEL_DELTA_WPARAM(wParam) > 0) {
viewport.x += sin(viewport.angle * M_PI / 180.0f) / 15.0f;
viewport.z -= cos(viewport.angle * M_PI / 180.0f) / 15.0f;
viewport.y[0] -= sin(viewport.y[0] - viewport.y[1]) / 15.0f;
viewport.y[1] -= sin(viewport.y[0] - viewport.y[1]) / 15.0f;
}
else {
viewport.x -= sin(viewport.angle * M_PI / 180.0f) / 15.0f;
viewport.z += cos(viewport.angle * M_PI / 180.0f) / 15.0f;
viewport.y[0] += sin(viewport.y[0] - viewport.y[1]) / 15.0f;
viewport.y[1] += sin(viewport.y[0] - viewport.y[1]) / 15.0f;
}
return 0;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
For the y Rotation: I think you should use a different vector than viewport.xyz for these arguments.
As you see, the parameters of gluLookAt are:
void gluLookAt(GLdouble eyeX, GLdouble eyeY, GLdouble eyeZ,
GLdouble centerX, GLdouble centerY, GLdouble centerZ,
GLdouble upX, GLdouble upY, GLdouble upZ);
so arguments 4 to 6 define the point where you look at. See this Picture:
So if you want to look around, you have to adjust the at vector, not the eye vector. To do so, try this:
take the vector between eye and at (at - eye)
turn that vector around the y axis (look up vector rotation on the web)
add the vector to eye => you have the new at vector
For the scrolling, I guess what you want is to move the eye vector in the direction the camera is looking. So something like eye += normalized(at - eye) * factor.

glutKeyboardFunc error [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
I have an opengl c++ code for reading .ply file. I want to read keyboard arrow keys(up,down,right,left) for move a point on the screen. I used glutKeyboardFunc function but i have an error:
Unhandled exception at 0x1000bb1e in opengl3.exe: 0xC0000005: Access violation reading location 0x00000070.
On this line:
glutKeyboardFunc(keyPressed);
#include <windows.h>
#include <gl/gl.h>
#include <gl/glu.h>
#include <gl/glut.h>
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <cmath>
#include <string>
#include <conio.h>
HWND hWnd;
HDC hDC;
HGLRC hRC;
// Set up pixel format for graphics initialization
void SetupPixelFormat()
{
PIXELFORMATDESCRIPTOR pfd, *ppfd;
int pixelformat;
ppfd = &pfd;
ppfd->nSize = sizeof(PIXELFORMATDESCRIPTOR);
ppfd->nVersion = 1;
ppfd->dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
ppfd->dwLayerMask = PFD_MAIN_PLANE;
ppfd->iPixelType = PFD_TYPE_COLORINDEX;
ppfd->cColorBits = 16;
ppfd->cDepthBits = 16;
ppfd->cAccumBits = 0;
ppfd->cStencilBits = 0;
pixelformat = ChoosePixelFormat(hDC, ppfd);
SetPixelFormat(hDC, pixelformat, ppfd);
}
void InitGraphics()
{
hDC = GetDC(hWnd);
SetupPixelFormat();
hRC = wglCreateContext(hDC);
wglMakeCurrent(hDC, hRC);
glClearColor(0, 0, 0, 0.5);
glClearDepth(1.0);
glEnable(GL_DEPTH_TEST);
}
// Resize graphics to fit window
void ResizeGraphics()
{
// Get new window size
RECT rect;
int width, height;
GLfloat aspect;
GetClientRect(hWnd, &rect);
width = rect.right;
height = rect.bottom;
aspect = (GLfloat)width / height;
// Adjust graphics to window size
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0, aspect, 1.0, 100.0);
glMatrixMode(GL_MODELVIEW);
}
// Draw frame
void DrawGraphics()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Set location in front of camera
glLoadIdentity();
glTranslated(0, 0, -10);
// Draw a square
glBegin(GL_QUADS);
glColor3d(100, 200, 30);
/*
glVertex3d(-2, 2, 0);
glVertex3d(2, 2, 0);
glVertex3d(2, -2, 0);
glVertex3d(-2, -2, 0);
*/
//FILE * file = fopen("D:\\dart.ply","r");
FILE * file = fopen("mosalas.ply","r");
if (file!=NULL)
{
fseek(file,0,SEEK_END);
long fileSize = ftell(file);
float* Vertex_Buffer;
try
{
Vertex_Buffer = (float*) malloc (ftell(file));
}
catch (char* )
{
//return -1;
}
//if (Vertex_Buffer == NULL) return -1;
fseek(file,0,SEEK_SET);
//Faces_Triangles = (float*) malloc(fileSize*sizeof(float));
//Normals = (float*) malloc(fileSize*sizeof(float));
if (file)
{
int i = 0;
int temp = 0;
int quads_index = 0;
int triangle_index = 0;
int normal_index = 0;
char buffer[1000];
fgets(buffer,300,file); // ply
// READ HEADER
// -----------------
int TotalConnectedPoints;
// Find number of vertexes
while ( strncmp( "element vertex", buffer,strlen("element vertex")) != 0 )
{
fgets(buffer,300,file); // format
}
strcpy(buffer, buffer+strlen("element vertex"));
sscanf(buffer,"%i", &TotalConnectedPoints);
int TotalFaces;
// Find number of face
fseek(file,0,SEEK_SET);
while ( strncmp( "element face", buffer,strlen("element face")) != 0 )
{
fgets(buffer,300,file); // format
}
strcpy(buffer, buffer+strlen("element face"));
sscanf(buffer,"%i", &TotalFaces);
// go to end_header
while ( strncmp( "end_header", buffer,strlen("end_header")) != 0 )
{
fgets(buffer,300,file); // format
}
i =0;
float* ver0,ver1,ver2,ver3;
//char* key[100];
for (int iterator = 0; iterator < TotalConnectedPoints; iterator++)
{
fgets(buffer,300,file);
//sscanf(buffer,"%f %f %f", &Vertex_Buffer[i], &Vertex_Buffer[i+1], &Vertex_Buffer[i+2]);
sscanf(buffer,"%f %f %f", &ver1, &ver2, &ver3);
glNormal3f(ver1, ver2, ver3);
glVertex3d(ver1, ver2, ver3);
//glVertex3f(ver1, ver2, ver3);
i += 3;
}
}
}
glPushMatrix();
glBegin;
glTranslatef(-10,5,0);
glColor3f(1,1,1);
glRotatef(90,0,1,0);
glutSolidCone(0.25, 15, 20, 20);
glEnd();
glPopMatrix();
//glutMouseFunc(0,0,0);
/*
glVertex3d(1.000000, 1.000000, 6);
glVertex3d(3.000000, 0.000000, 4);
glVertex3d(0.000000, 0.000000, 4);
glVertex3d(0.000000, 3.000000, 4);
glVertex3d(1.500000, 0.500000, 0);*/
glEnd();
// Show the new scene
SwapBuffers(hDC);/**/
}
void keyPressed (unsigned char key, int x, int y) {
}
// Handle window events and messages
LONG WINAPI MainWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_SIZE:
ResizeGraphics();
break;
case WM_CLOSE:
DestroyWindow(hWnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
// Default event handler
default:
return DefWindowProc (hWnd, uMsg, wParam, lParam);
break;
}
return 1;
}
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
const LPCWSTR appname = TEXT("OpenGL Sample");
WNDCLASS wndclass;
MSG msg;
// Define the window class
wndclass.style = 0;
wndclass.lpfnWndProc = (WNDPROC)MainWndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance;
wndclass.hIcon = LoadIcon(hInstance, appname);
wndclass.hCursor = LoadCursor(NULL,IDC_ARROW);
wndclass.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wndclass.lpszMenuName = appname;
wndclass.lpszClassName = appname;
// Register the window class
if (!RegisterClass(&wndclass)) return FALSE;
// Create the window
hWnd = CreateWindow(
appname,
appname,
WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
CW_USEDEFAULT,
CW_USEDEFAULT,
800,
600,
NULL,
NULL,
hInstance,
NULL);
if (!hWnd) return FALSE;
// Initialize OpenGL
InitGraphics();
// Display the window
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
DrawGraphics();
// Event loop
int key;
int asgh = 0;
POINT pt;
/**/while (1)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE) == TRUE)
{
if (!GetMessage(&msg, NULL, 0, 0))
return TRUE;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
glutKeyboardFunc(keyPressed);
DrawGraphics();
}
wglDeleteContext(hRC);
ReleaseDC(hWnd, hDC);
}
The program you posted lacks a call to glutInit().
Furthermore you're doing all of the platform-specific window management and context creation that GLUT is supposed abstract away.
Bottom line: If you want to use GLUT, use GLUT. If you want to use Win32, use Win32. Don't try to mix-and-match.