I am taking a computer graphics class that teaches us how to use OpenGL with the glut libraries. I have an idea for a final project that involves lighting and textures being put on a dinosaur model that I found online. My first step is to simplify the existing online code so I can begin working on my project.
Unfortunately, the online code for this model is broken, and I cannot seem to figure it out. I am not sure what gluTessCallback does, but my program is very upset with two lines of this code that is making it impossible to run this program on Visual Studio 2012.
Below is the code, and I have indicated which two lines are giving me the trouble.
typedef enum {
RESERVED, BODY_SIDE, BODY_EDGE, BODY_WHOLE, ARM_SIDE, ARM_EDGE, ARM_WHOLE,
LEG_SIDE, LEG_EDGE, LEG_WHOLE, EYE_SIDE, EYE_EDGE, EYE_WHOLE, DINOSAUR
} displayLists;
GLfloat angle = -150; /* in degrees */
GLboolean doubleBuffer = GL_TRUE, iconic = GL_FALSE, keepAspect = GL_FALSE;
int moving, begin;
int W = 300, H = 300;
GLdouble bodyWidth = 2.0;
int newModel = 1;
GLfloat body[][2] = { { 0, 3 },{ 1, 1 },{ 5, 1 },{ 8, 4 },{ 10, 4 },{ 11, 5 },
{ 11, 11.5 },{ 13, 12 },{ 13, 13 },{ 10, 13.5 },{ 13, 14 },{ 13, 15 },{ 11, 16 },
{ 8, 16 },{ 7, 15 },{ 7, 13 },{ 8, 12 },{ 7, 11 },{ 6, 6 },{ 4, 3 },{ 3, 2 },
{ 1, 2 } };
GLfloat arm[][2] = { { 8, 10 },{ 9, 9 },{ 10, 9 },{ 13, 8 },{ 14, 9 },{ 16, 9 },
{ 15, 9.5 },{ 16, 10 },{ 15, 10 },{ 15.5, 11 },{ 14.5, 10 },{ 14, 11 },{ 14, 10 },
{ 13, 9 },{ 11, 11 },{ 9, 11 } };
GLfloat leg[][2] = { { 8, 6 },{ 8, 4 },{ 9, 3 },{ 9, 2 },{ 8, 1 },{ 8, 0.5 },{ 9, 0 },
{ 12, 0 },{ 10, 1 },{ 10, 2 },{ 12, 4 },{ 11, 6 },{ 10, 7 },{ 9, 7 } };
GLfloat eye[][2] = { { 8.75, 15 },{ 9, 14.7 },{ 9.6, 14.7 },{ 10.1, 15 },
{ 9.6, 15.25 },{ 9, 15.25 } };
GLfloat lightZeroPosition[] = { 10.0, 4.0, 10.0, 1.0 };
GLfloat lightZeroColor[] = { 0.8, 1.0, 0.8, 1.0 }; /* green-tinted */
GLfloat lightOnePosition[] = { -1.0, -2.0, 1.0, 0.0 };
GLfloat lightOneColor[] = { 0.6, 0.3, 0.2, 1.0 }; /* red-tinted */
GLfloat skinColor[] = { 0.1, 1.0, 0.1, 1.0 }, eyeColor[] = { 1.0, 0.2, 0.2, 1.0 };
void
extrudeSolidFromPolygon(GLfloat data[][2], unsigned int dataSize,
GLdouble thickness, GLuint side, GLuint edge, GLuint whole)
{
static GLUtriangulatorObj *tobj = NULL;
GLdouble vertex[3], dx, dy, len;
int i;
int count = dataSize / (int)(2 * sizeof(GLfloat));
if (tobj == NULL) {
tobj = gluNewTess(); /* create and initialize a GLU
polygon tesselation object */
/////////////////////////////////////////////////////////////////////////////////////////
// THESE LINES WILL NOT COMPILE. Says that the glBegin and glVertex2fv are incompatable.
gluTessCallback(tobj, GLU_BEGIN, glBegin);
gluTessCallback(tobj, GLU_VERTEX, glVertex2fv); /* semi-tricky */
/////////////////////////////////////////////////////////////////////////////////////////
gluTessCallback(tobj, GLU_END, glEnd);
}
glNewList(side, GL_COMPILE);
glShadeModel(GL_SMOOTH); /* smooth minimizes seeing
tessellation */
gluBeginPolygon(tobj);
/////////////////////////////////////////////////////////////////////////////////////////
// ALSO A PROBLEM WITH THIS SECTION OF CODE?
for (i = 0; i < count; i++) {
vertex[0] = data[i][0];
vertex[1] = data[i][1];
vertex[2] = 0;
gluTessVertex(tobj, vertex, data[i]);
}
gluEndPolygon(tobj);
glEndList();
/////////////////////////////////////////////////////////////////////////////////////////
glNewList(edge, GL_COMPILE);
glShadeModel(GL_FLAT); /* flat shade keeps angular hands
from being "smoothed" */
glBegin(GL_QUAD_STRIP);
for (i = 0; i <= count; i++) {
/* mod function handles closing the edge */
glVertex3f(data[i % count][0], data[i % count][1], 0.0);
glVertex3f(data[i % count][0], data[i % count][1], thickness);
/* Calculate a unit normal by dividing by Euclidean
distance. We * could be lazy and use
glEnable(GL_NORMALIZE) so we could pass in * arbitrary
normals for a very slight performance hit. */
dx = data[(i + 1) % count][1] - data[i % count][1];
dy = data[i % count][0] - data[(i + 1) % count][0];
len = sqrt(dx * dx + dy * dy);
glNormal3f(dx / len, dy / len, 0.0);
}
glEnd();
glEndList();
glNewList(whole, GL_COMPILE);
glFrontFace(GL_CW);
glCallList(edge);
glNormal3f(0.0, 0.0, -1.0); /* constant normal for side */
glCallList(side);
glPushMatrix();
glTranslatef(0.0, 0.0, thickness);
glFrontFace(GL_CCW);
glNormal3f(0.0, 0.0, 1.0); /* opposite normal for other side */
glCallList(side);
glPopMatrix();
glEndList();
}
void
makeDinosaur(void)
{
GLfloat bodyWidth = 3.0;
extrudeSolidFromPolygon(body, sizeof(body), bodyWidth,
BODY_SIDE, BODY_EDGE, BODY_WHOLE);
extrudeSolidFromPolygon(arm, sizeof(arm), bodyWidth / 4,
ARM_SIDE, ARM_EDGE, ARM_WHOLE);
extrudeSolidFromPolygon(leg, sizeof(leg), bodyWidth / 2,
LEG_SIDE, LEG_EDGE, LEG_WHOLE);
extrudeSolidFromPolygon(eye, sizeof(eye), bodyWidth + 0.2,
EYE_SIDE, EYE_EDGE, EYE_WHOLE);
glNewList(DINOSAUR, GL_COMPILE);
glMaterialfv(GL_FRONT, GL_DIFFUSE, skinColor);
glCallList(BODY_WHOLE);
glPushMatrix();
glTranslatef(0.0, 0.0, bodyWidth);
glCallList(ARM_WHOLE);
glCallList(LEG_WHOLE);
glTranslatef(0.0, 0.0, -bodyWidth - bodyWidth / 4);
glCallList(ARM_WHOLE);
glTranslatef(0.0, 0.0, -bodyWidth / 4);
glCallList(LEG_WHOLE);
glTranslatef(0.0, 0.0, bodyWidth / 2 - 0.1);
glMaterialfv(GL_FRONT, GL_DIFFUSE, eyeColor);
glCallList(EYE_WHOLE);
glPopMatrix();
glEndList();
}
void
recalcModelView(void)
{
glPopMatrix();
glPushMatrix();
glRotatef(angle, 0.0, 1.0, 0.0);
glTranslatef(-8, -8, -bodyWidth / 2);
newModel = 0;
}
void
redraw(void)
{
if (newModel)
recalcModelView();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glCallList(DINOSAUR);
glutSwapBuffers();
}
/* ARGSUSED2 */
void
mouse(int button, int state, int x, int y)
{
if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
moving = 1;
begin = x;
}
if (button == GLUT_LEFT_BUTTON && state == GLUT_UP) {
moving = 0;
}
}
/* ARGSUSED1 */
void
motion(int x, int y)
{
if (moving) {
angle = angle + (x - begin);
begin = x;
newModel = 1;
glutPostRedisplay();
}
}
GLboolean lightZeroSwitch = GL_TRUE, lightOneSwitch = GL_TRUE;
void
controlLights(int value)
{
switch (value) {
case 1:
lightZeroSwitch = !lightZeroSwitch;
if (lightZeroSwitch) {
glEnable(GL_LIGHT0);
}
else {
glDisable(GL_LIGHT0);
}
break;
case 2:
lightOneSwitch = !lightOneSwitch;
if (lightOneSwitch) {
glEnable(GL_LIGHT1);
}
else {
glDisable(GL_LIGHT1);
}
break;
}
glutPostRedisplay();
}
int
main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
glutCreateWindow("glutdino");
glutDisplayFunc(redraw);
glutMouseFunc(mouse);
glutMotionFunc(motion);
glutCreateMenu(controlLights);
glutAddMenuEntry("Toggle right light", 1);
glutAddMenuEntry("Toggle left light", 2);
glutAttachMenu(GLUT_RIGHT_BUTTON);
makeDinosaur();
glEnable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
glMatrixMode(GL_PROJECTION);
gluPerspective( /* field of view in degree */ 40.0,
/* aspect ratio */ 1.0,
/* Z near */ 1.0, /* Z far */ 40.0);
glMatrixMode(GL_MODELVIEW);
gluLookAt(0.0, 0.0, 30.0, /* eye is at (0,0,30) */
0.0, 0.0, 0.0, /* center is at (0,0,0) */
0.0, 1.0, 0.); /* up is in postivie Y direction */
glPushMatrix(); /* dummy push so we can pop on model
recalc */
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1);
glLightfv(GL_LIGHT0, GL_POSITION, lightZeroPosition);
glLightfv(GL_LIGHT0, GL_DIFFUSE, lightZeroColor);
glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 0.1);
glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 0.05);
glLightfv(GL_LIGHT1, GL_POSITION, lightOnePosition);
glLightfv(GL_LIGHT1, GL_DIFFUSE, lightOneColor);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHT1);
glutMainLoop();
return 0; /* ANSI C requires main to return int. */
}
I tried to make it clear where the problem is. OpenGl is bringing me to my wit's end. Is there nowhere I can get a simple 3D dinosaur model to play with on the internet?
I hope you can provide me some insight on this gluTessCallback issue so I can get this working. All I want is a solid dinosaur model.
Looking at the man page, the signature of the callback passed to gluTessCallback() depends on the enum value passed as the second argument. This means that if you're using C++, or a version of C that uses function prototypes, you will need a typecast to cast your function to the type expected by gluTessCallback().
According to the man page, the argument type is defined as _GLUfuncptr. However, that type is not defined in the glu.h header I found. The type according to the spec and header is a function with no arguments and a return type of GLvoid. You can define your own function type for this, and then cast to it:
typedef GLvoid (*TessFuncPtr)();
gluTessCallback(tobj, GLU_BEGIN, (TessFuncPtr)glBegin);
gluTessCallback(tobj, GLU_VERTEX, (TessFuncPtr)glVertex2fv);
If you're just learning OpenGL, you should be aware that almost all of the calls in this code are deprecated and obsolete. This includes:
Immediate mode rendering (glBegin, glEnd, etc).
Display lists.
Matrix stack.
Fixed function lighting and material definitions.
I think you would be much better off learning a current version of OpenGL. For example the tessellation functionality you are trying to use was defined close to 25 years ago. Aside from being deprecated, I don't think it was ever widely used in the first place.
Related
I have been experimenting with 3d projection for a while,
but I've always used vertexes in -1 1 range I want to use units that are 1pixel big, so I use glm::ortho(-width / 2, width / 2, -height/2, height, 0.1f, 10.0f);
but that doesn't work
heres the code with glm::ortho(-1.0f, 1.0f, -1.0f, 1.0f, 0.1f,1.0f):
#include "Engine.h"
#include "vendor/stb/stb_image.h"
float width = 1200;
float height = 750;
// edits in imgui files have farouk comment before them
int main(void)
{
initGLFW();
GLFWimage icon;
icon.pixels = stbi_load("data/Images/Icon.png", &icon.width, &icon.height, nullptr, 4);
GLFWimage image;
image.pixels = stbi_load("data/Images/Cursor.png", &image.width, &image.height, nullptr, 4);
GLFWcursor * cursor = glfwCreateCursor(&image, image.width / 2, image.height / 2);
glfwWindowHint(GLFW_SAMPLES, 6);
glEnable(GL_MULTISAMPLE);
Window window("OGL", width, height, MVP());
Renderer renderer;
renderer.GenerateFonts({"data/fonts/arial.ttf", "data/fonts/Pixelboy.ttf"}, {"arial", "roboto"}, {64, 64});
// set perspective projection & set xyz ranges from -1, 1 to respective ranges
window.mvp.projection = glm::ortho(-1.0f, 1.0f, -1.0f, 1.0f, 0.1f, 10.0f);
window.createWindow("data/Images/Cursor.png", "data/Images/Icon.png");
glfwSetWindowIcon(window.window, 1, &icon);
glfwSetCursor(window.window, cursor);
stbi_image_free(image.pixels);
stbi_image_free(icon.pixels);
glfwMakeContextCurrent(window.window);
initGLEW(true);
glDepthMask(GL_TRUE);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
renderer.loadFonts({"arial", "roboto"});
initImGUI(window.window, "data/fonts/arial.ttf");
Shader shader("data/shaders/base.shader");
// TODO: Add Multiple Window Support (Window Manager)
// Addd .txt file for text with Characters map insteadt loaf Fonts
// texture in 3d space & 3d textures
// map -1, 1 to -width/2 , width/2
std::vector <Obj> cubes = {
{
{
{ {-0.5, -0.5, -1.1}, {1,1,1,1} },
{ {-0.5, 0.5, -1.1}, {1,1,1,1} },
{ {0.5, 0.5, -1.1}, {1,1,1,1} },
{ {0.5, -0.5, -1.1}, {1,1,1,1} },
{ {-0.5, -0.5, -2.1}, {0,1,1,1} },
{ {-0.5, 0.5, -2.1}, {0,1,1,1} },
{ {0.5, 0.5, -2.1}, {0,1,1,1} },
{ {0.5, -0.5, -2.1}, {0,1,1,1} },
},
{
0,1,2, 2,3,0, 4,5,6, 6,7,4, 0,4,5, 1,5,0
},
true
}
};
float tx = 0;
float ty = 0;
float tz = 0;
while (!glfwWindowShouldClose(window.window) )
{
glfwMakeContextCurrent(window.window);
renderer.Clear({0.0, 0.0, 0.0, 1});
// feed inputs to dear imgui, start new frame
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame();
renderer.Draw(shader, window.mvp, cubes);
window.mvp.view = glm::translate(glm::mat4(1), glm::vec3(0, 0, -1.6)) * glm::rotate(glm::mat4(1), glm::radians(tx), glm::vec3(1,0,0)) * glm::rotate(glm::mat4(1), glm::radians(ty), glm::vec3(0,1,0)) * glm::rotate(glm::mat4(1), glm::radians(tz), glm::vec3(0,0,1));
window.mvp.view = glm::translate(window.mvp.view, glm::vec3(0, 0, 1.6));
renderer.Text(shader, MVP(glm::mat4(1.0), glm::mat4(1.0),glm::ortho(0.0, (double)width, 0.0, (double)height)), {(TextObj){"roboto", "FPS:" + std::to_string((int)ImGui::GetIO().Framerate), 0.01424501424f * height, 0.01424501424f * height, 0, 0.02849002849f * height, 0, {1,1,1,1}}});
// render your GUI
ImGui::Begin("Demo window");
ImGui::Button("Hello!");
ImGui::SliderFloat("x", &tx, 0, 360, "%.0f", 1.0f);
ImGui::SliderFloat("y", &ty, 0, 360, "%.0f", 1.0f);
ImGui::SliderFloat("z", &tz, 0, 360, "%.0f", 1.0f);
ImGui::End();
// Render dear imgui into screen
ImGui::Render();
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
int display_w, display_h;
glfwGetFramebufferSize(window.window, &display_w, &display_h);
glViewport(0, 0, display_w, display_h);
glfwSwapBuffers(window.window);
glfwSwapInterval(1);
glfwPollEvents();
}
ImGui_ImplOpenGL3_Shutdown();
ImGui_ImplGlfw_Shutdown();
ImGui::DestroyContext();
return 0;
}
and the output:
and heres the code with glm::ortho(-width / 2, width / 2, -height/2, height, 0.1f, 10.0f):
#include "Engine.h"
#include "vendor/stb/stb_image.h"
float width = 1200;
float height = 750;
// edits in imgui files have farouk comment before them
int main(void)
{
initGLFW();
GLFWimage icon;
icon.pixels = stbi_load("data/Images/Icon.png", &icon.width, &icon.height, nullptr, 4);
GLFWimage image;
image.pixels = stbi_load("data/Images/Cursor.png", &image.width, &image.height, nullptr, 4);
GLFWcursor * cursor = glfwCreateCursor(&image, image.width / 2, image.height / 2);
glfwWindowHint(GLFW_SAMPLES, 6);
glEnable(GL_MULTISAMPLE);
Window window("OGL", width, height, MVP());
Renderer renderer;
renderer.GenerateFonts({"data/fonts/arial.ttf", "data/fonts/Pixelboy.ttf"}, {"arial", "roboto"}, {64, 64});
// set perspective projection & set xyz ranges from -1, 1 to respective ranges
window.mvp.projection = glm::ortho(-width / 2, width / 2, -height/2, height, 0.1f, 10.0f);
window.createWindow("data/Images/Cursor.png", "data/Images/Icon.png");
glfwSetWindowIcon(window.window, 1, &icon);
glfwSetCursor(window.window, cursor);
stbi_image_free(image.pixels);
stbi_image_free(icon.pixels);
glfwMakeContextCurrent(window.window);
initGLEW(true);
glDepthMask(GL_TRUE);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
renderer.loadFonts({"arial", "roboto"});
initImGUI(window.window, "data/fonts/arial.ttf");
Shader shader("data/shaders/base.shader");
// TODO: Add Multiple Window Support (Window Manager)
// Addd .txt file for text with Characters map insteadt loaf Fonts
// texture in 3d space & 3d textures
// map -1, 1 to -width/2 , width/2
std::vector <Obj> cubes = {
{
{
{ {-300, -300, -1.1}, {1,1,1,1} },
{ {-300, 300, -1.1}, {1,1,1,1} },
{ {300, 300, -1.1}, {1,1,1,1} },
{ {300, -300, -1.1}, {1,1,1,1} },
{ {-300, -300, -2.1}, {0,1,1,1} },
{ {-300, 300, -2.1}, {0,1,1,1} },
{ {300, 300, -2.1}, {0,1,1,1} },
{ {300, -300, -2.1}, {0,1,1,1} },
},
{
0,1,2, 2,3,0, 4,5,6, 6,7,4, 0,4,5, 1,5,0
},
true
}
};
float tx = 0;
float ty = 0;
float tz = 0;
while (!glfwWindowShouldClose(window.window) )
{
glfwMakeContextCurrent(window.window);
renderer.Clear({0.0, 0.0, 0.0, 1});
// feed inputs to dear imgui, start new frame
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame();
renderer.Draw(shader, window.mvp, cubes);
window.mvp.view = glm::translate(glm::mat4(1), glm::vec3(0, 0, -1.6)) * glm::rotate(glm::mat4(1), glm::radians(tx), glm::vec3(1,0,0)) * glm::rotate(glm::mat4(1), glm::radians(ty), glm::vec3(0,1,0)) * glm::rotate(glm::mat4(1), glm::radians(tz), glm::vec3(0,0,1));
window.mvp.view = glm::translate(window.mvp.view, glm::vec3(0, 0, 1.6));
renderer.Text(shader, MVP(glm::mat4(1.0), glm::mat4(1.0),glm::ortho(0.0, (double)width, 0.0, (double)height)), {(TextObj){"roboto", "FPS:" + std::to_string((int)ImGui::GetIO().Framerate), 0.01424501424f * height, 0.01424501424f * height, 0, 0.02849002849f * height, 0, {1,1,1,1}}});
// render your GUI
ImGui::Begin("Demo window");
ImGui::Button("Hello!");
ImGui::SliderFloat("x", &tx, 0, 360, "%.0f", 1.0f);
ImGui::SliderFloat("y", &ty, 0, 360, "%.0f", 1.0f);
ImGui::SliderFloat("z", &tz, 0, 360, "%.0f", 1.0f);
ImGui::End();
// Render dear imgui into screen
ImGui::Render();
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
int display_w, display_h;
glfwGetFramebufferSize(window.window, &display_w, &display_h);
glViewport(0, 0, display_w, display_h);
glfwSwapBuffers(window.window);
glfwSwapInterval(1);
glfwPollEvents();
}
ImGui_ImplOpenGL3_Shutdown();
ImGui_ImplGlfw_Shutdown();
ImGui::DestroyContext();
return 0;
}
and the output:
notice that i chane the vertexes from 0.5 to 300 so thats not a problem
explanation of obj struct
{
// vertexes -> vbo
{ {-0.5, -0.5, -1.1}, {1,1,1,1} }, glm::vec3 pos, glm::vec4 col
{ {-0.5, 0.5, -1.1}, {1,1,1,1} },
{ {0.5, 0.5, -1.1}, {1,1,1,1} },
{ {0.5, -0.5, -1.1}, {1,1,1,1} },
{ {-0.5, -0.5, -2.1}, {0,1,1,1} },
{ {-0.5, 0.5, -2.1}, {0,1,1,1} },
{ {0.5, 0.5, -2.1}, {0,1,1,1} },
{ {0.5, -0.5, -2.1}, {0,1,1,1} },
},
{
// indexex -> ibo
0,1,2, 2,3,0, 4,5,6, 6,7,4, 0,4,5, 1,5,0
},
true // fill -> GL_TRIANGLES or GL_LINES
}
Thanks to #derhass for the clarification the cuboid that I was drawing was too thin and my Z far value was too short I've adjusted it to 1000.0f and now everything works great
here is his comment:
"The problem is that the cube becomes a line". There are no cubes in your vertex data, there is a cuboid sized 600x600x1, so if you look at it at certain angles, it will look very thin of course. And furthermore, you will run into clipping issues as your z range is only 10 units.
For reference I'm using this guide.
I've gone over several guides including one that almost had the answer I was looking for.
I'm trying to draw an Icosahedron (an approximation on a sphere), as soon as I figure out why I'm not drawing I'll subdivide it so that I can progress from drawing with 20 triangles to 80 and then to 320 but currently I'm just trying to draw one with 20 sides.
I've gone through debugging and really can't see what's wrong with the program, all variables have the right values when they encounter a function.
Here's my program:
#define _USE_MATH_DEFINES
#define X .525731112119133606f
#define Z .850650808352039932f
#define N 0.0f
#include <glut.h>
#include <math.h>
#include <iostream>
using namespace std;
GLsizei winWidth = 1000, winHeight = 1000;
static GLfloat vdata[12][3] = {
{ -X,N,Z },{ X,N,Z },{ -X,N,-Z },{ X,N,-Z },
{ N,Z,X },{ N,Z,-X },{ N,-Z,X },{ N,-Z,-X },
{ Z,X,N },{ -Z,X, N },{ Z,-X,N },{ -Z,-X, N }
};
static GLuint tindices[20][3] = {
{ 0,4,1 },{ 0,9,4 },{ 9,5,4 },{ 4,5,8 },{ 4,8,1 },
{ 8,10,1 },{ 8,3,10 },{ 5,3,8 },{ 5,2,3 },{ 2,7,3 },
{ 7,10,3 },{ 7,6,10 },{ 7,11,6 },{ 11,0,6 },{ 0,1,6 },
{ 6,1,10 },{ 9,0,11 },{ 9,11,2 },{ 9,2,5 },{ 7,2,11 }
};
double randFrac() {
return (double)rand() / RAND_MAX;
}
void init(void){
glClearColor(1.0, 1.0, 1.0, 0.0); // White display window.
}
void drawTriangle(float* v1, float* v2, float* v3) {
glBegin(GL_TRIANGLES);
glNormal3fv(v1);
glVertex3fv(v1);
glNormal3fv(v2);
glVertex3fv(v2);
glNormal3fv(v3);
glVertex3fv(v3);
glEnd();
}
void normalize(float v[3]) {
GLfloat d = sqrt(v[0] * v[0] + v[1] * v[1] + v[1] * v[2]);
if (!d) {
cerr << "VECTOR HAS LENGTH OF ZERO";
return;
}
v[0] /= d;
v[1] /= d;
v[2] /= d;
}
void subdivide(float* v1, float* v2, float* v3, long depth) {
GLfloat v12[3],v23[3], v31[3];
if (!depth) {
drawTriangle(v1, v2, v3);
return;
}
for (GLint i = 0; i < 3; i++) {
v12[i] = (v1[i] + v2[i]) / 2.0;
v23[i] = (v2[i] + v3[i]) / 2.0;
v31[i] = (v1[i] + v3[i]) / 2.0;;
}
normalize(v12);
normalize(v23);
normalize(v31);
subdivide(v1, v12, v31, depth - 1);
subdivide(v2, v23, v12, depth - 1);
subdivide(v3, v31, v23, depth - 1);
subdivide(v12, v23, v31, depth - 1);
}
void drawIcosahedrons() {
glClear(GL_COLOR_BUFFER_BIT); // Clear display window.
glColor3f(0.0, 0.0, 1.0); // Set line color to blue.
/* Set viewing transformation. */
gluLookAt(5.0, 5.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
for (int i = 0; i < 20; i++) {
glColor3f(randFrac(), randFrac(), randFrac()); // set sides to random color
drawTriangle(&vdata[tindices[i][0]][0], &vdata[tindices[i][1]][0], &vdata[tindices[i][2]][0]);
}
}
void winReshapeFcn(GLint newWidth, GLint newHeight) {
glViewport(0, 0, newWidth, newHeight);
glMatrixMode(GL_PROJECTION);
glFrustum(-1.0, 1.0, -1.0, 1.0, 2.0, 20.0);
glMatrixMode(GL_MODELVIEW);
glClear(GL_COLOR_BUFFER_BIT);
}
void main (int argc, char** argv){
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
glutInitWindowPosition (100, 100);
glutInitWindowSize (winWidth, winHeight);
glutCreateWindow ("title");
init();
glutDisplayFunc (drawIcosahedrons);
glutReshapeFunc (winReshapeFcn);
glutMainLoop();
}
My apologies everyone, I forgot to glFlush(); after I finished drawing.
I'm trying to create cubes in OpenGL/glut using a for loop but as yet I only get an overflow.
here's the code to create the cube with textures:
void Cubes1Class::render()
{
for (int face = 0; face < 6; face++)
{
if (face < 1)
{
glBindTexture(GL_TEXTURE_2D, texHandle[1]);
glBegin(GL_QUADS);
for (int vert = 0; vert <= 4; vert++)
{
glVertex3fv(VertsZ[FacesZ[face][vert]]);
glTexCoord2f(TexZ[vert][0], TexZ[vert][1]);
}
}
else
{
glBindTexture(GL_TEXTURE_2D, texHandle[0]);
glBegin(GL_QUADS);
for (int vert = 0; vert <= 4; vert++)
{
glVertex3fv(VertsZ[FacesZ[face][vert]]);
glTexCoord2f(TexZ[vert][0], TexZ[vert][1]);
}
}
glEnd();
}
}
and this is where I try to render it with a for loop:
CubesClass::CubesClass(int num) // constructor
{
numOfCubes = 3;
for (int i=0; i<numOfCubes; i++)
{
lst[i]=new Cubes1Class();
}
}
void CubesClass::render()
{
int x = 0;
numOfCubes = 3;
for (x = 0; x < numOfCubes; x++)
{
glPushMatrix();
glTranslatef(0.0, x, 0.0);
lst[x]->render();
glPopMatrix();
}
}
I can't figure out where I've gone wrong.
Any idea?
EDIT:
The cubes render fine without the for loop if I just render then translate then render then translate etc.
These are the arrays:
static GLfloat VertsZ[8][3] = {
{ -0.5, 0.5, -0.5 }, /* 0 left top rear */
{ 0.5, 0.5, -0.5 }, /* 1 right top rear */
{ 0.5, -0.5, -0.5 }, /* 2 right bottom rear */
{ -0.5, -0.5, -0.5 }, /* 3 left bottom rear */
{ -0.5, 0.5, 0.5 }, /* 4 left top front */
{ 0.5, 0.5, 0.5 }, /* 5 right top front */
{ 0.5, -0.5, 0.5 }, /* 6 right bottom front */
{ -0.5, -0.5, 0.5 } /* 7 left bottom front */
};
static GLuint FacesZ[6][4] = {
7, 6, 5, 4, /* front */
6, 2, 1, 5, /* right */
3, 7, 4, 0, /* left */
5, 1, 0, 4, /* top */
7, 6, 2, 3, /* bottom */
2, 3, 0, 1 /* rear */
};
static GLfloat TexZ[4][2] = {
0.0, 0.0,
0.0, 1.0,
1.0, 1.0,
1.0, 0.0
};
the cubes1Class is empty currently
It works now not sure why it just didn't
sorry if I wasted time :/
here's the end code:
#include "Cubes.h"
#include "bitmap.h"
static GLfloat VertsZ[8][3] = {
{ -0.5, 0.5, -0.5 }, /* 0 left top rear */
{ 0.5, 0.5, -0.5 }, /* 1 right top rear */
{ 0.5, -0.5, -0.5 }, /* 2 right bottom rear */
{ -0.5, -0.5, -0.5 }, /* 3 left bottom rear */
{ -0.5, 0.5, 0.5 }, /* 4 left top front */
{ 0.5, 0.5, 0.5 }, /* 5 right top front */
{ 0.5, -0.5, 0.5 }, /* 6 right bottom front */
{ -0.5, -0.5, 0.5 } /* 7 left bottom front */
};
static GLuint FacesZ[6][4] = {
7, 6, 5, 4, /* front */
6, 2, 1, 5, /* right */
3, 7, 4, 0, /* left */
5, 1, 0, 4, /* top */
7, 6, 2, 3, /* bottom */
2, 3, 0, 1 /* rear */
};
static GLfloat NormalsZ[6][3] = {
0, 0, 1, /* front */
1, 0, 0, /* right */
-1, 0, 0, /* left */
0, 1, 0, /* top */
0, -1, 0, /* bottom */
0, 0, -1 /* rear */
};
static GLfloat TexZ[4][2] = {
{0.0, 0.0 },
{0.0, 1.0 },
{1.0, 1.0 },
{1.0, 0.0 }
};
static CBitmap *bmp0; // the texture
static CBitmap *bmp1; // the texture
static GLuint texHandle[2]; // the open gl texture handle
void readTextureFile()
{
bmp0= new CBitmap("metal.bmp");
printf("bmp size %d %d\n",bmp0->GetWidth(),bmp0->GetHeight());
bmp1= new CBitmap("starTexture3.bmp");
printf("bmp size %d %d\n",bmp1->GetWidth(),bmp1->GetHeight());
glGenTextures(2, &texHandle[0]);
// Texture handle will be bound to the BMP bitmap data just
// as it was read in...
glBindTexture(GL_TEXTURE_2D, texHandle[0]);
glTexImage2D(GL_TEXTURE_2D,
0, // Mipmap level 0
3, // 3 bytes [R,G,B] per pixel
bmp0->GetWidth(), // width of bitmap
bmp0->GetHeight(), // height of bitmap
0, // no border pixels
GL_RGBA, // bitmap pixel format
GL_UNSIGNED_BYTE, // format for GL to store it
bmp0->GetBits() // pointer to the pixel data
);
glBindTexture(GL_TEXTURE_2D, texHandle[1]);
glTexImage2D(GL_TEXTURE_2D,
0, // Mipmap level 0
3, // 3 bytes [R,G,B] per pixel
bmp1->GetWidth(), // width of bitmap
bmp1->GetHeight(), // height of bitmap
0, // no border pixels
GL_RGBA, // bitmap pixel format
GL_UNSIGNED_BYTE, // format for GL to store it
bmp1->GetBits() // pointer to the pixel data
);
}
// ------------------------- Cubes1Class -----------------------------
Cubes1Class::Cubes1Class() // constructor
{
}
void Cubes1Class::render()
{
for (int face = 0; face < 6; face++)
{
if (face < 1)
{
glBindTexture(GL_TEXTURE_2D, texHandle[1]);
glBegin(GL_QUADS);
for (int vert = 0; vert <= 4; vert++)
{
glTexCoord2f(TexZ[vert][0], TexZ[vert][1]);
glVertex3fv(VertsZ[FacesZ[face][vert]]);
}
}
else
{
glBindTexture(GL_TEXTURE_2D, texHandle[0]);
glBegin(GL_QUADS);
for (int vert = 0; vert <= 4; vert++)
{
glTexCoord2f(TexZ[vert][0], TexZ[vert][1]);
glVertex3fv(VertsZ[FacesZ[face][vert]]);
}
}
glEnd();
}
}
// ------------------------- CubesClass -----------------------------
//Cubes1Class *lst[MAX_NUM_CUBES]; // the cubes
//GLfloat angle[MAX_NUM_CUBES]; // the cubes rotations
CubesClass::CubesClass(int num) // constructor
{
numOfCubes = 4;
for (int i=0; i<numOfCubes; i++)
{
lst[i]=new Cubes1Class();
}
}
void CubesClass::render() // draw it
{
for (int i=0; i<numOfCubes; i++)
{
glPushMatrix();
glTranslatef(0.0, i, 0.0);
lst[i]->render();
glPopMatrix();
}
}
Hi I'm trying to implement a opengl program with rotation&translation. But I got this problem that, the world axes will rotating along with my object(a cube). It's like, first I rotate cube along Z-axis, it works fine, then I middle-click the mouse and want to rotate the cube along the original Y-axis. At the moment I click, the cube will stop rotating along Z and start to rotate along Y. But it turns out it will rotate along a "new and invisible" Y-axis. I figure out that's because when I rotate the cube along Z with glRotatef(), the other two axis:X,Y also rotate. How can I fix the axes when I'm rotating the cube. I know the glRotatef() will multiply all matrix in screen with a rotation axis, so I tried added a glLoadIdentity() in each rotation but it still not work. can anyone give me the solution?
the code is here for reference:
#include <stdlib.h>
#include <GL/glut.h>
#include <iostream>
GLfloat vertices[8][3] =
{ { -1.0, -1.0, -1.0 }, { 1.0, -1.0, -1.0 },
{ 1.0, 1.0, -1.0 }, { -1.0, 1.0, -1.0 }, { -1.0, -1.0, 1.0 },
{ 1.0, -1.0, 1.0 }, { 1.0, 1.0, 1.0 }, { -1.0, 1.0, 1.0 } };
GLuint listName;
GLfloat theta[3] = { 0.0, 0.0, 0.0 };
GLint axis = 2;
GLfloat delta = 0.02;
GLint stop = 0;
GLfloat distance = 0;
void face(int a, int b, int c, int d)
{
glBegin(GL_POLYGON);
//glColor3fv(colors[a]);
glVertex3fv(vertices[a]);
//glColor3fv(colors[b]);
glVertex3fv(vertices[b]);
//glColor3fv(colors[c]);
glVertex3fv(vertices[c]);
//glColor3fv(colors[d]);
glVertex3fv(vertices[d]);
glEnd();
}
void cube(void)
{
glColor3f(1.0f,1.0f,1.0f);
face(0, 3, 2, 1);
face(2, 3, 7, 6);
face(0, 4, 7, 3);
face(1, 2, 6, 5);
face(4, 5, 6, 7);
face(0, 1, 5, 4);
glutWireCube(2.5f);
glutPostRedisplay();
}
void drawAxis(void){
// save previous matrix
glPushMatrix();
// clear matrix
glLoadIdentity();
// draw our axes
glRotatef(45.0, 1.0, 0.0, 0.0);
glRotatef(45.0, 0.0, -1.0, 0.0);
glBegin(GL_LINES);
// draw line for x axis
glColor3f(1.0, 0.0, 0.0);
glVertex3f(0.0, 0.0, 0.0);
glVertex3f(10.0, 0.0, 0.0);
// draw line for y axis
glColor3f(0.0, 1.0, 0.0);
glVertex3f(0.0, 0.0, 0.0);
glVertex3f(0.0, 10.0, 0.0);
// draw line for Z axis
glColor3f(0.0, 0.0, 1.0);
glVertex3f(0.0, 0.0, 0.0);
glVertex3f(0.0, 0.0, 10.0);
glEnd();
// load the previous matrix
glPopMatrix();
glutPostRedisplay();
}
void spinCube()
{
theta[axis] += delta;
if (theta[axis] > 360.0) theta[axis] -= 360.0;
glutPostRedisplay();
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glRotatef(45.0, 1.0, 0.0, 0.0);
glRotatef(45.0, 0.0, -1.0, 0.0);
drawAxis();
glPushMatrix();
glRotatef(theta[0], 1.0, 0.0, 0.0);
glRotatef(theta[1], 0.0, 1.0, 0.0);
glRotatef(theta[2], 0.0, 0.0, 1.0);
glTranslatef(0.0, 0.0, distance + 2.0);
glCallList(listName);
glPopMatrix();
glutSwapBuffers();
}
void myReshape(int w, int h)
{
GLfloat aspect = (GLfloat) w / (GLfloat) h;
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if (w <= h)
glOrtho(-10.0, 10.0, -10.0 / aspect, 10.0 / aspect, -50.0, 50.0);
else
glOrtho(-10.0*aspect, 10.0*aspect, -10.0, 10.0, -50.0, 50.0);
glMatrixMode(GL_MODELVIEW);
}
void mouse(int btn, int state, int x, int y)
{
if (btn == GLUT_LEFT_BUTTON && state == GLUT_DOWN) { axis = 0;
}
if (btn == GLUT_MIDDLE_BUTTON && state == GLUT_DOWN) { axis = 1;
}
if (btn == GLUT_RIGHT_BUTTON && state == GLUT_DOWN) { axis = 2;
}
}
void keyboard(unsigned char key, int x, int y)
{
if (key == 'q' || key == 'Q') exit(0);
if (key == ' ') { stop = !stop; }
if (stop)
glutIdleFunc(NULL);
else
glutIdleFunc(spinCube);
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH | GLUT_RGB);
glutInitWindowSize(600, 600);
glutCreateWindow("cube");
glutReshapeFunc(myReshape);
glutDisplayFunc(display);
glutIdleFunc(spinCube);
glutMouseFunc(mouse);
glutKeyboardFunc(keyboard);
//creating a display list:
listName = glGenLists(1);
glNewList(listName, GL_COMPILE);
cube();
glEndList();
glEnable(GL_DEPTH_TEST);
glutMainLoop();
return 0;
}
What you're after might be accumulating arbitrary rotations. This can't be done with euler angles, which gimbal lock. It's pretty common to have euler angle rotations and in most cases the issue is simply to do with the order they're applied in. The first thing I'd suggest is to reverse the order of your x/y/z rotations.
Next, if you want to accumulate rotations you'll really want to get into quaternions. This can be done with matrices but can easily become numerically unstable. Quaternions can be normalized which solves this issue.
If you rotate around X, the first call is of course, glRotatef(a, 1, 0, 0); draw(). Then you want to rotate the object and its current rotation around y. Note that the object and current rotation are grouped in this line of thinking. So you glRotatef(b, 0, 1, 0); glRotatef(a, 1, 0, 0); draw();. Each time you rotate, you add the rotation behind the existing list of transforms. If you added in front, it'd transform the object in its local space and not global. What you could do is this (near-pseudo-code with an imaginary matrix implementation):
Keep a current object transform matrix M
In spinCube, M = rotationMatrix(delta, axis==0?1:0, axis==1?1:0, axis==2?1:0) * M (note it's rotation * M and not M * rotation.
Before you draw the cube, glMultMatrixf(M.data)
The problem is floating point error will build up over time and the matrix will start to skew/scale your object in weird ways. Instead, you'll want a quaternion implementation (again near-pseudo-code):
Q = rotationQuaternion(delta, axis==0?1:0, axis==1?1:0, axis==2?1:0) * Q
Q.normalize()
...
glMultMatrixf(Q.toMatrix().data)
I am trying to read the value from glEvalCoord, but not getting the exact values which I should get. My code is
GLfloat ctrlpoints[4][3] = {
{ -4.0, -4.0, 0.0}, { -2.0, 4.0, 0.0},
{ 2.0, -4.0, 0.0}, { 4.0, 4.0, 0.0}};
void display()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glEnable(GL_LIGHTING);
glMap1f(GL_MAP1_VERTEX_3, 0.0, 1.0, 3, 4, &ctrlpoints[0][0]);
glEnable(GL_MAP1_VERTEX_3);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
GLint size;
GLfloat feedBuffer[1024];
glFeedbackBuffer (1024, GL_3D, feedBuffer);
glRenderMode (GL_FEEDBACK);
glBegin (GL_POINTS);
for (int i=0; i<=30; ++i)
{
GLfloat t = GLfloat(i)/30;
glEvalCoord1f(t);
}
glEnd();
size = glRenderMode (GL_RENDER);
cerr<<size<<endl;
}
Now, I am not sure but shouldn't it give me 30*3 values for each of the x, y and z coordinates of the curve?? But I am getting only 7*3 values. And the output of size is 28.
I think your size is 28 because your projection/modelview pair is clipping out some points.
"In feedback mode, each primitive that would be rasterized ... generates a block of values that's copied into the feedback array."
Try this:
#include <GL/glut.h>
#include <iostream>
using namespace std;
void display()
{
glClear( GL_COLOR_BUFFER_BIT );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
double w = glutGet( GLUT_WINDOW_WIDTH );
double h = glutGet( GLUT_WINDOW_HEIGHT );
double ar = w / h;
glOrtho( -5 * ar, 5 * ar, -5, 5, -1, 1 );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
GLfloat ctrlpoints[4][3] =
{
{ -4.0, -4.0, 0.0 }, { -2.0, 4.0, 0.0 },
{ 2.0, -4.0, 0.0 }, { 4.0, 4.0, 0.0 }
};
glMap1f(GL_MAP1_VERTEX_3, 0.0, 1.0, 3, 4, &ctrlpoints[0][0]);
glEnable(GL_MAP1_VERTEX_3);
GLfloat feedBuffer[1024];
glFeedbackBuffer (1024, GL_3D, feedBuffer);
glRenderMode (GL_FEEDBACK);
glPointSize( 5 );
glColor3ub( 255, 255, 255 );
glBegin (GL_POINTS);
for (int i=0; i<=30; ++i)
{
GLfloat t = GLfloat(i)/30;
glEvalCoord1f(t);
}
glEnd();
GLint size = glRenderMode (GL_RENDER);
cerr << size << endl;
glutSwapBuffers();
}
int main( int argc, char **argv )
{
glutInit( &argc, argv );
glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE );
glutInitWindowSize( 640, 480 );
glutCreateWindow( "GLUT" );
glutDisplayFunc( display );
glutMainLoop();
return 0;
}
I added a slightly larger projection matrix.
With that I get a size of 124:
31 points * 3 floats per point = 93
31 points * 1 GL_POINT_TOKEN per point = 31
31 + 91 = 124