Trying to create an array of type GLFloat which contains arrays of type GLFloat.
GLfloat p0[] = { -3, 0, -3};
GLfloat p1[] = { 3, 0, -3};
GLfloat points[2][3] = {p0, p1};
Error message: Type GLFloat cannot be used to an entity of type GLFloat
You could create the matrix directly.
GLfloat points[2][3] = {{-3, 0, -3}, { 3, 0, -3}};
If you want to use braced initialisation the way to go would be
points[2][3] = { {-3, 0, -3}, {3, 0, -3} };
Why your way doesn't work:
points[2][3] = { p0, p1 };
What happens is that p0 decays to float* and so does p1 which you cannot assign to float.
Another option would be with memcpy:
std::memcpy(&points[0], &p0, 3 * sizeof(float));
std::memcpy(&points[1], &p1, 3 * sizeof(float));
But I'm not a fan of all this address manipulation and memcpy when using C++
Related
This is my perspective projection matrix code
inline m4
Projection(float WidthOverHeight, float FOV)
{
float Near = 1.0f;
float Far = 100.0f;
float f = 1.0f/(float)tan(DegToRad(FOV / 2.0f));
float fn = 1.0f / (Near - Far);
float a = f / WidthOverHeight;
float b = f;
float c = Far * fn;
float d = Near * Far * fn;
m4 Result =
{
{{a, 0, 0, 0},
{0, b, 0, 0},
{0, 0, c, -1},
{0, 0, d, 0}}
};
return Result;
}
And here is the main code
m4 Project = Projection(ar, 90);
m4 Move = {};
CreateMat4(&Move,
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, -2,
0, 0, 0, 1);
m4 Rotate = Rotation(Scale);
Scale += 0.01f;
m4 FinalTransformation = Project * Move * Rotate;
SetShaderUniformMat4("Project", FinalTransformation, ShaderProgram);
Here are some pictures of the cube rotating.
In the shader code I just multiply the transformation by the position (with the transformation being on the left).
I am not sure if it's helpful but here is the rotation code:
float c = cos(Angle);
float s = sin(Angle);
m4 R =
{
{{ c, 0, s, 0},
{ 0, 1, 0, 0},
{-s, 0, c, 0},
{ 0, 0, 0, 1}}
};
return R;
I tried multiplying the matricies in the shader code instead of on the c++ side but then everything disappeared.
OpenGL matrixes are stored with column major order. You have to read the columns from left to right. For example the 1st column of the matrix R is { c, 0, s, 0}, the 2nd one is { 0, 1, 0, 0} the 3rd is {-s, 0, c, 0} and the 4th is { 0, 0, 0, 1}. The lines in your code are actually columns (not rows).
Therefore you need to to transpose you projection matrix (Project) and translation matrix (Move).
I performed an MVP transformation on the vertices of the model. In theory, I must apply the inverse transpose matrix of the MVP transformation to the normal.
This is the derivation process:
(A, B, C) is the normal of the plane where the point (x, y, z) lies
For a vector, such as (x0, y0, z0), it is (x0, y0, z0, 0) in homogeneous coordinates. After transformation, it should still be a vector, like (x1, y1, z1, 0), This requires that the last row of the 4 * 4 transformation matrix is all 0 except for the elements in the last column, otherwise it will become (x1, y1, z1, n) after the transformation.
In fact, my MVP transformation matrix cannot satisfy this point after undergoing inverse transpose transformation.
Code:
Mat<4, 4> View(const Vec3& pos){
Mat<4, 4> pan{1, 0, 0, -pos.x,
0, 1, 0, -pos.y,
0, 0, 1, -pos.z,
0, 0, 0, 1};
Vec3 v = Cross(camera.lookAt, camera.upDirection).Normalize();
Mat<4, 4> rotate{v.x, v.y, v.z, 0,
camera.upDirection.x, camera.upDirection.y, camera.upDirection.z, 0,
-camera.lookAt.x, -camera.lookAt.y, -camera.lookAt.z, 0,
0, 0, 0, 1};
return rotate * pan;
}
Mat<4, 4> Projection(double near, double far, double fov, double aspectRatio){
double angle = fov * PI / 180;
double t = -near * tan(angle / 2);
double b = -t;
double r = t * aspectRatio;
double l = -r;
Mat<4, 4> zoom{2 / (r - l), 0, 0, 0,
0, 2 / (t - b), 0, 0,
0, 0, 2 / (near - far), 0,
0, 0, 0, 1};
Mat<4, 4> pan{1, 0, 0, -(l + r) / 2,
0, 1, 0, -(t + b) / 2,
0, 0, 1, -(near + far) / 2,
0, 0, 0, 1};
Mat<4, 4> extrusion{near, 0, 0, 0,
0, near, 0, 0,
0, 0, near + far, -near * far,
0, 0, 1, 0};
Mat<4, 4> ret = zoom * pan * extrusion;
return ret;
}
Mat<4, 4> modelMatrix = Mat<4, 4>::identity();
Mat<4, 4> viewMatrix = View(camera.position);
Mat<4, 4> projectionMatrix = Projection(-0.1, -50, camera.fov, camera.aspectRatio);
Mat<4, 4> mvp = projectionMatrix * viewMatrix * modelMatrix;
Mat<4, 4> mvpInverseTranspose = mvp.Inverse().Transpose();
mvp:
-2.29032 0 0.763441 -2.68032e-16
0 -2.41421 0 0
-0.317495 0 -0.952486 2.97455
0.316228 0 0.948683 -3.16228
mvpInverseTranspose:
-0.392957 0 0.130986 0
0 -0.414214 0 0
-4.99 0 -14.97 -4.99
-4.69377 0 -14.0813 -5.01
I seem to understand the problem. The lighting should be calculated in world space, so I only need to apply the inverse transpose matrix of the model transformation to the normal.
I am working with OpenGL and I am trying to make a simple ground class that draws a rectangle.
I have a class called Vertex:
class Vertex
{
public:
Vertex(
glm::vec3 _position,
glm::vec3 _color = glm::vec3(0.0, 0.0, 0.0),
glm::vec3 _normal = glm::vec3(0.0, 1.0, 0.0),
glm::vec3 _texture = glm::vec3(0.0, 0.0, 0.0));
void setNormal(glm::vec3 _normal);
void setTexture(glm::vec3 _texture);
virtual ~Vertex();
protected:
private:
glm::vec3 position;
glm::vec3 color;
glm::vec3 normal;
glm::vec3 texture;
};
And this is my Ground class:
class Ground
{
private:
double widht;
double length;
double y;
int* indexes;
Vertex* vertices;
public:
Ground(double _width, double_length, double y);
}
And here is what I want to do in the Ground constructor:
this->indexes = {0, 3, 1, 1, 3, 2};
this->vertices = {
Vertex(glm::vec3(0 - width/2, y, 0-length/2)),
Vertex(glm::vec3(0 - width/2, y, 0+length/2)),
Vertex(glm::vec3(0 + width/2, y, 0+length/2)),
Vertex(glm::vec3(0 + width/2, y, 0-length/2))
}
I am getting this error when compiling:
error: cannot convert ‘<brace-enclosed initializer list>’ to ‘Vertex*’
Now I know I could hard-code initialize all of this, but I want a solution for a general ClassX* array header definition and constructor initialization.
vertices is a Vertex pointer, rather than an array. You can either make the member variable an array of fixed size or create an array of type Vertex on the heap.
for the first way something like this:
const int NUM_VERTS = 4;
class Ground{
.
.
.
Vertex vertices[NUM_VERTS]
.
.
.
};
Or if you want several different Ground objects with varying number of vertices you can use templates, but this will cause a big code bloat and executable size. Not a good idea, but it is possible
template<size n>
class Ground{
.
.
.
Vertex vertices[n];
.
.
.
}
otherwise, of course
vertices = new Vertex[4];
vertices[0] = Vertex(glm::vec3(0 - width/2, y, 0-length/2));
//etc
.
.
.
Change indexes (indices) and vertices to be std::vector<int> and std::vector<Vertex> respectively. Then you can write:
Ground::Ground(double _width, double _length, double y)
: indexes{0, 3, 1, 1, 3, 2}
, vertices{
Vertex(glm::vec3(0 - width/2, y, 0-length/2)),
Vertex(glm::vec3(0 - width/2, y, 0+length/2)),
Vertex(glm::vec3(0 + width/2, y, 0+length/2)),
Vertex(glm::vec3(0 + width/2, y, 0-length/2))
}
{
}
I've been working on my Model Loader and I got an error because I use several structs with arrays (no vectors), I want to initialize the array before use it because the program gives me error when I try to use to access the vector array with brackets [].
GameObject struct:
struct GameObject
{
int ID, parent;
string tag;
Mesh_t Mesh;
Vector3 position;
Vector3 scale;
Quaternion rotation;
Color color;
};
Meshes struct:
struct Meshes_t
{
vector<GLfloat> VBO;
vector<GLfloat> VBO_Normal;
Texture_t Texture;
DWORD Geometry;
int VertexType;
};
struct Mesh_t
{
int VerticesCount;
int TexturesCount;
vector<Meshes_t> Faces;
};
And the problem is when I try to push_back to VBO vector array from "Meshes_t" like this:
GameObjects[GameObjectsCount].Mesh.Faces[k].VBO.push_back(vertex.x);
GameObjects[GameObjectsCount].Mesh.Faces[k].VBO.push_back(vertex.y);
GameObjects[GameObjectsCount].Mesh.Faces[k].VBO.push_back(vertex.z);
Due to Faces vector array is not initialized anywhere Visual Studio throws me a runtime error when the program reach the code below: this is the error https://gyazo.com/806e3426025ad3885f0d3ed0b7aa1d30
I tried to initialize the vector array but I don't know how to do it because the vector array has other struct inside and I can't push back struct data. Any ideas? Thanks in advance.
EDIT:
This is the gameobjects array from .h
extern struct GameObject GameObjects[1000];
and cpp is struct GameObject GameObjects[1000];
so I use this to create gameobject:
int teste = Entity.CreateEntity("data//models//cube.obj", Vector3(0, 25, 0), Quaternion(0, 0, 0), Vector3(0.51, 0.51, 0.51), -1);
and the int returned is what I use in GameObjects[ReturnedINT]
RENDER FUNCTION:
void GLRender ()
{
glBindTexture(GL_TEXTURE_2D, 0);
RenderSpaceLines();
drawLine(Vector3(0, 0, 0), GameObjects[0].position);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
for (int i = 0; i < Entity.GameObjectsCount; i++)
{
glBindTexture(GL_TEXTURE_2D, 0);
if (GameObjects[i].Mesh.TexturesCount > 0)
{
for (int t = 0; t < 10; t++)
{
glVertexPointer(3, GL_FLOAT, 0, (GLfloat*)GameObjects[i].Mesh.Faces[t].VBO.data());
glTexCoordPointer(2, GL_FLOAT, 0, (GLfloat*)GameObjects[i].Mesh.Faces[t].Texture.VBO.data());
glBindTexture(GL_TEXTURE_2D, TextureManager.GetTextureFromName(GameObjects[i].Mesh.Faces[t].Texture.TextureName));
glPushMatrix();
glPushAttrib(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
if (GameObjects[i].parent == -1)
{
glTranslatef(GameObjects[i].position.x, GameObjects[i].position.y, GameObjects[i].position.z);
glRotatef(GameObjects[i].rotation.x, 1, 0, 0);
glRotatef(GameObjects[i].rotation.y, 0, 1, 0);
glRotatef(GameObjects[i].rotation.z, 0, 0, 1);
}
else ///RELATIVITY OF ENTITY TO ANOTHER
{
glTranslatef(GameObjects[GameObjects[i].parent].position.x,
GameObjects[GameObjects[i].parent].position.y,
GameObjects[GameObjects[i].parent].position.z); ///SET WORLD RELATIVE POSITION
glRotatef(GameObjects[GameObjects[i].parent].rotation.x, 1, 0, 0);
glRotatef(GameObjects[GameObjects[i].parent].rotation.y, 0, 1, 0);
glRotatef(GameObjects[GameObjects[i].parent].rotation.z, 0, 0, 1);
glTranslatef(GameObjects[i].position.x,
GameObjects[i].position.y,
GameObjects[i].position.z);
}
glScalef(GameObjects[i].scale.x,
GameObjects[i].scale.y,
GameObjects[i].scale.z);
glDrawArrays(GameObjects[i].Mesh.Faces[t].Geometry, 0, GameObjects[i].Mesh.Faces[t].VertexType);
glPopMatrix();
}
}
}
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
Faces is actually initialized in the implicit default constructor of Mesh_t. But it will be empty. So, before accessing Faces[k] you must first put at least k + 1 elements into the vector. For example:
GameObjects[GameObjectsCount].Mesh.Faces.resize(k + 1);
GameObjects[GameObjectsCount].Mesh.Faces[k].VBO.push_back(vertex.x);
// ...
Also make sure that GameObjects has at least GameObjectsCount + 1 objects.
I'm trying to implement my custom opengl Rotation around y axix. Here is my code;
void mglRotateY(float angle)
{
float radians = angle * (PI/180);
GLfloat t[4][4] =
{
{cosf(angle), 0, -sinf(angle),0},
{0, 1, 0, 0},
{sinf(angle), 0, cosf(angle), 0},
{0, 0, 0, 1}
}; //Rotation matrix y
glMultMatrixf(*t);
}
The effect is a rotation around y axis, but the degrees seems to not correspond.
Does anyone know why?
Use radians not angle when calculating the sine and cosine.
In your code you reference angle instead of radian. Also you may want to precalc the values, as you have 4 calculations to populate the matrix t
perhaps something like
void mglRotateY(float angle)
{
float radians = angle * (PI/180);
float cosVal = cosf(radians);
float sinVal = sinf(radians);
GLfloat t[4][4] =
{
{cosVal, 0, -sinVal,0},
{0, 1, 0, 0},
{sinVal, 0, cosVal, 0},
{0, 0, 0, 1}
}; //Rotation matrix y
glMultMatrixf(*t);
}