PDA

View Full Version : Deforming a 3d Cube

LarrySellers
09-11-2014, 08:32 PM
Hey guys,

I'm trying to draw a 3D cube and then deform it using matrices. I've managed
to draw the cube, get it rotating, and even shear it. But I want to bend, twist,
and taper the object.

I know the matrix operations needed to do these, but I can't figure out how
to execute it in code. My algorithm for twisting is

cos(theta(y))
0
sin(theta(y))
0

0
1
0
0

-sin(theta(y))
0
cos(theta(y))
0

0
0
0
1

times the vector containing x, y, z, w.

However I can't figure out how to get the current vector for x, y, z, w
so that I can get the y value. I am assuming that I just use glMultMatrixf
to multiply the current matrix by the matrix mentioned about, right?
I used an array of vertices and glVertexPointer to feed these vertices
into glDrawArrays.

LarrySellers
09-12-2014, 10:40 PM
So I've figured out how to do it, I think. But I seem to have run into a problem.

Here is my program:

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include<glm/glm.hpp>
#include <iostream>

#define WIDTH 600
#define HEIGHT 480
#define TIME_BETWEEN_TRANSFORMATIONS 7

using std::cerr;
using std::cout;
using glm::mat4;
using glm::vec4;

GLFWwindow* initializeWindow(const int width, const int height)
{
//Initialize GLFW, and return NULL if glfwInit fails
if (!glfwInit())
{
cerr << "Failed to initialize GLFW.\n";
return NULL;
}

//Sets glfwWindowHint vaules
glfwWindowHint(GLFW_SAMPLES, 4); // 4x antialiasing

GLFWwindow* window = glfwCreateWindow(width, height, "Assignment 1", NULL, NULL);

if (window == NULL)
{
cerr << "Failed to create window.\n";
return NULL;
}

glfwMakeContextCurrent(window);

glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glDisable(GL_CULL_FACE);
glCullFace(GL_BACK);
return window;

}

void drawCube()
{
GLfloat vertices[] =
{
-1, -1, -1, 1, -1, -1, 1, 1, -1, 1, 1, 1, -1, 1, -1, 1,
1, -1, -1, 1, 1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, 1,
-1, -1, -1, 1, -1, -1, 1, 1, 1, -1, 1, 1, 1, -1, -1, 1,
-1, 1, -1, 1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, 1,
-1, -1, -1, 1, -1, 1, -1, 1, 1, 1, -1, 1, 1, -1, -1, 1,
-1, -1, 1, 1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, 1, 1
};

GLfloat colors[] =
{
0.f, 0.5f, 0.2f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.f, 0.5f, 0.3f, 0.6f,
1.f, 0.5f, 0.3f, 0.2f, 1.f, 0.6f, 0.f, 1.f, 1.f, 0.f, 0.9f, 0.1f,
0.f, 0.f, 0.f, 0.1f, 0.9f, 1.f, 1.f, 1.f, 0.f, 0.5f, 0.6f, 0.f,
0.6f, 0.5f, 0.6f, 0.8f, 0.9f, 0.2f, 0.3f, 0.2f, 1.f, 0.f, 0.8f, 0.f,
0.f, 0.5f, 0.2f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.f, 0.5f, 0.3f, 0.6f,
1.f, 0.5f, 0.3f, 1.f, 1.f, 1.f, 1.f, 0.7f, 1.f, 0.f, 0.9f, 0.1f
};

static float rotation = 0;

glRotatef(rotation, 0.1f, 1.0f, 0.3f);

glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glVertexPointer(4, GL_FLOAT, 0, vertices);
glColorPointer(3, GL_FLOAT, 0, colors);

glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
rotation += 0.15f;
}

int transformationType(float currentTime, float rotateTime, float shearTime, float taperTime, float twistTime, float bendTime)
{
if (currentTime < rotateTime) return 0;
if (currentTime < shearTime) return 1;
if (currentTime < taperTime) return 2;
if (currentTime < twistTime) return 3;
if (currentTime < bendTime) return 4;
else return 0;
}

void drawShearedCube()
{
GLfloat vertices[] =
{
-1, -1, -1, -1, -1, 1, -1, 1, 1, -1, 1, -1,
1, -1, -1, 1, -1, 1, 1, 1, 1, 1, 1, -1,
-1, -1, -1, -1, -1, 1, 1, -1, 1, 1, -1, -1,
-1, 1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1,
-1, -1, -1, -1, 1, -1, 1, 1, -1, 1, -1, -1,
-1, -1, 1, -1, 1, 1, 1, 1, 1, 1, -1, 1
};

GLfloat colors[] =
{
0.f, 0.5f, 0.2f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.f, 0.5f, 0.3f, 0.6f,
1.f, 0.5f, 0.3f, 0.2f, 1.f, 0.6f, 0.f, 1.f, 1.f, 0.f, 0.9f, 0.1f,
0.f, 0.f, 0.f, 0.1f, 0.9f, 1.f, 1.f, 1.f, 0.f, 0.5f, 0.6f, 0.f,
0.6f, 0.5f, 0.6f, 0.8f, 0.9f, 0.2f, 0.3f, 0.2f, 1.f, 0.f, 0.8f, 0.f,
0.f, 0.5f, 0.2f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.f, 0.5f, 0.3f, 0.6f,
1.f, 0.5f, 0.3f, 1.f, 1.f, 1.f, 1.f, 0.7f, 1.f, 0.f, 0.9f, 0.1f
};

static float rotation = 0;

glRotatef(rotation, 0.1f, 1.0f, 0.3f);

glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, vertices);
glColorPointer(3, GL_FLOAT, 0, colors);

float m[] = {
1, 0, 0, 0,
.3, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1 };
glMultMatrixf(m);

glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
rotation += 0.1f;
}

void drawTwistedCube()
{
GLfloat vertices[] =
{
-1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f,
1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f,
-1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f,
-1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f,
-1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f,
-1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f
};

GLfloat colors[] =
{
0.f, 0.5f, 0.2f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.f, 0.5f, 0.3f, 0.6f,
1.f, 0.5f, 0.3f, 0.2f, 1.f, 0.6f, 0.f, 1.f, 1.f, 0.f, 0.9f, 0.1f,
0.f, 0.f, 0.f, 0.1f, 0.9f, 1.f, 1.f, 1.f, 0.f, 0.5f, 0.6f, 0.f,
0.6f, 0.5f, 0.6f, 0.8f, 0.9f, 0.2f, 0.3f, 0.2f, 1.f, 0.f, 0.8f, 0.f,
0.f, 0.5f, 0.2f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.f, 0.5f, 0.3f, 0.6f,
1.f, 0.5f, 0.3f, 1.f, 1.f, 1.f, 1.f, 0.7f, 1.f, 0.f, 0.9f, 0.1f
};

int i = 0;
while (i < 71)
{
vec4 tempVector = vec4(vertices[i], vertices[i + 1], vertices[i + 2], vertices[i + 3]);
mat4 twistMatrix = mat4(2.0f, 0.0f, 0.0f, 0.0f, 0.0f, 2.0f, 0.0f, 0.0f, 0.0f, 0.0f, 2.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f);
//mat4 twistMatrix = mat4(cos(.2*vertices[i + 1]), 0, sin(.2*vertices[i + 1]), 0, 0, 1, 0, 0, -sin(.2*vertices[i + 1]),
//0, cos(.2*vertices[i + 1]), 0, 0, 0, 0, 1);

tempVector = twistMatrix * tempVector;

vertices[i] = tempVector[0];
vertices[i + 1] = tempVector[1];
vertices[i + 2] = tempVector[2];
vertices[i + 3] = tempVector[3];

i = i + 4;
}

cout << "START";
for (int i = 0; i < 72; i++)
{
cout << vertices[i];
if ((i % 4) == 3) cout << "\n";
}

static float rotation = 0;

glRotatef(rotation, 0.1f, 1.0f, 0.3f);

glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glVertexPointer(4, GL_FLOAT, 0, vertices);
glColorPointer(3, GL_FLOAT, 0, colors);

glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
rotation += 0.1f;
}

void display(GLFWwindow* window)
{
//Sets up time variables
float startTime, rotateTime, shearTime, taperTime, twistTime, bendTime;
startTime = glfwGetTime();
rotateTime = startTime + TIME_BETWEEN_TRANSFORMATIONS;
shearTime = rotateTime + TIME_BETWEEN_TRANSFORMATIONS;
taperTime = shearTime + TIME_BETWEEN_TRANSFORMATIONS;
twistTime = taperTime + TIME_BETWEEN_TRANSFORMATIONS;
bendTime = twistTime + TIME_BETWEEN_TRANSFORMATIONS;

float translateValue = 0;

while (!glfwWindowShouldClose(window))
{
// Scale to window size
GLint windowWidth, windowHeight;
glfwGetWindowSize(window, &windowWidth, &windowHeight);
glViewport(0, 0, windowWidth, windowHeight);

// Draw stuff
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glMatrixMode(GL_PROJECTION_MATRIX);
gluPerspective(70, (double)windowWidth / (double)windowHeight, 0.1, 100);

glMatrixMode(GL_MODELVIEW_MATRIX);
glTranslatef(0, 0, translateValue);

switch (transformationType(glfwGetTime(), rotateTime, shearTime, taperTime, twistTime, bendTime))
{
case 0:
drawCube();
break;
case 1:
drawTwistedCube();
break;
case 2:
drawCube();
break;
case 3:
drawCube();
break;
case 4:
drawTwistedCube();
break;
}

// Update Screen
glfwSwapBuffers(window);

// Check for any input, or window movement
glfwPollEvents();

if (translateValue > -5)
translateValue -= 0.001f;
}
}

int main()
{
GLFWwindow* window = initializeWindow(WIDTH, HEIGHT);
if (window != NULL)
{
display(window);
}
glfwDestroyWindow(window);
glfwTerminate();
return 0;
}

when I run drawTwistedCube() which, as it stands now should just scale the cube by a factor of 2,
it leaves 2 sides un-scaled and I can't figure out why. Can anyone help me figure out why this is?

Thanks!

carsten neumann
09-13-2014, 01:54 AM
#faces * #vertices per face * #floats per vertex = 6 * 4 * 4 = 96
In other words: your loop bounds are too small and you are not transforming all positions.

LarrySellers
09-14-2014, 11:19 AM
Ooooh okay. Thanks. I turned the matrix into 4 points per vertex instead of 3 and forgot to increase the size of the loop accordingly.
One thing I don't understand though, is the value placed in:

I tried messing around with the value placed as the third argument and it seemed
to make little difference unless the number I provided was less than 24. But when
I changed my vertices to contain 4 numbers instead of 3, 24 was still sufficient.
Can anyone explain that to me? I tried reading the documentation and was still
confused afterwards.

carsten neumann
09-14-2014, 11:50 AM
Your cube has 24 vertices, independent of how many components the vectors to specify the positions have. Using a number larger than 24 means you are reading off the end of your arrays and just happen to be lucky that it does not crash/render garbage/melt your computer (the latter is a rare case though ;) ) - still it's a bug to tell OpenGL to render more vertices than you have data available for.

LarrySellers
09-14-2014, 12:05 PM
Your cube has 24 vertices, independent of how many components the vectors to specify the positions have. Using a number larger than 24 means you are reading off the end of your arrays and just happen to be lucky that it does not crash/render garbage/melt your computer (the latter is a rare case though ;) ) - still it's a bug to tell OpenGL to render more vertices than you have data available for.

Ooh, that makes sense. Thanks!