directx c++ first person camera - c++

im creating a 3d room which you can walk around with a first person camera
i have defined the position of the eyeX eyeY and eyeZ as shown below:
float eyeX = 0;
float eyeY = 100;
float eyeZ = 75;
here is my lookat code:
D3DXMatrixLookAtLH( &g_matView, &D3DXVECTOR3( eyeX, eyeY,eyeZ ),
&D3DXVECTOR3( LookatX, LookatY, LookatZ ),
&D3DXVECTOR3( 0.0f, 1.0f, 0.0f ) );
g_pd3dDevice->SetTransform( D3DTS_VIEW, &g_matView );
my code allows me to move the camera around but not like a first person camera and i am struggling to achieve this.
// forwards = UP ARROW
// Backwards = DOWN ARROW
// rotate left = LEFT ARROW
// rotate right = RIGHT ARROW
case WM_KEYDOWN:
{
// Handle any non-accelerated key commands
switch (wparam)
{
case VK_RIGHT:
if(eyeX >=-50)
{
--eyeX;
}
return (0);
case VK_LEFT:
if(eyeX <=50)
{
++eyeX;
}
return (0);
case VK_DOWN:
if(eyeZ >=-50)
{
--eyeZ;
}
return (0);
case VK_UP:
if(eyeZ <=50)
{
++eyeZ;
}
return (0);
case VK_SPACE:
if(eyeY >=-50)
{
--eyeY;
}
return (0);
case VK_SHIFT:
if(eyeY <=50)
{
++eyeY;
}
return (0);
}
break;
}
LookatX = eyeX + 5.0f;
LookatY = eyeY;
LookatZ = eyeZ;
case WM_DESTROY:
{
// kill the application
PostQuitMessage(0);
return(0);
}
default:
break;
} // end switch
could anyone suggest some changes which would allow me to move around my room like a first person camera?

Instead of using D3DXMatrixLookAtLH, you could keep a view matrix.
Set up
(Note that I am making up names of functions, you might have to create these yourself)
Start with something like
Matrix view = Matrices.createIdentity();
Then every frame, you set the view matrix(just like you are doing with the matrix you are getting from MatrixLookAtLH)
Moving around
Normally modifing a model matrix is like this.
model = Matrix.multiply(model,transformation).
However, you manipulate the camera backwards
view = Matrix.multiply(transformation, view)
Simply run your switch statement, generate a transformation and update the view matrix.
e.g:
if (key == 'w')
view = Matrix.multiply(Matrices.createTranslate(0,0,-5), view);
if (key = 'j') // Key to turn
view = Matrix.multiply(Matrices.createRotateY(.1), view);
Formulas for genereating these matrices can be found on wikipedia(or DirectX might give them on its own).
(This is all based off of a simple software renderer I made a while ago, but it should apply the same to DirectX)
EDIT:
Oh, it looks like DirectX has all of these functions for you already in http://msdn.microsoft.com/en-us/library/windows/desktop/bb281696(v=vs.85).aspx

Related

OpenGL rotate camera on 2 keys

Basically what I'm trying to do is rotate a camera around an object in the center when I hold down "c" and use the arrow keys.
My first question doesn't have much to do with the camera, but with having a key callback recognize 2 keys at the same time.
My function DOES work if I have separate if statements for L/R keys and no "c", but I can't get it to work when I only want the camera to rotate when I'm holding down "c". I have tried using switch(key) and if statements within if statements. Both implementations I've tried are in the code below:
float R = 0.0;
float U = 0.0;
static void keyCallback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
if(key == GLFW_KEY_C && action == GLFW_PRESS) {
switch(key) {
case GLFW_KEY_RIGHT:
R+=0.05;
camera(R, U);
break;
case GLFW_KEY_LEFT:
R-=0.05;
camera(R, U);
break;
case GLFW_KEY_UP:
break;
case GLFW_KEY_DOWN:
break;
default:
break;
}
}
//OR --
if(key == GLFW_KEY_C && action == GLFW_PRESS) {
if(key == GLFW_KEY_RIGHT && action == GLFW_PRESS) {
R+=0.05;
camera(R, U);
}
}
}
What am I doing wrong? Is there something else I can try?
My second question has more to do with the camera. It rotates fine for a half circle around the object with my current code, but then once it reaches a certain point, the camera just pans farther and farther away from the object, rather than rotating.
This is the code for my camera function:
GLfloat ox = 10.0;
GLfloat oy = 10.0;
static void camera(float RL, float UD) {
ox+=cos(glm::radians(RL));
oy+=sin(glm::radians(RL));
gViewMatrix = glm::lookAt(glm::vec3(ox, oy, 10.0f), // eye
glm::vec3(0.0, 0.0, 0.0), // center
glm::vec3(0.0, 1.0, 0.0));
}
Your 'C' detecting code won't work because you're only matching when key equals C and an arrow. It can't be both. You'll have to keep another global variable, isCPressed. When C is pressed you set it to true, when C is released you set it to false, and then when an arrow is pressed you check if(isCPressed).
as for the camera code, your algorithm orbits the point 0,0,10 while looking at 0,0,0. That doesn't seem to be what you want, you should have something like oxdist, oydist, 0 for the eye position to orbit 0,0,0 at a distance of 'dist'

trying to use switch statement to move an image in relation to mouse position c++ SFML

as I'm new to coding in general I'm sure that my thinking is just heading in the wrong direction with this however..
I'm trying to get a sprite to chase the mouse on left click. I had tried to use else if statements but only the first 2 statements would run even on multiple clicks.
I want to be able to say if mouseposition.x > playerposition.x then move playerimage right, and so one for the other directions.
as I'm using sfml, I've used the below to get the positions of both.
sf::Vector2i mousePosition = sf::Mouse::getPosition(window);
sf::Vector2f playerPosition = playerImage.getPosition();
I was hoping to use the switch statement as below but I'm at a loss as to how to create the argument and compare the cases to that argument.
if(sf::Mouse::isButtonPressed(sf::Mouse::Left))
switch()
{
case 1:
playerImage.move(0.02, 0);
case 2:
playerImage.move(-0.02, 0);
case 3:
playerImage.move(0, -0.02);
case 4:
playerImage.move(0, 0.02);
}
Maybe something like this?
if (sf::Mouse::isButtonPressed(sf::Mouse::Left)) {
sf::Vector2f offset;
if (mousePosition.x > playerPosition.x) {
offset.x = 0.02f;
} else if (mousePosition.x < playerPosition.x) {
offset.x = -0.02f;
}
if (mousePosition.y > playerPosition.y) {
offset.y = 0.02f;
} else if (mousePosition.y < playerPosition.y) {
offset.y = -0.02f;
}
playerImage.move(offset);
}

SDL collision handling

I have an instance where a SDL_Rect is inside of a big SDL_Rect and i need it to make it so it cannot leave that rect but can still move. The movement of the little rect needs to be like board game movement where you click the button once and it moves a certain cords here is my code:
if( event.type == SDL_KEYDOWN) {
switch( event.key.keysym.sym ) {
case SDLK_UP:
yVel -= 10;
if (!check_collision(box,Cont))
{
std::cout<<"in the water"<<std::endl;
box.y -= yVel - 10;
}
break;
case SDLK_DOWN:
if (!check_collision(box,Cont))
{
std::cout<<"in the water"<<std::endl;
box.y -= yVel + 20;
}
else
{
yVel += 10;
}
break;
case SDLK_LEFT:
xVel -= 10;
if (!check_collision(box,Cont))
{
std::cout<<"in the water"<<std::endl;
}
break;
case SDLK_RIGHT:
xVel += 10;
if (!check_collision(box,Cont))
{
std::cout<<"in the water"<<std::endl;
}
break;
case SDLK_1:
return 2;
break;
}
}
You have inconsistencies in your SDLK_DOWN and the rest of your inputs - no velocity change happens if there are no collisions.
Your input code is changing coordinates, it shouldn't be like that. Make your input code manage the "intent", and have a game loop apply velocity to the object and to the collision detection.
Also, your collision checks should check if I'm at position and I move of delta, will I collide? If I do collide, what's the collision reaction? Do you want the entity to "slide" on collisions or simply stop as soon as a collision is detected?
Considering you are doing a board game, you shouldn't even have to do collision detection. Represent your board as a graph of possible positions your unit can be, translate mouse clicks into board coordinates and calculate the shortest path (use the A* algorithm) between your current position and your destination; invalid clicks (out of bounds) shouldn't translate into movement commands.

OpenGL strange Rendering behaviour (flickering faces)

PRE: I'm using Assimp (Open Asset Import) library to import a .3ds file. Meshes are rendered with normals and materials. Using Qt. Drivers up to date on all the computers we tried.
POST: When I rotate around the objects,using camera,I can see that some mesh' faces flickering.
The same happens using Assimp' render() method (sample code downloaded from A. wsite).
1)The strange thing is that it usually happens with small size .3ds,while never happens with big ones.
2)If I am really close there are no artifacts.The furthest I am,the more artifacts I see.
Is it a .3ds problem or mine?
Example of big .3ds (20MB)
Example of small .3ds (3MB)
I paste here my Draw() function (uses glLists but i can't get rid of them):
void Preview::BuildObjectsLists(Scene *sc,GLenum mode){
QHash<QString, SceneObject*>& hash=sc->getObj();
int counter =0;
for (QHash<QString,SceneObject*>::ConstIterator i = hash.begin();i!=hash.end();++i) {
glNewList(index-counter, GL_COMPILE);
Mesh* p = dynamic_cast<Mesh*>(i.value());
if(p){
Matrix4x4& a=p->getTrasformation();
a.transpose();
if(mode==GL_SELECT){
glPushName(counter);
}
glPushMatrix();
glMultMatrixf((float*) &(a.values));
applyMaterial(p->getMat());
QList<Face>& faccie=p->getFaces();
int numerofacce=faccie.count();
QList<Vector3D>& normals =p->getNormals();
bool hasNormals=(!(normals.isEmpty()));
if(hasNormals) glEnable(GL_LIGHTING);
else glDisable(GL_LIGHTING);
for (int t = 0; t < numerofacce; ++t) {
Face& f = faccie[t];
GLenum face_mode;
Vector3D* lista=f.arrayVertici;
int* listaNorm=f.normalIndex;
switch(f.numVertici) {
case 1:
face_mode = GL_POINTS;
glBegin(face_mode);
if(hasNormals)
glNormal3fv(&((normals[listaNorm[0]]).pos[0]));
glVertex3fv(&lista[0].pos[0]);
break;
case 2:
face_mode = GL_LINES;
glBegin(face_mode);
if(hasNormals){
glNormal3fv(&((normals[(f.normalIndex)[0]]).pos[0]));
glVertex3fv(&lista[0].pos[0]);
glNormal3fv(&((normals[(f.normalIndex)[1]]).pos[0]));
glVertex3fv(&lista[1].pos[0]);
}
else{
glVertex3fv(&lista[0].pos[0]);
glVertex3fv(&lista[1].pos[0]);
}
break;
case 3:
face_mode = GL_TRIANGLES;
glBegin(face_mode);
if(hasNormals){
glNormal3fv(&normals[(f.normalIndex)[0]].pos[0]);
glVertex3fv(&lista[0].pos[0]);
glNormal3fv(&normals[(f.normalIndex)[1]].pos[0]);
glVertex3fv(&lista[1].pos[0]);
glNormal3fv(&normals[(f.normalIndex)[2]].pos[0]);
glVertex3fv(&lista[2].pos[0]);
}
else{
glVertex3fv(&lista[0].pos[0]);
glVertex3fv(&lista[1].pos[0]);
glVertex3fv(&lista[2].pos[0]);
}
break;
default: face_mode = GL_POLYGON; break;
}
glEnd();
}
glPopMatrix();
}
if(mode==GL_SELECT) glPopName();
glEndList();
counter++;
}
}
12.040 Depth buffering seems to work, but polygons seem to bleed through polygons that are in front of them. What's going on?
You may have configured your zNear and zFar clipping planes in a way that severely limits your depth buffer precision. Generally, this is caused by a zNear clipping plane value that's too close to 0.0.
http://www.opengl.org/archives/resources/faq/technical/depthbuffer.htm

OpenGL L-System Rendering

I have gotten my basic L-System working and I decided to try and optimize the rendering of the application. Previously I was looping through the whole string of the L-System with a switch case and drawing. Better yet I will show you what I was doing:
for(unsigned int stringLoop = 0; stringLoop < _buildString.length(); stringLoop++)
{
switch(_buildString.at(stringLoop))
{
case'X':
//Do Nothing
//X is there just to facilitate the Curve of the plant
break;
case'F':
_prevState = _currState;
_currState.position += _currState.direction * stdBranchLength;
//Set the previous state to the current state
_graphics.SetColour3f(0.0f, 1.0f, 0.0f);
_graphics.Begin(OGLFlags::LINE_STRIP);
_graphics.Vertex3f(_prevState.position.X(), _prevState.position.Y(), _prevState.position.Z());
_graphics.Vertex3f(_currState.position.X(), _currState.position.Y(), _currState.position.Z());
_graphics.End();
break;
case'[':
_prevStack.push(_currState);
break;
case']':
_prevState = _currState;
_currState = _prevStack.top();
_prevStack.pop();
break;
case'-':
_currState.direction = _currState.direction.RotatedAboutZ(-(ROTATION) * Math::DegreesToRadians);
break;
case'+':
_currState.direction = _currState.direction.RotatedAboutZ(ROTATION * Math::DegreesToRadians);
break;
};
}
I removed all of this because I was literally resolving the tree every single frame, I changed this loop so that it would save all of the verticies in a std vector.
for(unsigned int stringLoop = 0; stringLoop < _buildString.length(); stringLoop++)
{
switch(_buildString.at(stringLoop))
{
case'X':
break;
case'F':
//_prevState = _currState;
_currState.position += _currState.direction * stdBranchLength;
_vertexVector.push_back(_currState.position);
break;
case'[':
_prevStack.push(_currState);
break;
case']':
_currState = _prevStack.top();
_prevStack.pop();
break;
case'-':
_currState.direction = _currState.direction.RotatedAboutZ(-(ROTATION) * Math::DegreesToRadians);
break;
case'+':
_currState.direction = _currState.direction.RotatedAboutZ(ROTATION * Math::DegreesToRadians);
break;
};
}
Now I changed my render loop so I just read straight from the vector array.
DesignPatterns::Facades::OpenGLFacade _graphics = DesignPatterns::Facades::openGLFacade::Instance();
_graphics.Begin(OGLFlags::LINE_STRIP);
for(unsigned int i = 0; i < _vertexVector.size(); i++)
{
_graphics.Vertex3f(_vertexVector.at(i).X(), _vertexVector.at(i).Y(), _vertexVector.at(i).Z());
}
_graphics.End();
Now my problem is that when I am using a vector array and I use Line Stip, I get extra artifact.
The first image is the original render that is the unoptimized one, then the second is the newer render which runs faster, and the thirds is a render of a dragon curve which uses no push and pops like the first two are using (I am pretty sure the push and pop is where the problems are coming in).
Is the problem with my logic here of storing verticies, or is it because I am using a line strip? I would just use lines, but it doesn't really work at all, it ends up looking more of a line_stipple.
Also sorry about the length of this post.
alt text http://img197.imageshack.us/img197/8030/bettera.jpg
alt text http://img23.imageshack.us/img23/3924/buggyrender.jpg
alt text http://img8.imageshack.us/img8/627/dragoncurve.jpg
You are getting those extra lines because you are using a LINE_STRIP.
In your 'F' case, push both end points of your line into the vector (like you were doing originally).
_vertexVector.push_back(_prevState.position);
_vertexVector.push_back(_currState.position);
And when you draw, use LINE_LIST instead.