I am porting my OpenGL 1.1 application to OpenGL ES 2.0 and am writing a wrapper to implement the OpenGL 1.1 functions. My code seems to work fine until I start calling glPushMatrix() and glPopMatrix(). I think my understanding of how these should be implemented is incorrect.
Do I compute the final rotate/translate/scale before pushing it back on the stack? Should I keep only one modelview matrix (instead of separating it into three)? Are the transforms applied in the correct order?
Here is the code for my tranformation matrices
static std::vector<GLfloat> vertices;
static std::vector<std::vector<GLfloat>> rotationMatrixStack;
static std::vector<std::vector<GLfloat>> scalingMatrixStack;
static std::vector<GLfloat> rotationMatrix =
{
1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f
};
static std::vector<GLfloat> scalingMatrix =
{
1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f
};
static std::vector<GLfloat> translationMatrix =
{
1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f
};
static std::vector<GLfloat> orthographicMatrix =
{
.0025f, 0.0f, 0.0f, -1.0f,
0.0f, .0025f, 0.0f, -1.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f
};
void glTranslatef (GLfloat x, GLfloat y, GLfloat z)
{
float translation[] =
{
1.0f, 0.0f, 0.0f, x,
0.0f, 1.0f, 0.0f, y,
0.0f, 0.0f, 1.0f, z,
0.0f, 0.0f, 0.0f, 1.0f
};
multiplyMatrix(translation , &translationMatrix[0], &translationMatrix[0]);
}
void glScalef (GLfloat x, GLfloat y, GLfloat z)
{
float scaling[] =
{
x, 0.0f, 0.0f, 0.0f,
0.0f, y, 0.0f, 0.0f,
0.0f, 0.0f, z, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f
};
multiplyMatrix(scaling , &scalingMatrix[0], &scalingMatrix[0]);
}
void glRotatef (GLfloat angle, GLfloat x, GLfloat y, GLfloat z)
{
glTranslatef(-x, -y, -z);
GLfloat radians = angle * M_PI/180;
float zRotation[] =
{
cos(radians), -sin(radians), 0.0f, 0.0f,
sin(radians), cos(radians), 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f
};
multiplyMatrix(zRotation , &rotationMatrix[0], &rotationMatrix[0]);
glTranslatef(x,y,z);
}
void glLoadIdentity (void)
{
rotationMatrix, scalingMatrix, translationMatrix =
{
1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f
};
}
void multiplyMatrix(float* a, float* b, float* product)
{
int a_heigth = 4;
int a_width = 4;
int b_heigth = 4;
int b_width = 4;
int product_heigth = a_heigth;
int product_width = b_width;
float intermediateMatrix[product_heigth * product_width] = {0};
for (int product_row = 0; product_row < product_heigth; product_row++)
{
for (int product_column = 0; product_column < product_width; product_column++)
{
float value = 0;
//std::cout << "r[" << (product_row*product_width) + product_column << "] = ";
for (int multiplication_index = 0; multiplication_index < a_width ; multiplication_index++)
{
value += a[(product_row * a_width) + multiplication_index] * b[product_column + (b_heigth * multiplication_index)];
//std::cout << "( a[" << (product_row * a_width) + multiplication_index << "] * b[" << product_column + (b_heigth * multiplication_index) << "] ) + ";
}
//std::cout << std::endl;
intermediateMatrix[(product_row*product_width) + product_column] = value;
}
}
for (int i = 0; i < product_heigth * product_width; i++)
{
product[i] = intermediateMatrix[i];
}
}
Here is the code for the matrix stack
static std::vector<std::vector<GLfloat>> translationMatrixStack;
void glPushMatrix()
{
rotationMatrixStack.push_back(rotationMatrix);
scalingMatrixStack.push_back(scalingMatrix);
translationMatrixStack.push_back(translationMatrix);
}
void glPopMatrix()
{
rotationMatrix = rotationMatrixStack.back();
scalingMatrix = scalingMatrixStack.back();
translationMatrix = translationMatrixStack.back();
rotationMatrixStack.pop_back();
scalingMatrixStack.pop_back();
translationMatrix.pop_back();
}
And here is the vertex shader code
attribute highp vec4 myVertex;
uniform mediump mat4 orthographicMatrix;
uniform mediump mat4 translationMatrix;
uniform mediump mat4 scalingMatrix;
uniform mediump mat4 rotationMatrix;
void main(void)
{
gl_Position = orthographicMatrix * translationMatrix * scalingMatrix * rotationMatrix * ( myVertex) ;
}";
You do not have a separate matrix stack for rotation, translation and scaling. In OpenGL there is one matrix stack for each matrix mode (See glMatrixMode). The matrix modes are GL_MODELVIEW, GL_PROJECTION, and GL_TEXTURE.
See the documentation of glTranslate:
glTranslate produces a translation by x y z . The current matrix (see glMatrixMode) is multiplied by this translation matrix, with the product replacing the current matrix.
the documentation of glRotate:
glRotate produces a rotation of angle degrees around the vector x y z . The current matrix (see glMatrixMode) is multiplied by a rotation matrix with the product replacing the current matrix.
and the documentation of glScale:
glScaleproduces a nonuniform scaling along the x, y, and z axes. The three parameters indicate the desired scale factor along each of the three axes.
The current matrix (see glMatrixMode) is multiplied by this scale matrix.
This means you need one matrix stack, and all operations operate on the same matrix stack.
Note, a matrix multiplication C = A * B works like this:
Matrix4x4 A, B, C;
// C = A * B
for ( int k = 0; k < 4; ++ k )
for ( int j = 0; j < 4; ++ j )
C[k][j] = A[0][l] * B[k][0] + A[1][j] * B[k][1] + A[2][j] * B[k][2] + A[3][j] * B[k][3];
A 4*4 matrix looks like this:
c0 c1 c2 c3 c0 c1 c2 c3
[ Xx Yx Zx Tx ] [ 0 4 8 12 ]
[ Xy Yy Zy Ty ] [ 1 5 9 13 ]
[ Xz Yz Zz Tz ] [ 2 6 10 14 ]
[ 0 0 0 1 ] [ 3 7 11 15 ]
And the memory image of a 4*4 matrix looks like this:
[ Xx, Xy, Xz, 0, Yx, Yy, Yz, 0, Zx, Zy, Zz, 0, Tx, Ty, Tz, 1 ]
This means you have to adapt your matrix operations:
static std::vector<std::vector<GLfloat>> modelViewMatrixStack;
static std::vector<GLfloat> modelViewMatrix{
1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f };
void multiplyMatrix( float A[], float B[], float P[] )
{
float C[16];
for ( int k = 0; k < 4; ++ k ) {
for ( int l = 0; l < 4; ++ l ) {
C[k*4+j] =
A[0*4+j] * B[k*4+0] +
A[1*4+j] * B[k*4+1] +
A[2*4+j] * B[k*4+2] +
A[3*4+j] * B[k*4+3];
}
}
std::copy(C, C+16, P);
}
void glTranslatef( GLfloat x, GLfloat y, GLfloat z )
{
float translation[]{
1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
x, y, z, 1.0f };
multiplyMatrix(&modelViewMatrix[0], translation, &modelViewMatrix[0]);
}
void glScalef( GLfloat x, GLfloat y, GLfloat z )
{
float scaling[]{
x, 0.0f, 0.0f, 0.0f,
0.0f, y, 0.0f, 0.0f,
0.0f, 0.0f, z, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f };
multiplyMatrix(&modelViewMatrix[0], scaling, &modelViewMatrix[0]);
}
void glRotatef( GLfloat angle, GLfloat x, GLfloat y, GLfloat z )
{
float radians = angle * M_PI/180;
float c = cos(radians);
float s = sin(radians);
float rotation[16]{
x*x*(1.0f-c)+c, x*y*(1.0f-c)-z*s, x*z*(1.0f-c)+y*s, 0.0f,
y*x*(1.0f-c)+z*s, y*y*(1.0f-c)+c, y*z*(1.0f-c)-x*s, 0.0f,
z*x*(1.0f-c)-y*s z*y*(1.0f-c)+x*s, z*z*(1.0f-c)+c, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f };
multiplyMatrix(&rotationMatrix[0], rotation, &rotationMatrix[0]);
}
See further:
GLSL 4×4 Matrix Fields
GLSL Programming/Vector and Matrix Operations
Data Type (GLSL)
Related
I used vertexes to draw textures and did not have a problem but now i am trying to rotate some textures and getting black screen.
This is my initial code to draw texture with vertex.
struct CUSTOM_VERTEX { FLOAT X, Y, Z, RHW, U, V; };
#define CUSTOM_FVF (D3DFVF_XYZRHW | D3DFVF_TEX1 )
CUSTOM_VERTEX vertices[4] =
{ //X, Y, Z, RHW, U, V
100.0f, 100.0f, 0.0f, 1.0f, 0.0f, 0.0f,
1000.0f, 100.0f, 0.0f, 1.0f, 1.0f, 0.0f,
100.0f, 750.0f, 0.0f, 1.0f, 0.0f, 1.0f,
1000.0f, 750.0f, 0.0f, 1.0f, 1.0f, 1.0f
};
LPDIRECT3DVERTEXBUFFER9 v_buffer = NULL;
d3d9device->CreateVertexBuffer(4 * sizeof(CUSTOM_VERTEX),
0,
CUSTOM_FVF,
D3DPOOL_MANAGED,
&v_buffer,
NULL);
VOID* pVoid;
v_buffer->Lock(0, 0, (void**)&pVoid, 0);
memcpy(pVoid, vertices, sizeof(vertices));
v_buffer->Unlock();
d3d9device->SetFVF(CUSTOM_FVF);
d3d9device->SetStreamSource(0, v_buffer, 0, sizeof(CUSTOM_VERTEX));
d3d9device->SetTexture(0, d3d9texture);
d3d9device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
I read that RHW describes pre-transformed vertices. Then i changed CUSTOM_VERTEX, CUSTOM_FVF and added SetTransform.
struct CUSTOM_VERTEX { FLOAT X, Y, Z, U, V; };
#define CUSTOM_FVF (D3DFVF_XYZ | D3DFVF_TEX1 )
CUSTOM_VERTEX vertices[4] =
{ //X, Y, Z, U, V
100.0f, 100.0f, 0.0f, 0.0f, 0.0f,
1000.0f, 100.0f, 0.0f, 1.0f, 0.0f,
100.0f, 750.0f, 0.0f, 0.0f, 1.0f,
1000.0f, 750.0f, 0.0f, 1.0f, 1.0f
};
//CreateVertexBuffer, memcpy, SetFVF and SetStreamsource are the same as above
D3DXMATRIX worldMatrix;
D3DXMatrixRotationZ(&worldMatrix, D3DXToRadian(90));
d3d9device->SetTransform(D3DTS_WORLD, &worldMatrix);
//SetTexture and DrawPrimitive are the same as above
I also tried adding view and projection matrix.
D3DXMATRIX viewMatrix;
D3DXMatrixLookAtLH(&viewMatrix,
&D3DXVECTOR3 (0.0f, 0.0f, 10.0f),
&D3DXVECTOR3 (0.0f, 0.0f, 0.0f),
&D3DXVECTOR3 (0.0f, 1.0f, 0.0f));
d3d9device->SetTransform(D3DTS_VIEW, &viewMatrix);
D3DXMATRIX projectionMatrix;
D3DXMatrixPerspectiveFovLH(&projectionMatrix,
D3DXToRadian(45),
width / height,
1.0f,
1000.0f);
d3d9device->SetTransform(D3DTS_PROJECTION, &projectionMatrix);
I changed pEye and pAt inputs of D3DXMatrixLookAtLH method to center of vertex but again black screen.
My problem was using the same points for both pre-transformed (RHW) and non pre-transformed vertices.
Solved problem like below.
struct CUSTOM_VERTEX { FLOAT X, Y, Z, U, V; };
#define CUSTOM_FVF (D3DFVF_XYZ | D3DFVF_TEX1 )
float halfBackBufferWidth = backBufferWidth / 2.0f;
float halfBackBufferHeight = backBufferHeight / 2.0f;
CUSTOM_VERTEX vertices[4] =
{ //X, Y, Z, U, V
{ halfBackBufferWidth - 100.0f, halfBackBufferHeight - 100.0f, 0.0f, 0.0f, 0.0f },
{ halfBackBufferWidth - 1000.0f, halfBackBufferHeight - 100.0f, 0.0f, 1.0f, 0.0f },
{ halfBackBufferWidth - 100.0f, halfBackBufferHeight - 750.0f, 0.0f, 0.0f, 1.0f },
{ halfBackBufferWidth - 1000.0f, halfBackBufferHeight - 750.0f, 0.0f, 1.0f, 1.0f }
};
LPDIRECT3DVERTEXBUFFER9 v_buffer = NULL;
d3d9device->CreateVertexBuffer(4 * sizeof(CUSTOM_VERTEX),
0,
CUSTOM_FVF,
D3DPOOL_MANAGED,
&v_buffer,
NULL);
VOID* pVoid;
v_buffer->Lock(0, 0, (void**)&pVoid, 0);
memcpy(pVoid, vertices, sizeof(vertices));
v_buffer->Unlock();
d3d9device->SetFVF(CUSTOM_FVF);
d3d9device->SetStreamSource(0, v_buffer, 0, sizeof(CUSTOM_VERTEX));
D3DXMATRIX worldMatrix;
D3DXMatrixRotationZ(&worldMatrix, D3DXToRadian(45));
d3d9device->SetTransform(D3DTS_WORLD, &worldMatrix);
D3DXMATRIX viewMatrix;
D3DXMatrixLookAtLH(&viewMatrix,
&D3DXVECTOR3 (0.0f, 0.0f, halfBackBufferHeight),
&D3DXVECTOR3 (0.0f, 0.0f, 0.0f),
&D3DXVECTOR3 (0.0f, 1.0f, 0.0f));
d3d9device->SetTransform(D3DTS_VIEW, &viewMatrix);
D3DXMATRIX projectionMatrix;
D3DXMatrixPerspectiveFovLH(&projectionMatrix,
D3DXToRadian(90),
backBufferWidth / backBufferHeight,
1.0f,
halfBackBufferHeight);
d3d9device->SetTransform(D3DTS_PROJECTION, &projectionMatrix);
d3d9device->SetTexture(0, d3d9texture);
d3d9device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
I dont want to add light so I disable it. If I dont disable it, I get black screen.
d3d9device->SetRenderState(D3DRS_LIGHTING, FALSE);
I am working on a custom 3D renderer engine based on Javidx9 3D engine tutorial. I'm trying to get some collision detection with rays and segments and it's not properly working.
I've tried implementing different methods trying to make it work the way I want it to but either the function is not working or its the way im using the function after it has been implemented. The current algorithm I am using is based on "Real-Time Collision Detection", by Christer Ericson, Pg 191. However, when the program is run I am getting no triangles intercepted triangles (the return vector is always zero). Is there something wrong with my code?
Note: I have some predefined functions that are self-explanatory based on the name.
#include <iostream>
#include <fstream>
#include <strstream>
#include <algorithm>
#include <string>
#include <vector>
#define SMALL_NUM 0.00000001 // anything that avoids division overflow
using namespace std;
// Created a 2D structure to hold texture coordinates
struct vec2d
{
float u = 0;
float v = 0;
float w = 1;
};
struct vec3d
{
float x = 0;
float y = 0;
float z = 0;
float w = 1; // Need a 4th term to perform sensible matrix vector multiplication
bool operator==(vec3d a) const
{
if (a.x == x && a.y == y && a.z == z && a.w == w)
return true;
else
return false;
}
vec3d operator+(const vec3d& a) const
{
return vec3d{ a.x + x, a.y + y, a.z + z, w };
}
vec3d operator-(const vec3d& a) const
{
return vec3d{ a.x - x, a.y - y, a.z - z, w };
}
vec3d operator*(const vec3d& a) const
{
return vec3d{ a.x * x, a.y * y, a.z * z, w };
}
vec3d operator/(const vec3d& a) const
{
return vec3d{ a.x / x, a.y / y, a.z / z, w };
}
vec3d operator+(const float& a) const
{
return vec3d{ a + x, a + y, a + z, w };
}
vec3d operator-(const float& a) const
{
return vec3d{ a - x, a - y, a - z, w };
}
vec3d operator*(const float& a) const
{
return vec3d{ a * x, a * y, a * z, w };
}
vec3d operator/(const float& a) const
{
return vec3d{ a / x, a / y, a / z, w };
}
};
struct triangle
{
vec3d p[3];
vec2d t[3]; // added a texture coord per vertex
int triid = 0;
wchar_t sym;
short col;
bool calculated = false;
};
struct mesh
{
vector<triangle> tris;
};
struct collision
{
bool plane = false;
triangle tris;
vec3d points;
};
float Vector_DotProduct(vec3d v1, vec3d v2)
{
return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
}
float Vector_Length(vec3d v)
{
return sqrtf(Vector_DotProduct(v, v));
}
vec3d Vector_Normalise(vec3d v)
{
float l = Vector_Length(v);
return { v.x / l, v.y / l, v.z / l };
}
vec3d Vector_CrossProduct(vec3d v1, vec3d v2)
{
vec3d v;
v.x = v1.y * v2.z - v1.z * v2.y;
v.y = v1.z * v2.x - v1.x * v2.z;
v.z = v1.x * v2.y - v1.y * v2.x;
return v;
}
vector<collision> CollisionSegment(vec3d ray, vec3d rayend, mesh* m)
{
vector<collision> ret; // The return varaible
vec3d raydir = Vector_Normalise(rayend - ray); // The ray direction
for (auto tri : m->tris)
{
vec3d ab = tri.p[1] - tri.p[0];
vec3d ac = tri.p[2] - tri.p[0];
vec3d qp = rayend - ray;
vec3d n = Vector_CrossProduct(ab, ac);
float d = Vector_DotProduct(qp, n);
if (d <= SMALL_NUM) continue;
vec3d ap = ray - tri.p[0];
float t = Vector_DotProduct(ap, n);
if (t < SMALL_NUM) continue;
if (t < d) continue;
vec3d e = Vector_CrossProduct(qp, ap);
float v = Vector_DotProduct(ac, e);
if (v < SMALL_NUM || v > d) continue;
float w = -Vector_DotProduct(ab, e);
if (w < SMALL_NUM || v + w > d) continue;
float ood = 1.0f / d;
t *= ood;
v *= ood;
w *= ood;
float u = 1.0f - v - w;
ret.push_back(collision{ false, tri, vec3d() });
}
return ret;
}
int main()
{
mesh meshCube;
meshCube.tris = {
// SOUTH
{ 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f,},
{ 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f,},
// EAST
{ 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f,},
{ 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f,},
// NORTH
{ 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f,},
{ 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f,},
// WEST
{ 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f,},
{ 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f,},
// TOP
{ 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f,},
{ 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f,},
// BOTTOM
{ 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f,},
{ 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f,},
};
vec3d p1 = { -1.5f, -1.5f, -1.5f };
vec3d p2 = { 1.5f, 1.5f, 1.5f };
vector<collision> hits = CollisionSegment(p1, p2, &meshCube);
return 0;
}
What I want is whenever I look at a mesh I want a vector of the triangles that come between me and my camera segment.
My perspective matrix is doing a weird thing where it makes my 3d pyramid look like a trapezoid.
This is the effect im getting
Angle 1
Angle 2
If I rotate the pyramid this effect is consistent so I don't think it has anything to do with my vertices. What is causing this effect to occur?
Animation Loop:
//enables depth testing
glEnable(GL_DEPTH_TEST);
//creates aspect ratio variable
float aspect = 500.0f / 500.0f;
//enables projection matrix
glm::mat4 pmat = glm::perspective(70.0f, aspect, 0.01f, 1000.0f);
//enables view matrix
glm::vec3 eye(0, -1, 2);
glm::vec3 center(0, 0, 0);
glm::vec3 up(0, 1, 0);
glm::mat4 vmat = glm::lookAt(eye, center, up);
while (!glfwWindowShouldClose(mWindow)) //animation loop
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glm::mat4 mvp = pmat * vmat * tmat;
glUniformMatrix4fv(uTransform, 1, GL_FALSE, glm::value_ptr(mvp));
for (int i = 0; i <= numberofshapes; i++)
{
glBindVertexArray(shapes[i].vao);
glDrawArrays(shapes[i].drawtype, 0, shapes[i].numOfvertices);
}
if (w == true) {
tmat = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.001f, 0.0f)) * tmat;
}if (a == true) {
tmat = glm::translate(glm::mat4(1.0f), glm::vec3(-0.001f, 0.0f, 0.0f)) * tmat;
}if (s == true) {
tmat = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, -0.001f, 0.0f)) * tmat;
}if (d == true) {
tmat = glm::translate(glm::mat4(1.0f), glm::vec3(0.001f, 0.0f, 0.0f)) * tmat;
}if (r == true) {
tmat = glm::rotate(glm::mat4(1.0f), glm::radians(0.1f), glm::vec3(0.0f, 1.0f, 0.0f)) * tmat;
}
glfwSwapBuffers(mWindow);
counter += 1;
glfwPollEvents();
}
Vertex Arrays:
vertex vertices[] = {
mkVert(0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f),
mkVert(-0.5f, -0.5f, 0.5f, 1.0f, 1.0f, 1.0f),
mkVert(0.5f, -0.5f, 0.5f, 1.0f, 1.0f, 1.0f)
};
//SECOND OBJECT
vertex vertices2[] = {
mkVert(0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f),
mkVert(-0.5f, -0.5f, 0.5f, 1.0f, 1.0f, 1.0f),
mkVert(-0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 1.0f)
};
//THIRD OBJECT
vertex vertices3[] = {
mkVert(0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f),
mkVert(0.5f, -0.5f, 0.5f, 1.0f, 1.0f, 1.0f),
mkVert(0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 1.0f)
};
vertex vertices4[] = {
mkVert(0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f),
mkVert(0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 1.0f),
mkVert(-0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 1.0f)
};
Just fyi my window is 500x500, I dont know if that would cause this effect.
Your camera is pointing at your pyramid from below. I guess your brain expected to look at it from above!? Especially with just a wireframe, this can get confusing. So here's a GIF of a pyramid being looked at from below:
The following two methods are taken from the ios GLKit framework:
GLK_INLINE GLKMatrix4 GLKMatrix4MakeOrtho(float left, float right,
float bottom, float top,
float nearZ, float farZ)
{
float ral = right + left;
float rsl = right - left;
float tab = top + bottom;
float tsb = top - bottom;
float fan = farZ + nearZ;
float fsn = farZ - nearZ;
GLKMatrix4 m = { 2.0f / rsl, 0.0f, 0.0f, 0.0f,
0.0f, 2.0f / tsb, 0.0f, 0.0f,
0.0f, 0.0f, -2.0f / fsn, 0.0f,
-ral / rsl, -tab / tsb, -fan / fsn, 1.0f };
return m;
}
GLK_INLINE GLKMatrix4 GLKMatrix4MakePerspective(float fovyRadians, float aspect, float nearZ, float farZ)
{
float cotan = 1.0f / tanf(fovyRadians / 2.0f);
GLKMatrix4 m = { cotan / aspect, 0.0f, 0.0f, 0.0f,
0.0f, cotan, 0.0f, 0.0f,
0.0f, 0.0f, (farZ + nearZ) / (nearZ - farZ), -1.0f,
0.0f, 0.0f, (2.0f * farZ * nearZ) / (nearZ - farZ), 0.0f };
return m;
}
I would like to smoothly move from perspective view to ortho view and vice-versa. How should i calculate the correct parameters for ortho matrix, given the perspective matrix and parameters?
This is how i have declared my light values and their positions
is this correct or is there another more officiant way?
// Lighting values
GLfloat greenLight[] = { 0.0f, 0.6f, 0.0f, 1.0f };
GLfloat redLight[] = { 0.6f, 0.0f, 0.0f, 1.0f };
GLfloat blueLight[] = { 0.0f, 0.6f, 0.0f, 1.0f };
GLfloat whiteLight[] = { 0.2f, 0.2f, 0.2f, 1.0f };
GLfloat sourceLight[] = { 0.9f, 0.9f, 0.9f, 1.0f };
GLfloat lightPos[] = { 0.0f, 0.0f, 0.0f, 1.0f };
GLfloat lightPos1[] = { 5.0f, -5.0f, 0.0f, 0.0f };
GLfloat lightPos2[] = { -5.0f, 5.0f, 0.0f, 0.0f };
GLfloat lightPos3[] = { 5.0f, 5.0f, 0.0f, 0.0f };
There really isn't any other way to do it using fixed-function OpenGL. Setting the parameters is a small part of the cost of lighting. If you want something more efficient, I would recommend you learn non-deprecated OpenGL and implement lighting in a shader, which will probably be faster than fixed-function lighting.