Em destaque

C++ OpenGL MFC Projects.

The control flow-chart of the standard OpenGL application with the steps numerated as per items of the sections accordingly.

4.1. Create GL Window

The procedure CreateGLwindow is common to all the lessons and located in GLRoutine.cpp file in the common GlobUse directory.

The procedure CreateGLWindow to be called by virtual procedure OnCreate:

int CChildView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CWnd::OnCreate(lpCreateStruct) == -1)
		return -1;
	CreateGLWindow(this, 32);             //borrowed from NeHe site; 
                                          //located in GlobUse\GLRoutine.cpp
	_tgetcwd(m_rootDir, _MAX_PATH);       //root directory identification
	CreateListLessons();                  //list box of DlgLesson dialog content; 
                                          //located in GlobUse\GLRoutine.cpp
	m_bPlay = TRUE;                       //flag of autoplay
  	SetTimer(ID_TIMER_PLAY, 15, NULL);    //timer of the scene to change in 15 milliseconds
	return 0;
}

The CreateGLWindow procedure almost completely has been borrowed from the original NeHe lessons and as much as possible, I’ve tried not to change the authoring codes.

 

4.2. Init Application

Initialization procedure to be called by the procedure CChildView::InitChildView:

void CChildView::InitChildView(void)
{
	m_bInitGL = FALSE;          //initialization flag
	m_pView = this;             //identification of the window 
                                //to be called in global procedures
	InitMRU();                  //initialization of the resent lessons list
	InitGLn(m_strNum);          //initialization of the OpenGL window
                                //(located in GlobUse\GlobDrawGL.cpp)
	//Main Frame Text:
	GetMainFrameGlob->SetWindowText( CString(AfxGetApp()->m_pszAppName) + 
                        _T(" : ") + (m_strLesson = GetLessonName(m_strNum)));
}

InitGLn initialization of the OpenGL window procedure (located in GlobUse\GlobDrawGL.cpp) refers to the initialization procedure InitGL_XX(GLvoid) of the current lesson located in the NeHeDrawInit\XX_*DrawInit.cpp. These initialization procedures have been borrowed from the NeHe site. I’ve tried not to change these codes as far as possible.

The only big difference is that I’ve taken the liberty to exclude Glaux.lib library from all the lessons used for the texture initialization. Nevertheless, I hope the authors of the original codes will not complain. Sure, they could not expect from MS VS developers that Glaux.lib library to be excluded from 10th version onwards. And if it is still possible to include Glaux.lib in the MS VS 10th version, in the 11th version it is not working.

The procedures for the texture initialization instead of Glaux.lib are located in the Globuse\GlobTexture.cpp. The instructions for the texture initialization may be obtained from my former CodeProject articles “Texture Mapping in OpenGL using Class CImage” and “Masking Texture in OpenGL using Class CImage“.

4.3. Resize GL Window

Procedure ResizeGLScene common to all the lessons to be called by virtual procedure OnSize:

void CChildView::OnSize(UINT nType, int cx, int cy)
{
	CWnd::OnSize(nType, cx, cy);
	ReSizeGLScene(cx, cy);        //base borrowed from NeHe site; 
                                  //located in GlobUse\GLRoutine.cpp
	SetTitlePos();                //title of the lesson  in Main Frame and in Full Screen mode
}

In distinct from the NeHe original base some global variables inserted:

GLfloat  fNearPlane = 0.1f, //Frustum Near Plane
         fFarPlane = 100.f, //Frustum Far Plane
         fViewAngle = 45.f, //Frustum View Angle
	     fAspect;           //Frustum Width/Height ratio
RECT m_viewRect;            //current View rect size in pixel

In some lessons (30,31,34,36,44,45,46,X4), the Frustum values set differ from default ones in the InitGL_XX procedure.

In lessons 21 and 24, the glOrtho presentation is used:

if(m_strNum == _T("21")||m_strNum == _T("24"))
	 glOrtho(0.0f,width,height,0.0f,-1.0f,1.0f);    // Create Ortho widthxheight View 
                                                    // (0,0 At Top Left)
else	                                            // Calculate The Aspect Ratio Of The Window
	gluPerspective(fViewAngle,(GLfloat)width/(GLfloat)height,fNearPlane,fFarPlane);

4.4. Draw GL Scene

OpenGL drawing procedure to be called by virtual procedure OnPaint:

void CChildView::OnPaint() 
{
	CPaintDC dc(this);               // device context for painting
	if (m_bInitGL)InitChildView();   //Initialization of the GL window if first call
	DrawGLSceneN();                  //Global drawing procedure
	// Do not call CWnd::OnPaint() for painting messages
}

DrawGLSceneN drawing of the OpenGL window procedure (located in GlobUse\GlobDrawGL.cpp) refers to the drawing procedure DrawGLScene_XX(GLvoid) of the current lesson located in the NeHeDrawInit\XX_*DrawInit.cpp. These drawing procedures have been borrowed from the NeHe site. I’ve tried not to change these codes as far as possible.

4.5. Messages Handling

Keyboard procedures handling to be called by virtual procedures OnKeyDown and OnKeyUp:

void CChildView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
	ProcessKeyboardN(nChar);                 //Global procedure of nChar handling
	CWnd::OnKeyDown(nChar, nRepCnt, 1nFlags);
}
void CChildView::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags)
{
	VkKeyUpN(nChar, nRepCnt, nFlags);        //Global procedure of nChar handling
	CWnd::OnKeyUp(nChar, nRepCnt, nFlags);
}

ProcessKeyboardN and VkKeyUpN keyboard commands handling procedures (located in GlobUse\GlobDrawGL.cpp) refer to the keyboard procedure ProcessKeyboard_XX(int idKey) and VkKeyUp_XX of the current lesson located in the NeHeDrawInit\XX_*DrawInit.cpp. These keyboards commands have been borrowed from the NeHe site. I’ve tried not to change these commands as far as possible. Just F1 command I’ve changed for Help performance and Ctrl+Enter command changed to FullScreen Mode handling.

Mouse procedures handling to be called by virtual procedures OnMouseMoveOnLButtonDown and OnRButtonDown:

 void CChildView::OnMouseMove(UINT nFlags, CPoint point)
{
	mouse_x = point.x; mouse_y = point.y;  //global mouse position
	MouseMoveN(nFlags, point);             //Global procedure of Mouse Move handling  
	CWnd::OnMouseMove(nFlags, point);
}
void CChildView::OnLButtonDown(UINT nFlags, CPoint point)
{
	LButtonDownN(nFlags, point);           //Global procedure of Mouse Left Button handling    
	CWnd::OnLButtonDown(nFlags, point);
}
void CChildView::OnRButtonDown(UINT nFlags, CPoint point)
{
	RButtonDownN(nFlags, point);           //Global procedure of Mouse Right Button handling
	CWnd::OnRButtonDown(nFlags, point);
}

MouseMoveN, LButtonDownN and RButtonDownN mouse commands handling procedures (located in GlobUse\GlobDrawGL.cpp) refer to the mouse handling procedures MouseMove_XX, LButtonDown_XX and RButtonDown_XX of the current lesson located in the NeHeDrawInit\XX_*DrawInit.cpp. These mouse commands have been borrowed from the NeHe site. I’ve tried not to change these commands as far as possible.

Timer procedure handling to be called by virtual procedure OnTimer:

void CChildView::OnTimer(UINT_PTR nIDEvent)
{
	switch (nIDEvent)
	{
	case ID_TIMER_PLAY:
		if (!m_bPlay) return; //if not play mode do nothing
		UpdateGLScene();      //Global procedure for one step image change
		DrawGLSceneN();       //Global drawing procedure
		break;
	}
	CWnd::OnTimer(nIDEvent);
}

UpdateGLScene procedure for one step image change (located in GlobUse\GlobDrawGL.cpp) refers to the procedure Update_XX of the current lesson located in the NeHeDrawInit\XX_*DrawInit.cpp. These update procedures have been borrowed from the NeHe site. I’ve tried not to change these procedures as far as possible.

4.6. Kill GL Window

If the new lesson in the Lesson Dialog is selected to start at the same window, the memory must be released and the OpenGL window to be closed. Also, before the application exit also the memory must be released and the OpenGL window to be closed:

    void CChildView::OnAppExit()
{
	DeinitializeN();			//Clear memory
	KillGLWindow(this);			//Close OpenGL window
}

DeinitializeN procedure for clear memory (located in GlobUse\GlobDrawGL.cpp) refers to the procedure Deinitialize_XX of the current lesson located in the NeHeDrawInit\XX_*DrawInit.cpp. These clear memory procedures have been borrowed from the NeHe site. I’ve tried not to change this procedure as far as possible.

The procedure KillGLwindow is common to all the lessons and located in GLRoutine.cpp file in the common GlobUse directory. The KillGLWindow procedure almost completely has been borrowed from the original NeHe lessons and as much as possible, I’ve tried not to change the authoring codes.

5. Joystick Implementation

Joystick handling is available in lessons 09, 10, 32, 40, X4, X5 in projects MFC_GL and MFC_GL1. In the project MFC_GL0, the Joystick functions are not available. Next two steps require to make MFC_GL0 working with the Joystick as in MFC_GL1:

  • Select menu Project->Add Existing Item… and insert GlobUse\JoystickMFCDlg.cpp and GlobUse\JoystickHelpDlg.cpp into Solution Explorer window
  • Open MFC_GL0\MFC_GL0\SetName0.cpp and put in comments (or just remove) the empty procedure void InitJoystickDlg(void){}.

And that’s all (point 2.1 of this article conditions understood). Now the project should be working with the Joystick.

Joystick procedures handling to be called by virtual procedure CJoystickMFCDlg::OnRawInput.

HandleJoystickN procedure for Joystick Controls handling (located in GlobUse\GlobDrawGL.cpp) refers to the procedure HandleJoystick_XX of the current lesson located in the NeHeDrawInit\XX_*DrawInit.cpp. These procedures have been developed by the author for demo purposes. Lesson 40 Joystick handling, e.g.:

    void HandleJoystick_40(int nx, int ny, int nz, int nzr, int nh, 
                           BOOL bButtonStates[], BOOL bButtonPrev[])
{
	ropeConnectionVel = Vector3D(-0.003f*nzr, 0.003f*nx, 0.003f*ny);
}

You may change these existing HandleJoystick_XX codes or create yourself as you like.

Em destaque

Writing a Unix Shell – Part I

What is a shell?

A lot has been written about this, so I will not go into too much detail about the definition. However, in one line –
A shell is an interface that allows you to interact with the kernel of an operating system.

How does a shell work?

A shell parses commands entered by the user and executes this. To be able to do this, the workflow of the shell will look like this:

  1. Startup the shell
  2. Wait for user input
  3. Parse user input
  4. Execute the command and return the result
  5. Go back to 2.

There is one important piece to all of this though: processes. The shell is the parent process. This is the main thread of our program which is waiting for user input. However, we cannot execute the command in the main thread itself, because of the following reasons:

  1. An erroneous command will cause the entire shell to stop working. We want to avoid this.
  2. Independent commands should have their own process blocks. This is known as isolation and falls under fault tolerance.

Fork

To be able to avoid this, we use the system call fork. I thought I understood fork until I wrote about four lines of code using it.

fork creates a copy of the current process. The copy is known as the child and each process in a system has a unique process id (pid) associated to it. Let’s take a look at the following piece of code:

fork.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int
main() {
    pid_t child_pid = fork();
        
    // The child process
    if (child_pid == 0) {
        printf("### Child ###\nCurrent PID: %d and Child PID: %d\n",
               getpid(), child_pid);
    } else {
        printf("### Parent ###\nCurrent PID: %d and Child PID: %d\n",
               getpid(), child_pid);
    }
 
    return 0;
}

The fork system call returns twice, once for each process. This sounds counter intuitive at first. But let’s take a look at what goes underneath the hood.

  1. By invoking fork we are creating a new branch in our program. This is not the same as a traditional if-else branch. fork creates a copy of the current process and creates a new one out of it. The resulting system call returns the process id of the child process.
  2. Immediately after the fork call has succeeded, both the child and the parent process (the main thread of our code) are running simultaneously.

To give you a better idea of the program flow, take a look at this diagram:

The fork() creates a new child process, but at the same time, execution of the parent process is not halted. The child process begins and finishes its execution independent of the parent and vice versa.

A quick note before we proceed further, the getpid system call returns the current process id.

If you compile and execute the code, you’d get an output similar to the following:

### Parent ###
Current PID: 85247 and Child PID: 85248
### Child ###
Current PID: 85248 and Child PID: 0

In the block under ### Parent ###, the current process ID is 85247 and that of the child is 85248. Note that the pid of the child is greater than that of the parent, implying that the child was created after the parent. (Update: As someone correctly pointed out on Hacker News this isn’t guaranteed, although the more likely scenario. Reason being that, the OS could recycle older unused process ids.

In the block under ### Child ###, the current process ID is 85248, which is the same as the pid of the child in the previous block. However, the child pid here is 0.

Actual numbers would vary on each execution.

You’d be forgiven for thinking about how can child_pid assume two different values in the same execution flow, when we have clearly assigned a value to child_pid once on line 9. However, recall that invoking fork creates a new process, which is identical to the current one. As a result, in the parent process, child_pid is the actual value of the child process that just got created, and the child process itself has no child of its own, as a result of which the value of child_pid is 0.

Thus, the if-else block we have defined from lines 12 to 16 is required to control what code to execute in the child, vs the parent. When child_pid is 0, the code block will be executed under the child process, while the else block will be executed under the parent process instead. The order in which the blocks will be executed cannot be determined, and depends on the operating system’s scheduler.

Deep Learning with TensorFlow in Python

sandipanweb

The following problems appeared in the first few assignments in the Udacity course Deep Learning (by Google). The descriptions of the problems are taken from the assignments.

Classifying the letters with notMNIST dataset

Let’s first learn about simple data curation practices, and familiarize ourselves with some of the data that are going to be used for deep learning using tensorflow. The notMNIST dataset to be used with python experiments. This dataset is designed to look like the classic MNIST dataset, while looking a little more like real data: it’s a harder task, and the data is a lot less ‘clean’ than MNIST.

Preprocessing

First the dataset needs to be downloaded and extracted to a local machine. The data consists of characters rendered in a variety of fonts on a 28×28 image. The labels are limited to ‘A’ through ‘J’ (10 classes). The training set has about 500k and…

Ver o post original 1.198 mais palavras

Deep Learning & Art: Neural Style Transfer – An Implementation with Tensorflow (using Transfer Learning with a Pre-trained VGG-19 Network) in Python

sandipanweb

This problem appeared as an assignment in the online coursera course Convolution Neural Networks by Prof Andrew Ng, (deeplearing.ai).  The description of the problem is taken straightway from the assignment.

Neural Style Transfer algorithm was created by Gatys et al. (2015) , the paper can be found here .

In this assignment, we shall:

  • Implement the neural style transfer algorithm
  • Generate novel artistic images using our algorithm

Most of the algorithms we’ve studied optimize a cost function to get a set of parameter values. In Neural Style Transfer, we  shall optimize a cost function to get pixel values!

Problem Statement

Neural Style Transfer (NST) is one of the most fun techniques in deep learning. As seen below, it merges two images, namely,

  1. a “content” image (C) and
  2. a “style” image (S),

to create a “generated” image (

Ver o post original 1.701 mais palavras

Some Image Processing and Computational Photography: Convolution, Filtering and Edge Detection with Python

sandipanweb

The following problems appeared as an assignment in the coursera course Computational Photography (by Georgia Institute of Technology). The following descriptions of the problems are taken directly from the assignment’s descriptions.

Introduction

In this article, we shall be playing around with images, filters, and convolution. We will begin by building a function that performs convolution. We will then experiment with constructing and applying a variety of filters. Finally, we will see one example of how these ideas can be used to create interesting effects in our photos, by finding and coloring edges in our images.

Filtering

In this section, let’s apply a few filters to some images. Filtering basically means replacing each pixel of an image by the linear combination of its neighbors. We need to understand the following concepts in this context:

  1. Kernel (mask) for a filter: defines which neighbors to be considered and what weights…

Ver o post original 1.677 mais palavras

%d blogueiros gostam disto: