I was implementing this dda algorithm using opengl. However, for some reason, it doesn't plot the second line. I tried putting printf at every line, which shows that it IS executing. However, there is no output in my window
#include <GL/gl.h>
#include <GL/glut.h>
#include <stdio.h>
int choice = 0;
void DDA(x0, y0, x1, y1)
const x0, y0, x1, y1;
{
glOrtho(-500, 500, -500, 500, -1, 1);
float dx = x1 - x0;
float dy = y1 - y0;
int steps = abs(dx) > abs(dy) ? abs(dx) : abs(dy);
float xInc = (float)steps/dx;
float yInc = (float)steps/dy;
int x = x0, y = y0;
for(int i = 0; i < steps; i++) {
glBegin(GL_POINTS);
glColor3f(1.0, 3.0, 2.0);
glVertex2i(x, y);
x += xInc;
y += yInc;
glEnd();
glFlush();
}
}
void Bresenham(x0, y0, x1, y1)
const x0, y0, x1, y1;
{
glOrtho(-500, 500, -500, 500, -1, 1);
int x = x0;
int y = y0;
int dx = x1 - x0;
int dy = y1 - y0;
int p = 2*dy-dx;
int m = dy / dx;
glBegin(GL_POINTS); {
glColor3f(2.0, 3.0, 5.0);
while(x != x1) {
if(m < 1) {
glVertex2i(x, y);
x++;
if(p >= 0) {
p += 2*(dy - dx);
y++;
}
else {
p += 2*dy;
}
}
else {
glVertex2i(x, y);
y++;
if(p >= 0) {
p += 2*(dx - dy);
x++;
}
else {
p += 2*dx;
}
}
}
glVertex2i(x, y);
}
glEnd();
glFlush();
}
void circle(x0, y0, r)
const x0, y0, r;
{
}
void renderDDA(void) {
DDA(0, 0, 300, 400);
DDA(0, 0, 200, 200);
}
void renderBresenham(void) {
Bresenham(0, 0, 300, 100);
Bresenham(0, 0, 500, 0);
}
void renderCircle(void) {
}
main(argc, argv)
char** argv;
{
redo:
printf("ENTER YOUR CHOICE: ");
scanf("%d", &choice);
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
glutInitWindowPosition(0, 0);
glutInitWindowSize(1920, 1680);
glutCreateWindow(argv[1]);
glClear(GL_COLOR_BUFFER_BIT);
glClearColor(0.0, 0.0, 0.0, 0.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
switch (choice) {
case 0:
glutDisplayFunc(renderDDA);
break;
case 1:
glutDisplayFunc(renderBresenham);
break;
case 2:
glutDisplayFunc(renderCircle);
break;
default:
printf("NO SUCH CHOICE!!");
goto redo;
}
glutMainLoop();
return 0;
}
I also tried swapping the lines. Then it draws only the upper line. it does execute the second call however.
glOrtho does not set an orthographic projection, it defines an orthographic projection matrix and multiplies the current matrix by the orthographic projection matrix.
You've to set the identity matrix before calling glOrtho:
glLoadIdentity();
glOrtho(-500, 500, -500, 500, -1, 1);
Further there is an issue in the algorithm. The type of x and y has to be float. If you would trunc the result to int, then it is only possible to draw lines with angles that are aligned to multiples of 45 degreess, because x and y change exactly by 0 or 1 at each step:
float x = x0, y = y0;
for(int i = 0; i < steps; i++) {
glBegin(GL_POINTS);
glColor3f(1.0, 3.0, 2.0);
glVertex2i((int)(x+0.5f), (int)(y+0.5f));
x += xInc;
y += yInc;
glEnd();
}
Note, changing the type from int to float causes that x and y are tracked with full precision. glVertex2i((int)(x+0.5f), (int)(y+0.5f)) ensures that coordinates (x, y) are rounded to the integral position when the point is draw.
I recommend to move the setting of the projection matrix from and glFlush from DDA respectively Bresenham to renderDDA respectively renderBresenham:
void DDA(float x0, float y0, float x1, float y1)
{
float dx = x1 - x0;
float dy = y1 - y0;
int steps = abs(dx) > abs(dy) ? abs(dx) : abs(dy);
float xInc = (float)steps/dx;
float yInc = (float)steps/dy;
float x = x0, y = y0;
for(int i = 0; i < steps; i++) {
glBegin(GL_POINTS);
glColor3f(1.0, 3.0, 2.0);
glVertex2i((int)(x+0.5f), (int)(y+0.5f));
x += xInc;
y += yInc;
glEnd();
}
}
void Bresenham(float x0, float y0, float x1, float y1)
{
int x = x0;
int y = y0;
int dx = x1 - x0;
int dy = y1 - y0;
int p = 2*dy-dx;
int m = dy / dx;
glBegin(GL_POINTS); {
glColor3f(2.0, 3.0, 5.0);
while(x != x1) {
if(m < 1) {
glVertex2i(x, y);
x++;
if(p >= 0) {
p += 2*(dy - dx);
y++;
}
else {
p += 2*dy;
}
}
else {
glVertex2i(x, y);
y++;
if(p >= 0) {
p += 2*(dx - dy);
x++;
}
else {
p += 2*dx;
}
}
}
glVertex2i(x, y);
}
glEnd();
}
void renderDDA(void) {
glLoadIdentity();
glOrtho(-500, 500, -500, 500, -1, 1);
DDA(0, 0, 300, 400);
DDA(0, 0, 200, 200);
glFlush();
glutSwapBuffers();
}
void renderBresenham(void) {
glLoadIdentity();
glOrtho(-500, 500, -500, 500, -1, 1);
Bresenham(0, 0, 300, 100);
Bresenham(0, 0, 500, 0);
glFlush();
glutSwapBuffers();
}
Related
I get this wglMakeCurrent error: 00000006
in Cygwin everytime I run an application that has menu items in OpenGL. For the first time it works perfectly but the second time onwards, instead of menu, I see black rectangle in Window and see wglMakeCurrent error: 00000006
in Cygwin.
Note: The same code works exactly as it should when I run it Dev-C++.
#include <GL/glut.h>
#include<stdio.h>
static int window;
static int menu_id;
static int submenu_id;
static int value = 0;
float x1 = 200.0, y1 = 200.0, x2 = 100.0, y2 = 300.0, x3 = 200.0, y3 = 400.0, x4 = 300.0, y4 = 300.0;
void draw_pixel(int x, int y)
{
glColor3f(0.0, 1.0, 0.0);
glBegin(GL_POINTS);
glVertex2i(x, y);
glEnd();
glFlush();
}
void edgedetect(float x1, float y1, float x2, float y2, int *le, int *re)
{
float mx, x, temp;
int i;
if ((y2 - y1)<0) // y1>y2 ie. Y1=400 ,y2=300
{
temp = y1; y1 = y2; y2 = temp;
temp = x1; x1 = x2; x2 = temp;
}
if ((y2 - y1) != 0) //not a horizontal line
mx = (x2 - x1) / (y2 - y1);
else mx = x2 - x1;
x = x1;
for (i = y1; i <= y2; i++)
{
if (x<(float)le[i])
le[i] = (int)x;
if (x>(float)re[i])
re[i] = (int)x;
x += mx;
}
}
void scanfill(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4)
{
int le[500], re[500], i, y;
for (i = 0; i<500; i++)
{
le[i] = 500;
re[i] = 0;
}
edgedetect(x1, y1, x2, y2, le, re);
edgedetect(x2, y2, x3, y3, le, re);
edgedetect(x3, y3, x4, y4, le, re);
edgedetect(x4, y4, x1, y1, le, re);
for (y = 0; y<500; y++)
{
if (le[y] <= re[y])
for (i = (int)le[y]; i<(int)re[y]; i++)
draw_pixel(i, y);
}
}
void menu(int num){
if (num == 0)
{
glutDestroyWindow(window);
exit(0);
}
else{
value = num;
}
glutPostRedisplay();
}
void createMenu(void)
{
submenu_id = glutCreateMenu(menu);
glutAddMenuEntry("scanfill polygon", 2);
menu_id = glutCreateMenu(menu);
glutAddMenuEntry("Clear", 1);
glutAddSubMenu("Draw", submenu_id);
glutAddMenuEntry("Quit", 0);
glutAttachMenu(GLUT_RIGHT_BUTTON);
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT);
if (value == 1)
{
return; //glutPostRedisplay();
}
else if (value == 2)
{
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0, 0.5, 0.0);
glBegin(GL_LINE_LOOP);
glVertex2f(x1, y1);
glVertex2f(x2, y2);
glVertex2f(x3, y3);
glVertex2f(x4, y4);
glEnd();
scanfill(x1, y1, x2, y2, x3, y3, x4, y4);
glFlush();
} }
void myinit()
{
glClearColor(0.17, 0.13, 0.4, 1.0);
glColor3f(1.0, 0.0, 0.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0, 499.0, 0.0, 499.0);
}
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_SINGLE);
glutInitWindowSize(500, 500);
glutInitWindowPosition(100, 100);
window = glutCreateWindow("Menu driven Programming for Scan filling ");
createMenu();
glClearColor(0.0, 0.0, 0.0, 0.0);
glutDisplayFunc(display);
myinit();
glutMainLoop();
return EXIT_SUCCESS;
}
Menu:
After selecting menu subitem to fill polygon:
Error on Cygwin Terminal:
Output in Dev-C++:
So I just added ortho projection to my rendering and everything stopped rendering... If I remove it, it works again. This is my matrix code:
#include <stdlib.h>
#include <stdlib.h>
#include <math.h>
matrix4x4 init_matrix4x4() {
matrix4x4 m = calloc(16, sizeof(float));
m[0] = 1; m[1] = 0; m[2] = 0; m[3] = 0;
m[4] = 0; m[5] = 1; m[6] = 0; m[7] = 0;
m[8] = 0; m[9] = 0; m[10] = 1; m[11] = 0;
m[12] = 0; m[13] = 0; m[14] = 0; m[15] = 1;
return m;
}
void translate_matrix4x4(matrix4x4* matrix, float x, float y, float z) {
matrix4x4 m = (*matrix);
m[12] = m[0] * x + m[4] * y + m[8] * z + m[12];
m[13] = m[1] * x + m[5] * y + m[9] * z + m[13];
m[14] = m[2] * x + m[6] * y + m[10] * z + m[14];
m[15] = m[3] * x + m[7] * y + m[11] * z + m[15];
}
void ortho_matrix4x4(matrix4x4* matrix, float left, float right, float bottom, float top, float near, float far) {
matrix4x4 m = (*matrix);
m[0] = 2 / (right-left);
m[1] = 0;
m[2] = 0;
m[3] = 0;
m[4] = 0;
m[5] = 2 / (top - bottom);
m[6] = 0;
m[7] = 0;
m[8] = 0;
m[9] = 0;
m[10] = 1 / (far - near);
m[11] = 0;
m[12] = (left + right) / (left - right);
m[13] = (top + bottom) / (bottom - top);
m[14] = near / (near - far);
m[15] = 1;
}
void mat4_identity(matrix4x4* matrix) {
matrix4x4 out = (*matrix);
out[0] = 1;
out[1] = 0;
out[2] = 0;
out[3] = 0;
out[4] = 0;
out[5] = 1;
out[6] = 0;
out[7] = 0;
out[8] = 0;
out[9] = 0;
out[10] = 1;
out[11] = 0;
out[12] = 0;
out[13] = 0;
out[14] = 0;
out[15] = 1;
}
void mat4_lookAtf(matrix4x4* matrix, float eye[3], float center[3], float up[3]) {
matrix4x4 out = (*matrix);
float x0, x1, x2, y0, y1, y2, z0, z1, z2, len,
eyex = eye[0],
eyey = eye[1],
eyez = eye[2],
upx = up[0],
upy = up[1],
upz = up[2],
centerx = center[0],
centery = center[1],
centerz = center[2];
if (fabs(eyex - centerx) < 0.000001 &&
fabs(eyey - centery) < 0.000001 &&
fabs(eyez - centerz) < 0.000001) {
mat4_identity(&out);
return;
}
z0 = eyex - centerx;
z1 = eyey - centery;
z2 = eyez - centerz;
len = 1 / sqrt/*f*/(z0 * z0 + z1 * z1 + z2 * z2);
z0 *= len;
z1 *= len;
z2 *= len;
x0 = upy * z2 - upz * z1;
x1 = upz * z0 - upx * z2;
x2 = upx * z1 - upy * z0;
len = sqrt(x0 * x0 + x1 * x1 + x2 * x2);
if (!len) {
x0 = 0;
x1 = 0;
x2 = 0;
} else {
len = 1 / len;
x0 *= len;
x1 *= len;
x2 *= len;
}
y0 = z1 * x2 - z2 * x1;
y1 = z2 * x0 - z0 * x2;
y2 = z0 * x1 - z1 * x0;
len = sqrt(y0 * y0 + y1 * y1 + y2 * y2);
if (!len) {
y0 = 0;
y1 = 0;
y2 = 0;
} else {
len = 1 / len;
y0 *= len;
y1 *= len;
y2 *= len;
}
out[0] = x0;
out[1] = y0;
out[2] = z0;
out[3] = 0;
out[4] = x1;
out[5] = y1;
out[6] = z1;
out[7] = 0;
out[8] = x2;
out[9] = y2;
out[10] = z2;
out[11] = 0;
out[12] = -(x0 * eyex + x1 * eyey + x2 * eyez);
out[13] = -(y0 * eyex + y1 * eyey + y2 * eyez);
out[14] = -(z0 * eyex + z1 * eyey + z2 * eyez);
out[15] = 1;
};
And here is the main.c , where I render things:
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <stdio.h>
#include <stdlib.h>
#include "include/matrix.h"
#include "include/io.h"
const int WIDTH = 640;
const int HEIGHT = 480;
// called when user resizes window
void framebuffer_size_callback(GLFWwindow* window, int width, int height) {
glViewport(0, 0, width, height);
}
// called when we receive input
void processInput(GLFWwindow *window) {
if(glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, 1);
}
GLuint get_checker_texture() {
unsigned char texDat[64];
for (int i = 0; i < 64; ++i)
texDat[i] = ((i + (i / 8)) % 2) * 128 + 127;
//upload to GPU texture
GLuint tex;
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, 8, 8, 0, GL_RED, GL_UNSIGNED_BYTE, texDat);
glGenerateMipmap(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0);
return tex;
}
//void render_box(renderable* this, unsigned int vbo, unsigned int vao, unsigned int ebo) {
// draw_texture(this->texture, this->x, this->y, this->z, vbo, vao, ebo);
//}
int main(int argc, char* argv[]) {
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#ifdef __APPLE__
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // only on MACOS
#endif
// creating the window
GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "OpenGL App", NULL, NULL);
if (window == NULL) {
printf("Failed to create GLFW window");
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
// hook on window resize
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
printf("Failed to initialize GLAD");
return -1;
}
printf("OpenGL %d.%d\n", GLVersion.major, GLVersion.minor);
glEnable(GL_DEPTH_TEST);
glViewport(0, 0, WIDTH, HEIGHT);
unsigned int tex = get_checker_texture();
const char* vertex_shader_src = read_file("res/shaders/textured_and_positioned.vs.glsl");
unsigned int vertex_shader;
vertex_shader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex_shader, 1, &vertex_shader_src, NULL);
glCompileShader(vertex_shader);
int success;
char infoLog[512];
glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &success);
if (!success) {
glGetShaderInfoLog(vertex_shader, 512, NULL, infoLog);
printf("%s\n", infoLog);
}
const char* fragment_shader_src = read_file("res/shaders/textured_and_positioned.fs.glsl");
unsigned int fragment_shader;
fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment_shader, 1, &fragment_shader_src, NULL);
glCompileShader(fragment_shader);
int success0;
char infoLog0[512];
glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &success0);
if (!success0) {
glGetShaderInfoLog(fragment_shader, 512, NULL, infoLog0);
printf("%s\n", infoLog0);
}
unsigned int shaderProgram;
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertex_shader);
glAttachShader(shaderProgram, fragment_shader);
glLinkProgram(shaderProgram);
unsigned uniform_sampler_ourTexture = glGetUniformLocation(shaderProgram, "ourTexture");
unsigned uniform_mat4_model = glGetUniformLocation(shaderProgram, "model");
unsigned uniform_mat4_view = glGetUniformLocation(shaderProgram, "view");
unsigned uniform_mat4_perspective = glGetUniformLocation(shaderProgram, "perspective");
int success1;
char infoLog1[512];
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success1);
if(!success1) {
glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog1);
printf("%s\n", infoLog1);
}
float vertices[] = {
// positions // colors // texture coords
0.1f, 0.1f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // top right
0.1f, -0.1f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // bottom right
-0.1f, -0.1f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // bottom left
-0.1f, 0.1f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0 // top left
};
unsigned elements[] = {
0, 1, 2, // triangle
2, 3, 0 // triangle
};
unsigned int vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
matrix4x4 model = init_matrix4x4();
matrix4x4 view = init_matrix4x4();
translate_matrix4x4(&view, 0.0f, 0.0f, 0.0f);
float x = 0.0f;
float y = 0.0f;
float z = 0.0f;
matrix4x4 perspective = calloc(16, sizeof(float));
ortho_matrix4x4(&perspective, 0.0f, 640.0f, 0.0f, 480.0f, 0.1f, 100.0f);
unsigned int vbo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
// positions
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(0 * sizeof(float)));
glEnableVertexAttribArray(0);
// colors
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
// texture coords
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
glEnableVertexAttribArray(2);
unsigned int ebo;
glGenBuffers(1, &ebo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elements), elements, GL_STATIC_DRAW);
glUseProgram(shaderProgram);
glUniformMatrix4fv(uniform_mat4_view, 1, GL_FALSE, view);
glUniformMatrix4fv(uniform_mat4_perspective, 1, GL_FALSE, perspective);
// render loop
while(!glfwWindowShouldClose(window)) {
processInput(window);
// render here
glClearColor(
0, 0, 0, 0
);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, tex);
glUniform1i(uniform_sampler_ourTexture, 0);
translate_matrix4x4(&model, x, y, z);
glUniformMatrix4fv(uniform_mat4_model, 1, GL_FALSE, model);
//x += 0.0001f;
//y += 0.0001f;
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwTerminate();
return 0;
}
Here is the vertex shader:
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;
layout (location = 2) in vec2 aTexCoord;
uniform mat4 model;
uniform mat4 view;
uniform mat4 perspective;
out vec3 ourColor;
out vec2 TexCoord;
void main()
{
gl_Position = perspective * view * model * vec4(aPos, 1.0);
ourColor = aColor;
TexCoord = aTexCoord;
}
Here is the fragment shader:
#version 330 core
out vec4 FragColor;
in vec3 ourColor;
in vec2 TexCoord;
uniform sampler2D ourTexture;
void main()
{
FragColor = vec4(vec3(texture(ourTexture, TexCoord).r), 1.);
}
Now, if I remove the perspective value from the shader, which is the ortho matrix, the checkered texture is rendered as it should.
What is wrong here?
Is it my shader or is it the matrix ortho function?
Your matrices are stored in row-major, submit them to the uniforms without transposing and do calculations left-associative in the shader.
You can either
store in column major order
or
transpose upon loading into the uniform
or
switch to left-associative multiplication in the shader
Each to the same effect.
I have the next code using OPENGL GLUT, this code draws a line at a cursor position. Once you click the right button of the mouse it captures the coordinates x0, y0 of the line, then when the mouse moves to another pixel while pushing the button the coordinates(x1,y1) change, and finally when the button is released the line is drawn.
#include<windows.h>
#include <gl/glut.h>
float a[90000];
int x0=0,y0=0,xf=0,yf=0;
int print=0;
void init(void)
{
glClearColor(1.0, 1.0, 1.0, 0.0);
glMatrixMode(GL_PROJECTION);
gluOrtho2D(0.0, 300.0, 0.0,300.0);
}
void putpixel(int x,int y)
{
glColor3f(0.0, 0.9,0.7);
glBegin(GL_POINTS);
glVertex2i(x,y);
glEnd();
}
void Bresenham(int x0, int y0, int x1, int y1)
{
int dx,dy,p,x,y,px = 1,py = 1,twoDy_Dx,twoDy,i;
glColor3f(0.0,0.0,1.0);
dx = x1-x0;
dy = y1-y0;
if(dx < 0)
dx = dx*-1;
if(dy < 0)
dy = dy*-1;
if(x1 < x0)
px = -1;
if(y1 < y0)
py = -1;
x = x0;
y = y0;
if( dx > dy )
{
putpixel(x,y);
p = 2 * dy - dx;
twoDy_Dx = 2 * ( dy - dx );
twoDy = 2 * dy;
for( i = 0; i < dx; i++ )
{
if( p >= 0 )
{
y += py;
p += twoDy_Dx;
}
else
p += twoDy;
x += px;
putpixel(x,y);
}
}
else
{
putpixel(x,y);
p = 2*dx - dy;
twoDy_Dx = 2 * ( dx - dy );
twoDy = 2*dx;
for( i = 0; i < dy; i++ )
{
if( p >= 0 )
{
x += px;
p += twoDy_Dx;
}
else
p += twoDy;
y += py;
putpixel(x,y);
}
}
glFlush();
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT);
if(print==1)
glDrawPixels(300,300,GL_RGB,GL_UNSIGNED_BYTE,a);
Bresenham(x0,y0,xf,yf);
glutSwapBuffers();
glFlush();
}
void onMotion(int x,int y)
{
xf=x;
yf=300-y;
glutPostRedisplay();
}
void onMouse(int button, int e, int x, int y)
{
if((button == GLUT_LEFT_BUTTON) && (e == GLUT_DOWN))
{
x0 = x;
y0 = abs(300-y);
print = 1;
}
if( (button == GLUT_RIGHT_BUTTON) && (e==GLUT_DOWN))
{
print=0;
}
if ( (button == GLUT_LEFT_BUTTON || button == GLUT_RIGHT_BUTTON) && (e == GLUT_UP) )
{
print=0;
}
}
void onPassive(int x,int y)
{
x0=-1;y0=-1;xf=-1;yf=-1;
glReadPixels( 0.0, 0.0,300.0,300.0,GL_RGB,GL_UNSIGNED_BYTE,a);
}
int main(int argc, char** argv)
{
glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB);
glutInitWindowPosition(100, 100);
glutInitWindowSize(300, 300);
glutCreateWindow("Line");
init();
glutDisplayFunc(display);
glutMotionFunc(onMotion);
glutMouseFunc(onMouse);
glutPassiveMotionFunc(onPassive);
glutMainLoop();
}
The problem that I have is that when the button is pushed and while the final coordinates are changing, the line should be drawn as a pointed line: ---------
but when it reaches the final coordinates, the line should be drawn like this: _________. How can I do this?
I have an openGL program thats using GLUT and I'm stuck with moving it from the top left corner to bottom right when i resize the window. I'm trying to get a ratio down and i cant figure it out.
#include <stdio.h>
#include <stdlib.h>
#include <GLUT/glut.h>
//global variables
GLsizei wh = 500, ww = 500;
double height;
double width;
double top = 500;
double bottom = 450;
int right = 50;
int left = 0;
double ratiowidth = 500/500;
double ratioheight = 500/500;
void myinit(){
glClearColor (0.0, 0.0, 0.0, 0.0);
}
void reshape(int w, int h){
if(h == 0){
h = 1;
}
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, (GLsizei) w, 0, (GLsizei)h);
glViewport(0,0,w,h);
glMatrixMode(GL_MODELVIEW);
int difference = h - wh;
int difference2 = w - ww;
left = left + difference2;
right = right + difference2;
wh = (GLsizei)h;
ww = (GLsizei)w;
height = h;
width = w;
}
void mouse(int button, int state, int x, int y){
if(button == GLUT_LEFT_BUTTON && state == GLUT_DOWN){
top = height;
bottom = height - 50;
right = 50;
left = 0;
ratiowidth = width/height;
ratioheight = height/width;
}
if(button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN){
exit(0);
}
}
void display(){
glClear (GL_COLOR_BUFFER_BIT);
glColor3i (rand(), rand(), rand());
glBegin(GL_POLYGON);
glVertex3f (left,top,0.0);
glVertex3f (right, top, 0.0);
glVertex3f (right, bottom, 0.0);
glVertex3f (left, bottom, 0.0);
glEnd();
if(bottom == 0 || bottom < 0)
bottom = 0;
else{
left = left + ratiowidth;
right = right + ratiowidth;
top = top - ratioheight;
bottom = bottom - ratioheight;
}
glutSwapBuffers();
usleep(10000);
glutPostRedisplay();
}
int main(int argc, char** argv) {
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(ww, wh);
glutInitWindowPosition(100,100);
glutCreateWindow("moving Square");
myinit();
glutReshapeFunc(reshape);
glutDisplayFunc(display);
glutMouseFunc(mouse);
glutMainLoop();
return 0;
}
glBegin(GL_POLYGON);
glVertex3f (left,top,0.0);
glVertex3f (right, top, 0.0);
glVertex3f (right, bottom, 0.0);
glVertex3f (left, bottom, 0.0);
glEnd();
Careful with your winding order. glFrontFace() defaults to GL_CCW. Perhaps you meant this:
glBegin(GL_POLYGON);
glVertex3f (left, bottom, 0.0);
glVertex3f (right, bottom, 0.0);
glVertex3f (right, top, 0.0);
glVertex3f (left,top,0.0);
glEnd();
EDIT: This is what I think you were trying to do:
#include <GL/glut.h>
struct State
{
double x; // in units
double y;
double xvel; // in units per second
double yvel;
};
State curState = { 0 };
void myinit()
{
curState.xvel = 100;
curState.yvel = 100;
}
void Integrate( State* state, double dt )
{
state->x += state->xvel * dt;
state->y += state->yvel * dt;
}
double GetSeconds()
{
return glutGet(GLUT_ELAPSED_TIME) / 1000.0f;
}
void reshape(int w, int h)
{
glViewport(0,0,w,h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, (GLsizei)w, 0, (GLsizei)h);
}
void mouse(int button, int state, int x, int y)
{
if(button == GLUT_LEFT_BUTTON && state == GLUT_UP)
{
curState.x = 0;
curState.y = 0;
}
if(button == GLUT_RIGHT_BUTTON && state == GLUT_UP)
{
exit(0);
}
}
void display()
{
glClearColor (0.0, 0.0, 0.0, 0.0);
glClear (GL_COLOR_BUFFER_BIT);
float w = 20;
float h = 20;
float x = curState.x;
float y = curState.y;
glColor3ub(rand()%255, rand()%255, rand()%255);
glBegin(GL_QUADS);
glVertex2f( x - w/2, y - h/2 );
glVertex2f( x + w/2, y - h/2 );
glVertex2f( x + w/2, y + h/2 );
glVertex2f( x - w/2, y + h/2 );
glEnd();
static double lastTime = GetSeconds();
double curTime = GetSeconds();
Integrate( &curState, curTime - lastTime );
lastTime = curTime;
glutSwapBuffers();
}
void timer(int extra)
{
glutPostRedisplay();
glutTimerFunc(16, timer, 0);
}
int main(int argc, char** argv)
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(500, 500);
glutInitWindowPosition(100,100);
glutCreateWindow("moving Square");
myinit();
glutReshapeFunc(reshape);
glutTimerFunc(0, timer, 0);
glutDisplayFunc(display);
glutMouseFunc(mouse);
glutMainLoop();
return 0;
}
Be aware that there are probably some C++-isms in there :)
this is my draw() function written in C, using vertex arrays:
void draw(float x1, float x2, float y1, float y2)
{
glPushMatrix();
glScalef(1.0 / (x2 - x1), 1.0 / (y2 - y1), 1.0);
glTranslatef(-x1, -y1, 0.0);
glColor3f(1.0, 1.0, 1.0);
if( pts.size > 0 )
{
glEnableClientState( GL_VERTEX_ARRAY );
glVertexPointer( 2, GL_FLOAT, 0, (float*)pts.data );
glDrawArrays( GL_LINE_STRIP, 0, pts.size / 2 );
glDisableClientState( GL_VERTEX_ARRAY );
}
glPopMatrix();
};
before calling draw(), pts get's updated inside the update() function:
void update(double (* func)(double x), float x1, float x2, int N)
{
double x, dx = (double)1.0/(double)N;
vector_cleanup( &pts );
m = 0;
for(x = x1; x < x2; x += dx)
{
vector_resize( &pts, pts.size + 2 );
*(float*)vector_get( &pts, pts.size-2 ) = (float)x;
*(float*)vector_get( &pts, pts.size-1 ) = (float)func3(x);
m++;
}
}
I hope that by converting this code to use VBO, my graphics performance will increase.
EDIT: func3() can be anything, e.g. sin(x) or just some linear mapping. All I'm currently trying to do is, to find out how quickly I can plot a bunch of points.
Using GLEW for extension wrangling:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <GL/glew.h>
#include <GL/glut.h>
typedef struct vector /*dynamic vector of void* pointers. This one is used only by the deflate compressor*/
{
void* data;
size_t size; /*in groups of bytes depending on type*/
size_t allocsize; /*in bytes*/
unsigned typesize; /*sizeof the type you store in data*/
} vector;
static unsigned vector_resize(vector* p, size_t size) /*returns 1 if success, 0 if failure ==> nothing done*/
{
if(size * p->typesize > p->allocsize)
{
size_t newsize = size * p->typesize * 2;
void* data = realloc(p->data, newsize);
if(data)
{
p->allocsize = newsize;
p->data = data;
p->size = size;
}
else return 0;
}
else p->size = size;
return 1;
}
static void vector_cleanup(void* p)
{
((vector*)p)->size = ((vector*)p)->allocsize = 0;
free(((vector*)p)->data);
((vector*)p)->data = NULL;
}
static void vector_init(vector* p, unsigned typesize)
{
p->data = NULL;
p->size = p->allocsize = 0;
p->typesize = typesize;
}
static void* vector_get(vector* p, size_t index)
{
return &((char*)p->data)[index * p->typesize];
}
/* function to calculate each data point */
float func(float x)
{
return (float)sin(x);
}
GLuint vbo = 0;
GLsizei vertcount = 0;
void update(float (* func)(float x), float x1, float x2, int N)
{
float x, dx = 1.0f/N;
vector pts;
vector_init( &pts, sizeof( float ) );
for(x = x1; x < x2; x += dx)
{
vector_resize( &pts, pts.size + 2 );
*(float*)vector_get( &pts, pts.size-2 ) = x;
*(float*)vector_get( &pts, pts.size-1 ) = func(x);
}
vertcount = (GLsizei)( pts.size / 2 );
glBindBuffer( GL_ARRAY_BUFFER, vbo );
glBufferData( GL_ARRAY_BUFFER, pts.size * pts.typesize, pts.data, GL_DYNAMIC_DRAW );
glBindBuffer( GL_ARRAY_BUFFER, 0 );
vector_cleanup( &pts );
}
/* plotting function - very slow */
void draw(float x1, float x2, float y1, float y2)
{
glPushMatrix();
glScalef( 1.0f / (x2 - x1), 1.0f / (y2 - y1), 1.0f );
glTranslatef( -x1, -y1, 0.0f );
glColor3f( 1.0f, 1.0f, 1.0f );
glBindBuffer( GL_ARRAY_BUFFER, vbo );
glEnableClientState( GL_VERTEX_ARRAY );
glVertexPointer( 2, GL_FLOAT, 0, 0 );
glDrawArrays( GL_LINE_STRIP, 0, vertcount );
glDisableClientState( GL_VERTEX_ARRAY );
glBindBuffer( GL_ARRAY_BUFFER, 0 );
glPopMatrix();
};
/* Redrawing func */
float xmin = -10, xmax = 10, ymin = -5, ymax = 5;
void redraw(void)
{
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// -x, +x, -y, +y, number points
draw(xmin, xmax, ymin, ymax);
glutSwapBuffers();
};
/* Idle proc. Redisplays, if called. */
int nPoints = 3000;
void idle(void)
{
// shift 'xmin' & 'xmax' by one.
xmin++;
xmax++;
update(func, xmin, xmax, nPoints);
glutPostRedisplay();
};
/* Key press processing */
void key(unsigned char c, int x, int y)
{
if(c == 27) exit(0);
};
/* Window reashape */
void reshape(int w, int h)
{
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, 1, 0, 1, -1, 1);
glMatrixMode(GL_MODELVIEW);
};
/* Main function */
int main(int argc, char **argv)
{
GLenum err;
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
glutCreateWindow("Graph plotter");
glutReshapeWindow(1024, 800);
// init GLEW and output some GL info
err = glewInit();
printf("GL_VERSION : %s\n", glGetString(GL_VERSION) );
printf("GL_VENDOR : %s\n", glGetString(GL_VENDOR) );
printf("GL_RENDERER : %s\n", glGetString(GL_RENDERER) );
if( GLEW_OK != err )
{
printf("glewInit failed: %s", glewGetErrorString(err));
return EXIT_FAILURE;
}
if( !glewIsSupported("GL_VERSION_1_5") )
{
printf("OpenGL version 1.5 or greater required.\n");
return EXIT_FAILURE;
}
glGenBuffers( 1, &vbo );
/* Register GLUT callbacks. */
glutDisplayFunc(redraw);
glutKeyboardFunc(key);
glutReshapeFunc(reshape);
glutIdleFunc(idle);
/* Init the GL state */
glLineWidth(2.0);
/* Main loop */
glutMainLoop();
return 0;
}