I'm translating my object with glTranslate to an other location. But the problem is that the normals stay at the old position. How can i translate them together with the object vertices.
I read about using the transpose of the inverse modelview matrix. But this is not working. It stretches out my whole model. I have left this code commented under need //translate normals
//Rotate model because Z axes is up
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glTranslatef(4, 4, 0.7);
glRotatef(90, 1.0, 0, 0);
//translate normals
//glGetDoublev(GL_MODELVIEW_MATRIX, matrix);
//printMatrix(matrix);
//inverse(matrix, inverseM);
//transpose(inverseM);
//printMatrix(inverseM);
//glMultMatrixd(inverseM);
glBegin(GL_TRIANGLES);
for (int i = 0; i<triangles.size(); ++i)
{
Vec3Df edge01 = vertices[triangles[i].v[1]].p - vertices[triangles[i].v[0]].p;
Vec3Df edge02 = vertices[triangles[i].v[2]].p - vertices[triangles[i].v[0]].p;
Vec3Df n = Vec3Df::crossProduct(edge01, edge02);
n.normalize();
glNormal3f(n[0], n[1], n[2]);
for (int v = 0; v < 3; v++) {
//color
if (triangles[i].v[v] < meshColor.size()) {
glColor3f(meshColor[triangles[i].v[v]].p[0], meshColor[triangles[i].v[v]].p[1], meshColor[triangles[i].v[v]].p[2]);
glVertex3f(vertices[triangles[i].v[v]].p[0], vertices[triangles[i].v[v]].p[1], vertices[triangles[i].v[v]].p[2]);
}
}
}
glEnd();
glPopMatrix();
Related
Im trying to scale and rotate 10 squares to fit inside each other recursively at a rotation angle of 45 in OpenGl. my output should look like this.
my current code is this
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glBindVertexArray(vao);
scale = 1.0f;
angle = 45.0f;
for (int i = 0; i < 10; i++)
{
transformObject(scale -=0.156f, Z_AXIS, angle -= 45.0f, glm::vec3(0.0f, 0.0f, 0.0f));
glDrawArrays(GL_LINE_LOOP, 0, 4);
}
The size of the square gets smaller by the scale 1/sqrt(2) with each iteration of the loop. The outer rectangle is not transformed. The outer rectangle is not transformed. Change the scale and angle at the end of the loop:
scale = 1.0f;
angle = 0.0f;
for (int i = 0; i < 10; i++)
{
transformObject(scale, Z_AXIS, angle, glm::vec3(0.0f));
glDrawArrays(GL_LINE_LOOP, 0, 4);
scale = 1.0f/sqrt(2.0f);
angle -= 45.0f;
}
I am trying to create 5x5x5 cubes for my game. Right now, I have this code which shows only one cube in the camera view. Obviously, it is "inserted" only one time.
void onIdle() override {
// Animate using time when activated
if (animationEnabled) time = (float) glfwGetTime();
// Set gray background
glClearColor(.5f, .5f, .5f, 0);
// Clear depth and color buffers
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Create object matrices
auto cubeMat = rotate(mat4{}, time, {1.0f, 1.0f, 0.0f});
//auto cubeMat = mat4(1.0f);
auto sphereMat = rotate(mat4{}, (float)time, {0.5f, 1.0f, 0.0f});
cubeMat = scale(cubeMat, {0.2f, 0.2f, 0.2f});
// Camera position/rotation - for example, translate camera a bit backwards (positive value in Z axis), so we can see the objects
auto cameraMat = translate(mat4{}, {0, 0, -4.0f});
program.setUniform("ViewMatrix", cameraMat);
// Update camera position with perspective projection
program.setUniform("ProjectionMatrix", perspective((PI / 180.f) * 60.0f, 1.0f, 0.1f, 10.0f));
program.setUniform("LightDirection", normalize(vec3{1.0f, -1.0f, 1.0f}));
// Render objects
// Central box
program.setUniform("Texture", cubeTexture);
for (int i = 0; i < 5*5*5; ++i)
{
program.setUniform("ModelMatrix", cubeMat[i]);
cube.render();
}
}
};
How can I generate 5x5x5 cubes so I don't have to manually insert them so many times? Also, every insertion should give each cube its specific location to create a big 3D cube full of little 5x5x5 cubes (like rubik's cube) or even better, here is a good example.
You need a function which generates a model matrix for an individual cube:
mat4 CubeMat( int x, int y, int z )
{
mat4 cubeMat;
//cubeMat = rotate(cubeMat, time, {1.0f, 1.0f, 0.0f});
//cubeMat = scale(cubeMat, {0.2f, 0.2f, 0.2f});
cubeMat = translate(cubeMat, {1.5f*(float)x-4.0f, 1.5f*(float)y-4.0f, 1.5f*(float)z-4.0f});
return cubeMat;
}
You have to call cube.render(); 5*5*5 times and you have to set 5*5*5 idividual model matrices:
for (int x = 0; x < 5; ++x)
{
for (int y = 0; y < 5; ++y)
{
for (int z = 0; z < 5; ++z)
{
mat4 cubeMat = CubeMat(x, y, z);
program.setUniform("ModelMatrix", cubeMat);
cube.render();
}
}
}
I am using vertex arrays to store circle vertices and colors.
Here is the setup function:
void setup1(void)
{
glClearColor(1.0, 1.0, 1.0, 0.0);
// Enable two vertex arrays: co-ordinates and color.
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
// Specify locations for the co-ordinates and color arrays.
glVertexPointer(3, GL_FLOAT, 0, Vertices1);
glColorPointer(3, GL_FLOAT, 0, Colors1);
}
The global declaration of the arrays is here:
static float Vertices1[500] = { 0 };
static float Colors1[500] = { 0 };
The arrays are all set up here (R is the radius, X and Y are the (X,Y) center, and t is the angle parameter of the circle)
void doGlobals1()
{
for (int i = 0; i < numVertices1 * 3; i += 3)
{
Vertices1[i] = X + R * cos(t);
Vertices1[i + 1] = Y + R * sin(t);
Vertices1[i + 2] = 0.0;
t += 2 * PI / numVertices1;
}
for (int j = 0; j < numVertices1 * 3; j += 3)
{
Colors1[j] = (float)rand() / (float)RAND_MAX;
Colors1[j + 1] = (float)rand() / (float)RAND_MAX;
Colors1[j + 2] = (float)rand() / (float)RAND_MAX;
}
}
Finally, this is where the shape is drawn.
// Window 1 drawing routine.
void drawScene1(void)
{
glutSetWindow(win1);
glLoadIdentity();
doGlobals1();
glClear(GL_COLOR_BUFFER_BIT);
glRotatef(15, 1, 0, 0);
glDrawArrays(GL_TRIANGLE_FAN, 0, numVertices1);
glFlush();
}
Without the Rotation, the circle draws just fine. The circle also draws fine with any Scale/Translate function. I suspect there is some special protocol necessary to rotate an object drawn with vertex arrays.
Can anyone tell me where I have gone wrong, what I will need to do in order to rotate the object, or offer any advice?
glRotatef(15, 1, 0, 0);
^ why the X axis?
The default ortho projection matrix has pretty tight near/far clipping planes: -1 to 1.
Rotating your circle of X/Y coordinates outside of the X/Y plane will tend to make those points get clipped.
Rotate around the Z axis instead:
glRotatef(15, 0, 0, 1);
I am trying to make a tank game. I have successfully loaded an OBJ model, and calculated its bounding box for the model at the origin.
I am now trying to apply the transformations done to my model in the game logic to the original coordinates for the bounding box. For this, I grab the modelview matrix right before drawing my model, then multiply this matrix for the two vectors that define the BBox.
Here is the code that draws my tank:
void drawTank()
{
bBox = calcBBox(modelo, 1);
glPushMatrix();
glBindTexture(GL_TEXTURE_2D, texTank);
glScalef(0.2, 0.2, 0.2);
glTranslatef(posTank.x,posTank.y,posTank.z);
glRotatef(anguloTanque, 0, 1, 0); // rotate around Y (horizontal)
glRotatef(90, 0, 1, 0);
glRotatef(-90, 1, 0, 0);
glGetFloatv(GL_MODELVIEW_MATRIX, matrix);
glmDraw(modelo, GLM_TEXTURE | GLM_MATERIAL);
glColor3f(1,0,0);
drawBBox(bBox);
glPopMatrix();
}
With this snippet, my bbox is properly drawn over the tank model (transformations are applied in rendering by the glTranslate & glRotate functions). As you can see I also grab here my ModelView matrix.
Then I apply this matrix as follows (this is my entire display function):
void Display(void) {
// Clear the window with current clearing color
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glPushMatrix();
camera();
glEnable(GL_TEXTURE_2D);
//glTranslatef(0,-40,150);
//PLANE
glBindTexture(GL_TEXTURE_2D, texArena);
glBegin(GL_POLYGON);
glTexCoord2f( 0.0f, 0.0f );
glVertex3f(-500, 0, -500);
glTexCoord2f( 5.0f, 5.0f );
glVertex3f(500, 0, -500);
glTexCoord2f(5.0f, 0.0f );
glVertex3f(500, 0, 500);
glTexCoord2f( 0.0f, 5.0f );
glVertex3f(-500, 0, 500);
glEnd();
drawTank();
glPopMatrix();
point3D max = bBox.max;
point3D min = bBox.min;
point3D resultMax;
point3D resultMin;
//Transformacion
multVectorByMatrix(matrix, max, resultMax);
multVectorByMatrix(matrix, min, resultMin);
bBox.max.x = resultMax.x; bBox.max.y = resultMax.y; bBox.max.z = resultMax.z;
bBox.min.x = resultMin.x; bBox.min.y = resultMin.y; bBox.min.z = resultMin.z;
glPushMatrix();
glColor3f(1,1,1);
drawBBox(bBox);
glPopMatrix();
glFlush();
glutSwapBuffers();
}
The function that multiplies a vector by a matrix:
void multVectorByMatrix(float* matrix, point3D vector, point3D &result)
{
result.x = (matrix[0] * vector.x) +
(matrix[4] * vector.y) +
(matrix[8] * vector.z) +
matrix[12];
result.y = (matrix[1] * vector.x) +
(matrix[5] * vector.y) +
(matrix[9] * vector.z) +
matrix[13];
result.z = (matrix[2] * vector.x) +
(matrix[6] * vector.y) +
(matrix[10] * vector.z) +
matrix[14];
}
If I draw the bounding box with this render loop, then my bounding box gets drawn but transformations are not applied properly. I can see the bounding box moving correctly with translations, but rotations are not done right.
What might be the problem here?
edit: some screenshots
Your problem is in this code.
point3D max = bBox.max;
point3D min = bBox.min;
point3D resultMax;
point3D resultMin;
//Transformacion
multVectorByMatrix(matrix, max, resultMax);
multVectorByMatrix(matrix, min, resultMin);
bBox.max.x = resultMax.x; bBox.max.y = resultMax.y; bBox.max.z = resultMax.z;
bBox.min.x = resultMin.x; bBox.min.y = resultMin.y; bBox.min.z = resultMin.z;
glPushMatrix();
glColor3f(1,1,1);
drawBBox(bBox);
glPopMatrix();
You take two vertices from your box and then apply transformations to them, then you use this transformed vertices to display a box, which of course will be axis aligned, because that's the only box you can get from just two opposite vertices. And you can see on your screenshot, that you bbox and the correct bbox have common vertices - these are exactly the vertices you applied your transformations to. So, in order to get a correct bbox, you need to get all vertices of the bbox and apply these transformations to all of them. Then you'll get exactly what you want.
I'm trying to make a light source rotate around my character model in my OpenGL project, but as I try it, all I got so far is my model rotating like crazy (or the floor).
My rendering code looks like this:
void mainRender() {
updateState();
renderScene();
glFlush();
glutPostRedisplay();
//spin = (spin + 30) % 360;
Sleep(30);
}
void renderScene() {
glClearColor(backgrundColor[0],backgrundColor[1],backgrundColor[2],backgrundColor[3]);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // limpar o depth buffer
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
updateCam();
renderFloor();
modelAL.Translate(0.0f,1.0f,0.0f);
modelAL.Draw();
}
void renderFloor() {
// set things up to render the floor with the texture
glShadeModel(GL_SMOOTH);
glEnable(type);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glPushMatrix();
glTranslatef(-(float)planeSize/2.0f, 0.0f, -(float)planeSize/2.0f);
float textureScaleX = 10.0;
float textureScaleY = 10.0;
glColor4f(1.0f,1.0f,1.0f,1.0f);
int xQuads = 40;
int zQuads = 40;
for (int i = 0; i < xQuads; i++) {
for (int j = 0; j < zQuads; j++) {
glBegin(GL_QUADS);
glTexCoord2f(1.0f, 0.0f); // coords for the texture
glNormal3f(0.0f,1.0f,0.0f);
glVertex3f(i * (float)planeSize/xQuads, 0.0f, (j+1) * (float)planeSize/zQuads);
glTexCoord2f(0.0f, 0.0f); // coords for the texture
glNormal3f(0.0f,1.0f,0.0f);
glVertex3f((i+1) * (float)planeSize/xQuads, 0.0f, (j+1) * (float)planeSize/zQuads);
glTexCoord2f(0.0f, 1.0f); // coords for the texture
glNormal3f(0.0f,1.0f,0.0f);
glVertex3f((i+1) * (float)planeSize/xQuads, 0.0f, j * (float)planeSize/zQuads);
glTexCoord2f(1.0f, 1.0f); // coords for the texture
glNormal3f(0.0f,1.0f,0.0f);
glVertex3f(i * (float)planeSize/xQuads, 0.0f, j * (float)planeSize/zQuads);
glEnd();
}
}
glDisable(type);
glPopMatrix();
}
How could I make this new lightsource rotate around my "modelAL" object?
For the fixed pipeline, light source position assigned with glLight() are transformed with the model-view matrix, just as normal objects are. So you can use the transformation functions to position and rotate your light source as you would normal objects.
To rotate a light source (or other object) around a point, you need to follow these steps. Let L be where the light source will be when the rotation is 0 degrees, and O be the subject - the object around which you want to rotate the light source.
Position the light source at L-O (the position of the light source relative to the subject)
Rotate it about the required axis (probably the Y axis)
Translate it by O to move it into position.
Because of the way OpenGL works, you essentially do these in backwards order. Basically it would go like this:
glPushMatrix();
glTranslatef(O.x,O.y,O.z);
glRotate(angle,0,1,0);
GLfloat lightpos[4] = {L.x-O.x,L.y-O.y,L.z-O.z,1};
glLightfv(GL_LIGHT0,GL_POSITION,lightpos);
glPopMatrix();
Note, this only applies to positioned light sources, not directional ones i.e. with w=0.