PDA

View Full Version : How to create a camera to a 3D (game)



Kalir44
09-06-2014, 01:26 AM
Hi,

im studying from the superbible 6th edition, and i want to make a camera to my 3D "game" but, I dont know how. The source is:

#include <sb6.h>
#include <vmath.h>
#include <time.h>
#include <stdio.h>
#include <object.h>
using namespace vmath;
// Remove this to draw only a single cube!
#define MANY_CUBES
/*float r;
float p;*/
class singlepoint_app : public sb6::application
{
void init()
{
static const char title[] = "OpenGL SuperBible - Spinny Cube";

sb6::application::init();

memcpy(info.title, title, sizeof(title));

}

virtual void startup()
{
static const char * vs_source[] =
{
"#version 410 core \n"
" \n"
"in vec4 position; \n"
" \n"
"out VS_OUT \n"
"{ \n"
" vec4 color; \n"
"} vs_out; \n"
" \n"
"uniform mat4 mv_matrix; \n"
"uniform mat4 proj_matrix; \n"
" \n"
"void main(void) \n"
"{ \n"
" gl_Position = proj_matrix * mv_matrix * position; \n"
" vs_out.color = position * 2.0 + vec4(0.5, 0.5, 0.5, 0.0); \n"
"} \n"
};

static const char * fs_source[] =
{
"#version 410 core \n"
" \n"
"out vec4 color; \n"
" \n"
"in VS_OUT \n"
"{ \n"
" vec4 color; \n"
"} fs_in; \n"
" \n"
"void main(void) \n"
"{ \n"
" color = fs_in.color; \n"
"} \n"
};

program = glCreateProgram();
GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fs, 1, fs_source, NULL);
glCompileShader(fs);

GLuint vs = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vs, 1, vs_source, NULL);
glCompileShader(vs);

glAttachShader(program, vs);
glAttachShader(program, fs);

glLinkProgram(program);

mv_location = glGetUniformLocation(program, "mv_matrix");
proj_location = glGetUniformLocation(program, "proj_matrix");


glGenVertexArrays(1, &vao);
glBindVertexArray(vao);


static const GLfloat data[] =
{
-0.25f, 0.25f, -0.25f,
-0.25f, -0.25f, -0.25f,
0.25f, -0.25f, -0.25f,

0.25f, -0.25f, -0.25f,
0.25f, 0.25f, -0.25f,
-0.25f, 0.25f, -0.25f,

0.25f, -0.25f, -0.25f,
0.25f, -0.25f, 0.25f,
0.25f, 0.25f, -0.25f,

0.25f, -0.25f, 0.25f,
0.25f, 0.25f, 0.25f,
0.25f, 0.25f, -0.25f,

0.25f, -0.25f, 0.25f,
-0.25f, -0.25f, 0.25f,
0.25f, 0.25f, 0.25f,

-0.25f, -0.25f, 0.25f,
-0.25f, 0.25f, 0.25f,
0.25f, 0.25f, 0.25f,

-0.25f, -0.25f, 0.25f,
-0.25f, -0.25f, -0.25f,
-0.25f, 0.25f, 0.25f,

-0.25f, -0.25f, -0.25f,
-0.25f, 0.25f, -0.25f,
-0.25f, 0.25f, 0.25f,

-0.25f, -0.25f, 0.25f,
0.25f, -0.25f, 0.25f,
0.25f, -0.25f, -0.25f,

0.25f, -0.25f, -0.25f,
-0.25f, -0.25f, -0.25f,
-0.25f, -0.25f, 0.25f,

-0.25f, 0.25f, -0.25f,
0.25f, 0.25f, -0.25f,
0.25f, 0.25f, 0.25f,

0.25f, 0.25f, 0.25f,
-0.25f, 0.25f, 0.25f,
-0.25f, 0.25f, -0.25f
};




glGenBuffers(1, &buffer[0]);
glBindBuffer(GL_ARRAY_BUFFER, buffer[0]);
glBufferData(GL_ARRAY_BUFFER,
sizeof(data),
data,
GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
glEnableVertexAttribArray(0);




glEnable(GL_CULL_FACE);
glFrontFace(GL_CW);

glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
}

virtual void render(double currentTime)
{
static const GLfloat green[] = { 0.0f, 0.25f, 0.0f, 1.0f };
static const GLfloat one = 1.0f;

glViewport(0, 0, info.windowWidth, info.windowHeight);
glClearBufferfv(GL_COLOR, 0, green);
glClearBufferfv(GL_DEPTH, 0, &one);

glUseProgram(program);


glUniformMatrix4fv(proj_location, 1, GL_FALSE, proj_matrix);

#ifdef MANY_CUBES

/*if (GetAsyncKeyState('W'))
{
Sleep (2);
p += 0.01f;
r += 0.01f;
}
else if (GetAsyncKeyState('S'))
{
Sleep (2);
p -= 0.01f;
r -= 0.01f;
}*/

int i;
for (i = 0; i < 24; i++)
{


float f = (float)i + (float)currentTime * 0.3f;


vmath::mat4 mv_matrix =
vmath::translate(0.0f, 0.0f, -6.0f) *
vmath::rotate( 10.0f, 0.0f, 0.0f /*p*/, 0.0f) *
vmath::rotate( 10.0f, 0.0f /*r*/, 0.0f, 0.0f) *
vmath::translate(sinf(0.1f * f) * 2.0f,
cosf(0.1f * f) * 2.0f,
sinf(0.1f * f) * cosf(1.5f * f) * 2.0f);


glUniformMatrix4fv(mv_location, 1, GL_FALSE, mv_matrix);

glDrawArrays(GL_TRIANGLES, 0, 36);

}
#else
float f = (float)currentTime * 0.3f;
vmath::mat4 mv_matrix = vmath::translate(0.0f, 0.0f, -4.0f) *
vmath::translate(sinf(2.1f * f) * 0.5f,
cosf(1.7f * f) * 0.5f,
sinf(1.3f * f) * cosf(1.5f * f) * 2.0f) *
vmath::rotate((float)currentTime * 45.0f, 0.0f, 1.0f, 0.0f) *
vmath::rotate((float)currentTime * 81.0f, 1.0f, 0.0f, 0.0f);
glUniformMatrix4fv(mv_location, 1, GL_FALSE, mv_matrix);
glDrawArrays(GL_TRIANGLES, 0, 36);
#endif
}

virtual void shutdown()
{
glDeleteVertexArrays(1, &vao);
glDeleteProgram(program);
glDeleteBuffers(1, &buffer[0]);
}

void onResize(int w, int h)
{
sb6::application::onResize(w, h);

aspect = (float)w / (float)h;

proj_matrix = vmath::perspective(60.0f, aspect, 0.1f, 2000.0f);


}



private:
GLuint program;
GLuint vao;
GLuint buffer[2];
GLint mv_location;
GLint proj_location;

float aspect;
vmath::mat4 proj_matrix;
};

DECLARE_MAIN(singlepoint_app)


So, iam using the SB6 header file, and vmath, thats the sb6 tool, too. So, Iam thinking about a camera like in a mmorpg games, like wow, savage, fps games.. I think, the my way is not good. I have there that my view matrix will view 24 cubes, thats the first problem, that all of them must be rendered alone. i want to make(if it is possible) something like, a world, and the objects will be there, and if i rotate my camera to a any direction, it will render that objects, which are in that direction. Can anybody help me, pls?:) It is my dream, to make a 3D world, and the first thing what i need, is a camera.

Yandersen
09-06-2014, 03:34 AM
Nice dream! :D
This is a basic trivial thing, so just google it. Example:
http://stackoverflow.com/questions/4294596/opengl-creating-my-own-camera/4295174#4295174
Here is the general topic that may be useful also:
http://www.tomdalling.com/blog/modern-opengl/04-cameras-vectors-and-input/
I would also suggest to use the OpenGL legacy matrix functions to manipulate matrices. If if you use higher versions of shaders you can still request matrices using glGet* and upload them into your shaders' uniforms.

Kalir44
09-06-2014, 11:57 AM
Thank you, but, Iam learning 4.3 version, that tutorial is for 3.2, so, some things i cant understand, is possible to find something like that, but written in 4.3 ver? btw. this is a camera tut, what about that, world? That i will have a 3D world, and i can rotate my camera to any direction, and it will render the objects in that direction?

btw2. It is just an idea, stupid idea, but, is it possible to make a lookat matrix, and then, i will rotate that matrix and it will work like a camera?:D

Yandersen
09-07-2014, 07:20 AM
Yeah, that is exactly how it works: initially you place your camera using the glLookAt function (or your emulation of it in case you maintain the modelview matrix by yourself), then you move and rotate it using the glTranslate and glRotate functions (or their emulations). So your camera typically represented with two matrices: movelview (MV) and projection (P). The projection matrix is somewhat constant most of the time as it's purpose is to guide a perspective projection onto the screen. You change it when your screen is resized, or when you want to change the perspective angle, or play with the clipping planes.
The MV matrix is what you need to modify all the time as this matrix is used to emulate the camera movement. In order to do that, you make a translation or rotation matrix in response to the change in user input related to camera movement (let's call this a transformation matrix for now, "T"). Then you multiply that matrix onto the current modelview matrix to modify it accordingly:
MV = T * MV;
Here multiplication is linear, so the columns of first matrix are multiplied by the rows of second one in order to calculate the element in the intersection of both. The result will look like you move and rotate the camera by itself, not the scene. I guess that is what you want, right?
Just ensure that you normalize the MV matrix after a few hundreds of such transformations to counteract the calculation error. That means that the basis directional vectors your MV matrix consist of slowly runaway from perpendicularity and unit length. So you take first column (3 elements), normalize it (make it a unit length), then you cross the first column vector with the second one to recalculate the third, normalize it's length. Then you cross the third column with the first one to get the second column (first 3 elements only you play with, because the 4th one is 0 for first 3 columns of MV matrix).

The OpenGL version has nothing to do with the camera.

Kalir44
09-07-2014, 12:31 PM
Ok, so lets say, i understand. And, what about that world? Yes, i know about a projection matrix, but the my question is, how to make a....... world :D That i will made my objects, i will set their position, for example, X 4444, Y 3333, and iam with my camera on X 5445, Y 3121, so i have to move to that position.

GClements
09-07-2014, 01:23 PM
I would also suggest to use the OpenGL legacy matrix functions to manipulate matrices.
I wouldn't. Either generate the matrices yourself (the actual matrices used for each function are given in the OpenGL 2.1 reference (http://www.opengl.org/sdk/docs/man2/)) or use GLM.

If if you use higher versions of shaders you can still request matrices using glGet* and upload them into your shaders' uniforms.
In the compatibility profile, you can access the standard matrices via the gl_* variables (e.g. gl_ModelViewMatrix for the model-view matrix). glGet* should be avoided, as it can take an inordinate amount of time compared to generating the matrix locally.

Kalir44
09-10-2014, 12:20 AM
ok thank you all. So now, i want to learn something about making 3D "world"
so i will can set objects 3D position, i think it has no something with projection matrix, there you can set if you want to draw "3d, or 2d" but is there something like world matrix? i know something about world space, but in sb6 i have very briefly introduced to that, they did not show me an examples or functions. So i want a help from you, a right direction with which i should go.

Ruggero Visitnin
09-11-2014, 01:13 PM
In 3D graphics there are three very important matrices:

1) Model Matrix: this is unique for every geometry in your "world" and "transforms" the local coordinates of the geometry into world coordinates, thanks to this matrix you can perform geometry rotation, scaling and translation.

the model matrix is like this:


{
ax, bx, cx, dx
ay, by, cy, dy
az, bz, cz, dz
aw, bw, cw, dw

// where dx, dy, and dz indicates the position in the world of your geometry
}


2) View Matrix: this is the matrix that defines the position and direction (and up vector but this is not the point) of the eye (or camera, call it how you want), note that the eye position and direction are ever the same, is the "world" that changes around the eye (or camera).
3) Projection Matrix: this matrix is used to obtain a 3D projection of the "world", there are two projections: the first is Ortographic projection and the second is Perspective projection, this matrix simply transform the vertices in order to simulate the perspective or ortographic projection.

there are two main multiplication that you can do with this three matrices:

1) MVP (ModelViewProjection) Matrix: Projection Matrix * View Matrix * Model Matrix
2) MV (ModelView) matrix: View * Model

since you are reading Opengl Superbible 6th i suppose that you are using modern Opengl (Opengl 3.x and above), to deal with matrices and vectors you can use GLM math library that come with all operations you'll need.

what i wrote is the very basic if you want to deepen here there are some links:
http://www.opengl-tutorial.org/beginners-tutorials/tutorial-3-matrices/
http://www.minho-kim.com/courses/13fa71033/data/redbook-05.pdf

Kalir44
09-17-2014, 09:38 AM
Thank you, now i can set position of my objects. But, i have another question(maybe i will have to create a new thread, but why?:):D So, i want to create my object, then publish a game. If i will use a png or another format of objects, someone will can change that object, or steal my own object. So, what i have to do that i will can publish my game, and no one will steal my objects?:D I saw that some games has formats what i have never seen, for example tmh.. So, i have to create my own format, and loader?:D And, what about that, where I should learn more about that.?

Ruggero Visitnin
09-23-2014, 11:25 AM
Well yes, usually an engine uses it's own format, not so much for safety reasons but of convenience: files always contain something you don't need, usually they need lot of memory, they require a lot of loading time and so on..
So Yes if you have the time, write your own format, but you don't have to care if people can "steal" your object, they probably can do the same even with your own format.
What you have to encrypt, what you don't want people can access to, are your databases, probably shaders (if you have a revolutionary algorithm), stuff that could allow people to cheat in your game:
for example gdr games usually need some databases to track items, this databases should be encrypted or everyone might can access to it and cheat... in those cases formats are very important as well as encryption.

Concerning the loader yes, i think you can go for it and you should write a file exporter, not only for your format but for every format your engine is going to support, the very useful feature of having your own format is that when you want to save a scene you made, is quite sure that you will need a format that track all model matrix of objects, colors, textures and so on..
I think you understood that Engines and Games are more complicated then what they seem
Regards and good work.