Dot Product & Cross Product

July 28, 2011 Leave a comment

In computer graphics, everything base on a mathematical system mostly linear algebra. You have to solve your problem in a mathematical way in order to achieve it in every platform and every situation. There are some classical equations to help us. I’m going to indicate two of them. Dot product & Cross Product.

Dot Product


Shortly, this equation gives us cosine value of angle between two given vectors. Let’s investigate;

We will use this equation frequently in game engine. As you guess, easy to implement it in C++. We will design a Vector class and will override an operator especially for this process.

Cross Product


This equation is a little more complex than previous one, but don’t be afraid, I will explain in details. In a few words, if you want to find out a vector that is perpendicular to both of two given vectors, you may use this equation. Let’s see;

I think demostration is enough to understand what is about and how to calculate. You will get used to it as much as you use.

See you in a next article…

Advertisements
Categories: Game Engine, General

3D Game Engine Design – 2

July 24, 2011 Leave a comment

Hi again, before move on talking about Render Engine, it might be very good to see the big picture. I have design an UML diagram of the sistem. Let’s take a look;

As you see, each individual task has been separated and power of object oriented programming techniques in order to do abstraction by interfaces has been used, these are magic tricks of developing a game engine.

In the previous article, I have mentioned that we are using Manager classes to do in easy way. I have also indicated Singleton design pattern is the best choice in order to ensure that there only one instance of a manager class can be existing.

First step may be SceneManager class:

/*
	Dosya: SceneManager.h
	İşlev: Sahne Yönetimi Sınıfı için başlık dosyası
	Yazar: rbellek
*/
#pragma once

#include "Definitions.h"
#include "Scene.h"
#include <vector>

namespace IREM{
    #define pCSceneManager CSceneManager*

	class CSceneManager
	{
		IMPLEMENT_IT_FUNC_CALL(CSceneImpl, CScene, renderSceneFrame);
    private:
        CSceneManager(void);
        static pCSceneManager	alone;
		std::vector<pCScene>	m_scenes;
		pCScene					m_current;
    public:
         static					pCSceneManager getInstance();
		pCScene					getScene(const std::string& sceneName);
		   void					removeScene(unsigned int index);
		pCScene					createScene(const std::string& sceneName);
		pCScene					createScene();
		   void					setCurrentScene(pCScene const scene);
		pCScene					getCurrentScene();
		   void					renderCurrentScene();
		   void					clearCurrentScene();
		
	};


}
/*
	Dosya: SceneManager.cpp
	İşlev: Sahne Yönetimi Sınıfını gerçekleyen kaynak dosya
	Yazar: rbellek
*/
#include "SceneManager.h"

namespace IREM{

    pCSceneManager CSceneManager::alone = NULL;
	

	CSceneManager::CSceneManager(void)
	{
        m_current = NULL;
	}


    pCSceneManager CSceneManager::getInstance(){
        if (alone == NULL)
            alone = new CSceneManager();
        return alone;
    }

	pCScene CSceneManager::getScene(const std::string& sceneName){
		for(std::vector<pCScene>::iterator it = m_scenes.begin();
			it!=m_scenes.end();
			it++)
			if (sceneName==(*it)->getName())
				return *it;
		return NULL;
	}

	void CSceneManager::removeScene(unsigned int index){
		 m_scenes.erase(m_scenes.begin()+index);
	}

	pCScene CSceneManager::createScene(const std::string& sceneName){
		pCScene retScene = createScene();
		retScene->setName(sceneName);
		return retScene;
	}

	pCScene CSceneManager::createScene(){
		pCScene retScene = (pCScene)new CSceneImpl;
		if (m_scenes.empty())
			m_current = retScene;
		m_scenes.push_back(retScene);
		return retScene;
	}

	void CSceneManager::setCurrentScene(pCScene const scene){
		m_current = scene;
	}

	pCScene CSceneManager::getCurrentScene(){
		return m_current;
	}

	void CSceneManager::renderCurrentScene(){
		((CSceneImpl*)m_current)->__funcCall();
	}
	void CSceneManager::clearCurrentScene(){
		((CSceneImpl*)m_current)->clearSceneFrame();
	}
}

I demostrate these simple code pieces to flash something in your minds about how to do. Please do not focus on code, because of complexity. They supply nothing for your project, and also they cannot help to solve your problems. Just take a look and try to shape information that is divided.

See you in a next sweety article 🙂

Thanks for reading…

Categories: C/C++, DirectX, Game Engine, OpenGL

GLSL Vertex Shader & Fragment Shader – Test 1

May 8, 2011 1 comment

Note: This work is just for test purpose. I will explain the following codes in a next article.

/*
GLSL Vertex Shader & Fragment Shader Test

This is my first GLSL work. There are some problems about texture as you see.
I will fix them as soon as possible.


https://rbellek.wordpress.com
Ramazan Bellek
May 2011

*/
#include <iostream>
#include <Windows.h>
#include <gl\glew.h>
#include <GL\glut.h>

#pragma comment(lib, "opengl32.lib")
#pragma comment(lib, "glut32.lib")
#pragma comment(lib, "glu32.lib")
#pragma comment(lib, "glew32.lib")

using namespace std;
RGBTRIPLE *image = NULL;

void loadBMP(LPCWSTR fileName, int& width, int& height)
{
	HANDLE hfile;
	DWORD written;
	BITMAPFILEHEADER bfh;
	BITMAPINFOHEADER bih;
	int imagesize;
	hfile = CreateFile(fileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, NULL, NULL);
	ReadFile(hfile, &bfh, sizeof(bfh), &written, NULL); 
	ReadFile(hfile, &bih, sizeof(bih), &written, NULL);
	width = bih.biWidth;
	height = bih.biHeight;
	imagesize = bih.biWidth*bih.biHeight;
	image = new RGBTRIPLE[imagesize];
	ReadFile(hfile, image, imagesize*sizeof(RGBTRIPLE), &written, NULL); 
	CloseHandle(hfile);
}


GLuint vertexShader, fragmentShader, shaderProgram, timeVar; 
long timeElapsed = GetTickCount();
GLuint texture;


char vertexSource[] = "uniform float timeElapsed;"\
					  "void main(){"\
					  "gl_TexCoord[0] = gl_MultiTexCoord0;"\
					  "vec4 vertex = vec4(gl_Vertex);"\
					  "vertex.z = sin((timeElapsed*3.0 + vertex.x)*3.1415)*0.25;"\
					  "gl_Position = gl_ModelViewProjectionMatrix*vertex;"\
					  "}";

char fragmentSource[] = "uniform sampler2D tex; void main(){"\
						"vec4 color = texture2D(tex,gl_TexCoord[0].st);"\
						"color.r = color.r + 10;"\
						"gl_FragColor = color;"\
					    "}";

void setup(){
	vertexShader = glCreateShader(GL_VERTEX_SHADER);
	fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);

	const char *v = vertexSource;
	const char *f = fragmentSource;
	glShaderSource(vertexShader, 1, &v, NULL);
	glShaderSource(fragmentShader, 1, &f, NULL);

	glCompileShader(vertexShader);
	glCompileShader(fragmentShader);

	shaderProgram = glCreateProgram();
	glAttachShader(shaderProgram, fragmentShader);
	glAttachShader(shaderProgram, vertexShader);

	glLinkProgram(shaderProgram);
	glUseProgram(shaderProgram);
	timeVar = glGetUniformLocationARB(shaderProgram, "timeElapsed");
}

void render(){
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glLoadIdentity();
	gluLookAt(2.0, 0.0, 4.0,
			  0.0, 0.0, 0.0,
			  0.0, 1.0, 0.0);


	glUniform1fARB(timeVar, (float)(GetTickCount() - timeElapsed)/4000.0f);
	
	float min = 0.1f, max = 1.5f, step = 0.01f;
	glBegin(GL_QUADS);
	for(float f=min; f<max; f+=step){
		glTexCoord2f(f/max, 0);
		glVertex3f(-2.0f*f, -1.0f, 0.0f);
		glNormal3f(0.0f, 0.0f, 1.0f);

		glTexCoord2f(step+f/max, 0);
		glVertex3f(-1.0f*f, -1.0f, 0.0f);
		glNormal3f(0.0f, 0.0f, 1.0f);

		glTexCoord2f(step+f/max, 1);
		glVertex3f(-1.0f*f, 1.0f, 0.0f);
		glNormal3f(0.0f, 0.0f, 1.0f);

		glTexCoord2f(f/max, 1);
		glVertex3f(-2.0f*f, 1.0f, 0.0f);
		glNormal3f(0.0f, 0.0f, 1.0f);
	}
	glEnd();

	glutSwapBuffers();
}

void changeRes(int w, int h){
	if (h==0)
		h=1;

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();

	glViewport(0, 0, w, h);
	gluPerspective(45, (float)w/h, 1, 100);
	glMatrixMode(GL_MODELVIEW);
}

void textureInit(){
	glGenTextures(1, &texture);
	glBindTexture(GL_TEXTURE_2D, texture);
	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
	int w, h;
	loadBMP(L"c:\\bayrak.bmp", w, h);
	gluBuild2DMipmaps(GL_TEXTURE_2D, 3, w, h, GL_BGR, GL_UNSIGNED_BYTE, image);
	delete image;
	glEnable( GL_TEXTURE_2D );
	glBindTexture( GL_TEXTURE_2D, texture );
	
}

int main(int argc, char **argv){
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
	glutInitWindowPosition(0, 0);
	glutInitWindowSize(800, 600);
	glutCreateWindow("GLSL Turkish Flag");

	glutDisplayFunc(render);
	glutIdleFunc(render);
	glutReshapeFunc(changeRes);

	glEnable(GL_DEPTH_TEST);
	glClearColor(1.0,1.0,1.0,1.0);

	glewInit();
	if (glewIsSupported("GL_VERSION_2_0"))
		printf("Ready for OpenGL 2.0\n");
	else {
		printf("OpenGL 2.0 not supported\n");
		exit(1);
	}
	setup();

	textureInit();

	glutMainLoop();
	return EXIT_SUCCESS;
}


3D Game Engine Design – 1

May 4, 2011 Leave a comment

Hi everyone, I decided to start posting how to write a 3D game engine from scratch. Actually, this is my graduation project in university. We are four and I participate in as architecture of the engine. I also code the system. Before I start, I have to mention that I am not going to represent you a professional one, and also it doesn’t have everything inside. You might feel disappointed if you expect like that.

In a complete 3d game engine includes a lot of sub system. These discrete systems work together without depends eachother. Another way to say abstraction. Let’s define these sub systems.

Game Engine
– Render Engine
– Physics Engine
– AI Engine
– Sound Engine
– Network Engine
– Inputs
– Windowing
– Utilities

I’ll start with Render Engine and talk about all of them, respectively.

| Render Engine |
This module is responsible for everything that you see on the screen. A graphic API like OpenGL or Direct3D must be used in render engine. The main idea in my design is seperating jobs. In order to build a powerfull, flexible and stable you have to take control of every object and the memory. So I group associated classes and create a manager class in order to manage them. Let’s take a look at my design;

  • Scene Manager
  • Model Manager
  • GUI Manager
  • Light Manager
  • Camera Manager
  • Resource Manager
  • Animation Manager

“What are you talkin’ about?”

🙂 Do not panic! I will explain step-by-step. We will use C++ as programming language, Direct3D API and will use as possible as OOP technique. Just before I introduce Scene Manager, we have to know some programming stuff like design patterns. I use Singleton design pattern especially in each Manager class. I mean,

// SceneManager.h

...
class CSceneManager{
    private:
        CSceneManager(void); // must be private!
        static pCSceneManager	alone; // this is too.
    public:
         static pCSceneManager getInstance(); // exit point to the outside...
...
};

// SceneManager.cpp
#include "SceneManager.h"

    pCSceneManager CSceneManager::alone = NULL; // it must init. to NULL
	
    CSceneManager::CSceneManager(void){
         ...
    // implement constructor method...
    }

    pCSceneManager CSceneManager::getInstance(){
        if (alone == NULL)
            alone = new CSceneManager();
        return alone;
    }

...

You may look up wikipedia (Singleton@Wiki) or watch my video on Youtube (My Singleton Video in Turkish) for further information.

To be continue…

Math of the Art – Daisy

March 10, 2011 Leave a comment

A gentle touch on beauty of nature…
Using math of the Art…

P.S.: This sourcecode requires Python Imaging Library (PIL) (get it)

'''
Ramazan Bellek
https://rbellek.wordpress.com
March 2011
'''
import Image
from random import randint
from math import sin, cos

im = Image.new('RGBA', (1120, 754))

#print im.format, im.size, im.mode

pixels = im.load()

w = im.size[0] # width
h = im.size[1] # height

mx = w / 2 # center x
my = h / 2 # center y

#pi / 180 = 0.0174532925
pi_div_180 = 0.0174532925

''' draws a square as a point '''
def point(x, y, r, g, b, a):
    for i in range(-1,1):
        for j in range(-1,1):
            pixels[(x+i)%w, (y+j)%h] = (r, g, b, a)


for i in range(w):
    for j in range(h):
         pixels[i, j] = (255, 255, 255, 0) # background color and transparency

# (360-137.5) / 137.5 = 1.618~
for i in range(360):
    posx = cos(137.5*i*pi_div_180)*i/1.5
    posy = sin(137.5*i*pi_div_180)*i/1.5
    # draws a daisy...
    point(mx+posx, my+posy, (i*3)%255, (i+5)%255, i%255, 255)

for i in range(360):
    posx = cos(i*pi_div_180)*i/1.5
    posy = sin(i*pi_div_180)*i/1.5
    # fibonacci curve...
    point(mx+posx, my+posy, 0, 255, 0, 120)
            
im.save('art_of_math.png')


Categories: General Tags:

STL Vector Class

March 6, 2011 Leave a comment

Dynamic extendable arrays are programmers’ general necessity. Some generic structures like ArrayList in C# or Java are used in this purpose, in C++ we can use vector class of STL.

#include <iostream>
#include <vector>

using namespace std;



int main(int argc, char **argv){
	vector<int> iarray; // object declaration

	iarray.push_back(5); // insert an item to end
	iarray.push_back(1); // ...
	iarray.push_back(7);
	iarray.push_back(2);
	
	iarray.pop_back(); // remove an item from end

	for(vector<int>::iterator i = iarray.begin(); // define an iterator for vector<int>
		i != iarray.end(); // check whether it equals to size of vector or not
		i++) // iterate
		cout<<(*i)<<endl; // we get object from vector using this syntax

	system("pause");
	return 0;
}

There are some other functionality about this class.

Further information
C++ Reference

Categories: C/C++ Tags:

Dynamic Array Creation in C++

March 6, 2011 1 comment

Memory management is a big job to do when you need extreme performans like game programming. There are lots of way to achieve it, however I will demostrate you dynamic array creation part of it.  Before I start, I have to say that it is not just about using pointers, hardest side of dynamic creation is allocating memory. Every time we call memory allocation functions, it requests a memory block from OS, thus it costs very much. We have to do it at once, especially for two dimension arrays.

I have written a template class to implement logic above.

#include <iostream>

using namespace std;

template<typename T>
class ArrayGen{
public:
    T* generate(unsigned int lenght);
    T** generate(unsigned int row, unsigned int col);
};

template<typename T>T *ArrayGen<T>::generate(unsigned int lenght){
    T *ptr = new (nothrow)T[lenght];
    if (!ptr)
        return NULL;
    memset(ptr, 0, lenght);
    return ptr;
}

template<typename T>T **ArrayGen<T>::generate(unsigned int row, unsigned int col){
    T **ptr = new T*[row];
    ptr[0] = new T[row*col];
    memset(ptr[0], 0, row*col);
    for(int i = 1; i<row; i++)
        ptr[i] = &ptr[0][i*col];
    return ptr;

}

int main(int argc, char **argv){
	ArrayGen<float> *ag = new ArrayGen<float>;
	float **fMatrix = ag->generate(5, 3);
	unsigned int count = 0;
	for(int i=0; i<5; i++)
		for(int j=0; j<3; j++)
			fMatrix[i][j] = count++;

	// proof of concept
	for(int i=0; i<5; i++){
		for(int j=0; j<3; j++)
			cout<<fMatrix[i][j]<<" | ";
	cout<<endl;
	}

	system("pause");
	return 0;
}

This code is pretty simple but effective, although it supports max. two dimension. We implement two dimension array as an one dimension array and hide from programmer by abstraction methods.

Result Screen:

Categories: C/C++ Tags: