Draw bezier curve

This commit is contained in:
hasufell 2014-06-01 02:13:45 +02:00
parent 99863ddcdd
commit cabc8e8c09
No known key found for this signature in database
GPG Key ID: 220CD1C5BDEED020
5 changed files with 179 additions and 20 deletions

View File

@ -28,6 +28,7 @@
#include "filereader.h" #include "filereader.h"
#include "gl_draw.h" #include "gl_draw.h"
#include "half_edge.h" #include "half_edge.h"
#include "print.h"
#include <GL/glut.h> #include <GL/glut.h>
#include <GL/gl.h> #include <GL/gl.h>
@ -66,10 +67,11 @@ bool shademodel = true;
/* /*
* static function declaration * static function declaration
*/ */
static void draw_bez(HE_obj const * const obj); static void draw_bez(HE_obj const * const obj, float step_factor_inc);
static void draw_obj(int32_t const myxrot, static void draw_obj(int32_t const myxrot,
int32_t const myyrot, int32_t const myyrot,
int32_t const myzrot); int32_t const myzrot,
float bez_inc);
static void draw_Planet_1(void); static void draw_Planet_1(void);
static void draw_Planet_2(void); static void draw_Planet_2(void);
static void gl_destroy(void); static void gl_destroy(void);
@ -189,11 +191,16 @@ static void draw_vertices(HE_obj const * const obj,
glPopMatrix(); glPopMatrix();
} }
static void draw_bez(HE_obj const * const obj) static void draw_bez(HE_obj const * const obj, float step_factor_inc)
{ {
uint32_t i = 0; uint32_t i = 0;
static float line_width = 2; static float line_width = 2;
static float point_size = 10; static float point_size = 10;
static float step_factor = 0.1;
if (step_factor + step_factor_inc > 0.002 &
step_factor + step_factor_inc < 0.50)
step_factor += step_factor_inc;
glPushMatrix(); glPushMatrix();
@ -201,7 +208,13 @@ static void draw_bez(HE_obj const * const obj)
glPointSize(point_size); glPointSize(point_size);
glColor3f(1.0, 0.0, 0.0); glColor3f(1.0, 0.0, 0.0);
while (i < obj->bzc) { while (i < obj->bzc) { /* for all bezier curves */
vector *v1 = NULL,
*v2 = NULL;
/*
* draw frame
*/
glBegin(GL_LINE_STRIP); glBegin(GL_LINE_STRIP);
for (uint32_t j = 0; j <= obj->bez_curves[i].deg; j++) { for (uint32_t j = 0; j <= obj->bez_curves[i].deg; j++) {
glVertex3f(obj->bez_curves[i].vec[j].x, glVertex3f(obj->bez_curves[i].vec[j].x,
@ -209,21 +222,69 @@ static void draw_bez(HE_obj const * const obj)
obj->bez_curves[i].vec[j].z); obj->bez_curves[i].vec[j].z);
} }
glEnd(); glEnd();
i++;
}
i = 0; /*
while (i < obj->bzc) { * draw control points
*/
glBegin(GL_POINTS); glBegin(GL_POINTS);
for (uint32_t j = 0; j <= obj->bez_curves[i].deg; j++) { for (uint32_t j = 0; j <= obj->bez_curves[i].deg; j++) {
glVertex3f(obj->bez_curves[i].vec[j].x, glVertex3f(obj->bez_curves[i].vec[j].x,
obj->bez_curves[i].vec[j].y, obj->bez_curves[i].vec[j].y,
obj->bez_curves[i].vec[j].z); obj->bez_curves[i].vec[j].z);
} }
glEnd();
glBegin(GL_LINES);
/*
* line segments: first line
*/
v1 = calculate_bezier_point(&(obj->bez_curves[i]), step_factor);
glVertex3f(obj->bez_curves[i].vec[0].x,
obj->bez_curves[i].vec[0].y,
obj->bez_curves[i].vec[0].z);
glVertex3f(v1->x,
v1->y,
v1->z);
for (float k = step_factor; k < 1 - step_factor; k += step_factor) {
free(v1);
free(v2);
v1 = calculate_bezier_point(&(obj->bez_curves[i]), k);
v2 = calculate_bezier_point(&(obj->bez_curves[i]), k +
step_factor);
/*
* line segments: middle lines
*/
glVertex3f(v1->x,
v1->y,
v1->z);
glVertex3f(v2->x,
v2->y,
v2->z);
}
/*
* line segments: last line
*/
glVertex3f(v2->x,
v2->y,
v2->z);
glVertex3f(obj->bez_curves[i].vec[obj->bez_curves[i].deg].x,
obj->bez_curves[i].vec[obj->bez_curves[i].deg].y,
obj->bez_curves[i].vec[obj->bez_curves[i].deg].z);
free(v1);
free(v2);
glEnd(); glEnd();
i++; i++;
} }
glPopMatrix(); glPopMatrix();
} }
@ -237,7 +298,8 @@ static void draw_bez(HE_obj const * const obj)
*/ */
static void draw_obj(int32_t const myxrot, static void draw_obj(int32_t const myxrot,
int32_t const myyrot, int32_t const myyrot,
int32_t const myzrot) int32_t const myzrot,
float bez_inc)
{ {
/* rotation */ /* rotation */
static int32_t xrot = 0, static int32_t xrot = 0,
@ -279,7 +341,7 @@ static void draw_obj(int32_t const myxrot,
} }
if (obj->bzc != 0) if (obj->bzc != 0)
draw_bez(obj); draw_bez(obj, bez_inc);
glPopMatrix(); glPopMatrix();
} }
@ -451,7 +513,7 @@ void display(void)
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW); glMatrixMode(GL_MODELVIEW);
draw_obj(0, 0, 0); draw_obj(0, 0, 0, 0);
draw_Planet_1(); draw_Planet_1();
draw_Planet_2(); draw_Planet_2();
@ -616,27 +678,27 @@ void keyboard(unsigned char key, int x, int y)
glutPostRedisplay(); glutPostRedisplay();
break; break;
case 'x': case 'x':
draw_obj(2, 0, 0); draw_obj(2, 0, 0, 0);
glutPostRedisplay(); glutPostRedisplay();
break; break;
case 'X': case 'X':
draw_obj(-2, 0, 0); draw_obj(-2, 0, 0, 0);
glutPostRedisplay(); glutPostRedisplay();
break; break;
case 'y': case 'y':
draw_obj(0, 2, 0); draw_obj(0, 2, 0, 0);
glutPostRedisplay(); glutPostRedisplay();
break; break;
case 'Y': case 'Y':
draw_obj(0, -2, 0); draw_obj(0, -2, 0, 0);
glutPostRedisplay(); glutPostRedisplay();
break; break;
case 'c': case 'c':
draw_obj(0, 0, 2); draw_obj(0, 0, 2, 0);
glutPostRedisplay(); glutPostRedisplay();
break; break;
case 'C': case 'C':
draw_obj(0, 0, -2); draw_obj(0, 0, -2, 0);
glutPostRedisplay(); glutPostRedisplay();
break; break;
case 'D': case 'D':
@ -654,13 +716,22 @@ void keyboard(unsigned char key, int x, int y)
glutPostRedisplay(); glutPostRedisplay();
break; break;
case 'k': case 'k':
draw_normals(obj, 0.01f); draw_obj(0, 0, 0, 0.02);
glutPostRedisplay(); glutPostRedisplay();
break; break;
case 'l': case 'K':
draw_normals(obj, -0.01f); draw_obj(0, 0, 0, -0.02);
glutPostRedisplay(); glutPostRedisplay();
break; break;
/* case 'k': */
/* draw_normals(obj, 0.01f); */
/* glutPostRedisplay(); */
/* break; */
/* case 'l': */
/* draw_normals(obj, -0.01f); */
/* glutPostRedisplay(); */
/* break; */
case 'w': case 'w':
glTranslatef(0.0f, 1.0f, 0.0f); glTranslatef(0.0f, 1.0f, 0.0f);
break; break;

View File

@ -285,6 +285,43 @@ bool normalize_object(HE_obj *obj)
return true; return true;
} }
/**
* Calculate a point on the bezier curve according to the
* bezier vertices. If section is set to 0.5 then it will
* return the vector to the point in the middle of the curve.
*
* @param obj the object holding the bezier vertices information
* @param section the section which will be applied to all
* lines between the bezier vertices
* @return the vector to the calculated point
*/
vector *calculate_bezier_point(bez_curv *bez, float section)
{
vector vec_arr[bez->deg];
bez_curv new_bez;
for (uint32_t i = 0; i < bez->deg; i++) {
vector new_vec;
SUB_VECTORS(&(bez->vec[i + 1]), &(bez->vec[i]), &new_vec);
VECTOR_LEN_SCAL_MUL(&new_vec, section, &new_vec);
ADD_VECTORS(&new_vec, &(bez->vec[i]), &new_vec);
vec_arr[i] = new_vec;
}
new_bez.vec = vec_arr;
new_bez.deg = bez->deg - 1;
if (new_bez.deg > 0) {
return calculate_bezier_point(&new_bez, section);
} else {
vector *result_vector = malloc(sizeof(*result_vector));
*result_vector = vec_arr[0];
return result_vector;
}
}
/** /**
* Free the inner structures of an object. * Free the inner structures of an object.
* *

View File

@ -324,6 +324,7 @@ bool vec_normal(HE_vert const * const vert, vector *vec);
bool find_center(HE_obj const * const obj, vector *vec); bool find_center(HE_obj const * const obj, vector *vec);
float get_normalized_scale_factor(HE_obj const * const obj); float get_normalized_scale_factor(HE_obj const * const obj);
bool normalize_object(HE_obj *obj); bool normalize_object(HE_obj *obj);
vector *calculate_bezier_point(bez_curv *bez, float section);
HE_obj *parse_obj(char const * const filename); HE_obj *parse_obj(char const * const filename);
void delete_object(HE_obj *obj); void delete_object(HE_obj *obj);

View File

@ -33,6 +33,43 @@
#include <stdlib.h> #include <stdlib.h>
/**
* Calculate the vector which lengths is reduced by the
* factor scal and store it in c.
* This function is aliasing safe.
*
* @param a vector
* @param scal scalar to multiply the vector with
* @param c vector [out]
* @return true/false for success/failure
*/
bool vector_len_scal_mul(vector *a, float scal, vector *c)
{
vector a_tmp;
float vector_length;
float factor;
if (!a || !scal || !c)
return false;
copy_vector(a, &a_tmp);
vector_length = sqrt((a_tmp.x * a_tmp.x) +
(a_tmp.y * a_tmp.y) + (a_tmp.z * a_tmp.z));
factor = vector_length * scal;
c->x = a_tmp.x / vector_length;
c->y = a_tmp.y / vector_length;
c->z = a_tmp.z / vector_length;
c->x = c->x * factor;
c->y = c->y * factor;
c->z = c->z * factor;
return true;
}
/** /**
* Calculate the vector product of a and b * Calculate the vector product of a and b
* and store it in c. This function is aliasing safe. * and store it in c. This function is aliasing safe.

View File

@ -31,6 +31,18 @@
#include <stdio.h> #include <stdio.h>
/**
* Fault intolerant macro. Will abort the program if the called
* function failed.
*/
#define VECTOR_LEN_SCAL_MUL(...) \
{ \
if (!vector_len_scal_mul(__VA_ARGS__)) { \
fprintf(stderr, "Failure in vector_product()!\n"); \
abort(); \
} \
}
/** /**
* Fault intolerant macro. Will abort the program if the called * Fault intolerant macro. Will abort the program if the called
* function failed. * function failed.
@ -117,6 +129,7 @@ struct vector {
}; };
bool vector_len_scal_mul(vector *a, float scal, vector *c);
bool vector_product(vector *a, vector *b, vector *c); bool vector_product(vector *a, vector *b, vector *c);
bool add_vectors(vector *a, vector *b, vector *c); bool add_vectors(vector *a, vector *b, vector *c);
bool sub_vectors(vector *a, vector *b, vector *c); bool sub_vectors(vector *a, vector *b, vector *c);