PDA

View Full Version : Really need your help... gluUnProject and revolving bsplines around axis...

BigShooter
11-10-2003, 11:57 PM
I had a simple project in mind: user clicks on screen and bspline is generated. Then that b-spline is swept around (the middle of screen) and a b-spline surface is made. I have done the b-spline functions are they work perfectly. The gluUnProject also works... (but the z values returned are around -93). The problem starts when I try to rotate the curve. I understand that I can just rotate the control points and pass them again to b-spline drawing function and they will draw them correctly.
NOTE: I'm writing my own b-spline routines, not using Opengl ones...
My problem: the spline is rotated weirdly and disappears from the view... Here are my functions:
--------------------------------------------
/************************************************** *****/
/* Multiply a point by a matrix */
/************************************************** *****/
Point3d multPointByMatrix (Point3d p, Matrix3x3 mat) {

float tempZ;
Point3d rp;

/* Get the z value of point */
//tempZ = p.z;
//p.z = 0.0;

rp.x = p.x * mat.n00 + p.y * mat.n01 + p.z * mat.n02;
rp.y = p.x * mat.n10 + p.y * mat.n11 + p.z * mat.n12;
rp.z = p.x * mat.n20 + p.y * mat.n21 + p.z * mat.n22;

/* Add the original z back to the new one */
//p.z += tempZ;

return rp;
}

/************************************************** ****************************************/
/* Rotate a set of points around y axis, given the rotation in degrees */
/************************************************** ****************************************/
void rotatePointsOnY ( float degRotY, Point3d origPts[], Point3d rotatedPts[], int numOfPoints) {

int i;
/* Build rotation matrix */
Matrix3x3 mat;

mat.n00 = cos(degRotY);
mat.n01 = 0.0;
mat.n02 = sin(degRotY);
mat.n10 = 0.0;
mat.n11 = 1.0;
mat.n12 = 0.0;
mat.n20 = -sin(degRotY);
mat.n21 = 0.0;
mat.n22 = cos(degRotY);

for (i = 0; i < numOfPoints; i++) {
rotatedPts[i] = multPointByMatrix (origPts[i], mat);
}

}

My gluUnProject is use just like described in RedBook: (part of my mouse callback function)
case GLUT_LEFT_BUTTON:
if (state == GLUT_DOWN) {

glGetIntegerv (GL_VIEWPORT, viewport);
glGetDoublev (GL_MODELVIEW_MATRIX, mvmatrix);
glGetDoublev (GL_PROJECTION_MATRIX, projmatrix);

/*viewport [3] is height of window in pixels */
/* bottom left of viewport is 0.0, top right is width-1, height -1 */
real_y = viewport[3] - (GLint) y -1;
/*printf ("Coordinates at cursor are (%4d, %4d)\n", x, real_y);*/

/* assume world z coordinate is z = 1.0 */
gluUnProject ((GLdouble) x, (GLdouble) real_y, 1.0, mvmatrix, projmatrix, viewport, &wx, &wy, &wz);
/*printf ("world coords at z=1.0 are (%f, %f, %f)\n", wx, wy, wz);*/

wz, wy and wz are then used to create the new points in control point array that is used to calculate b-splines
--------------------------------------------
Matrix and point definitions are as following:

typedef struct {
float x, y, z;
} Point3d;

typedef struct {
float n00, n01, n02;
float n10, n11, n12;
float n20, n21, n22;
} Matrix3x3;

I've spent two days trying to find the bug....
I know it must be in the way I'm handling either the unProject or doing the rotation...

Your help is invaluable to me...
Thank you,
Luke

BigShooter
11-10-2003, 11:59 PM
Just to add to this, the b-spline is actually rotated (swept) 360 degrees around y axis. For instance, a wine glass profile when quickly rotated would generate a 'trace' of a wine glass.

BigShooter
11-11-2003, 12:04 AM
Shoot, one more thing...
I CAN'T USE OPENGL glRotated(..) function. I must actually rotate the control points on the bspline as they will be then used to calculate triangles that would make up the surface.
I.e. the algorithm would be
- 2 curves
- trace both changing the t values and write out the coordinates of the points etc...
So I must actually write my own rotation...
At least I think I do :-)
?
Thanks again,
Luke

BigShooter
11-11-2003, 01:49 AM
And for those who really want to help, but the code gives is not enough, here's the full source code of my mini project :-)

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <GL/glut.h>

#define MAX_CTRL_POINTS 50 /* Maximum control points for b-spline curve */
#define WIN_WIDTH 640 /* Dimentions of Opengl window */
#define WIN_HEIGHT 480
#define CURVE_STEP 0.005 /* This represents the resolution of the b-spline on screen. The smaller the value, the smoother the curve */

/* Helper macros */
#define PI (3.14159265359f)

/************************************************** *******************/
/* Structure to hold 3d point */
/************************************************** *******************/
typedef struct {
float x, y, z;
} Point3d;

/************************************************** *******************/
/* Structure to hold a triangle */
/************************************************** *******************/
typedef struct {
/* 3 points that make up the triangle */
/* POINTS MUST BE IN COUNTER CLOCKWISE ORDER !!! */
Point3d p1;
Point3d p2;
Point3d p3;
/* Triangle normal - represented as point, but is really a 3d vector, which is normalized */
Point3d normal;
} Triangle;

/************************************************** *******************/
/* Structure defining a 3x3 matrix */
/************************************************** *******************/
typedef struct {
float n00, n01, n02;
float n10, n11, n12;
float n20, n21, n22;
} Matrix3x3;

/************************************************** *******************/
/* GLOBAL VARIABLES */
/************************************************** *******************/

int numOfCtrlPoints = 0;
Point3d ctrlPoints [MAX_CTRL_POINTS];
Point3d rotatedCtrlPoints[MAX_CTRL_POINTS];
Point3d newPoint;

float max_t; /* holds the maximum t value from the knot vector */
int order = 4; /* Holds the order of the spline */

/* function prototypes */
void drawPoints ();
void drawBspline (float tInit, float tEnd, float stepInT, Point3d ctrls[], int numOfCtrls);
Point3d triangleNormal(Triangle tri);
void rotatePointsOnY ( float degY, Point3d origPts[], Point3d rotatedPts[], int numOfPoints);

/************************************************** *******************/
void glInit(void) {

/****** FOR PROGRAM 2 ******/
/* Setup for the lights: */
float ambientLight[] = { 0.5f, 0.5f, 0.5f, 1.0f}; /* Redish ambient light */
float diffuseLight[] = { 0.7f, 0.7f, 0.7f, 1.0f};
/* Position is the same as the camera position */
float lightPosition[] = { 0.0f, 0.0f, 5.0f, 0.0f};
/* Setup materials*/
float matAmbient[] = { 0.5f, 0.5f, 0.5f, 1.0f };
float matDiff[] = { 0.8f, 0.6f, 0.8f, 1.0f };
/****** END FOR PROGRAM 2 ****/

glClearColor (0.0, 0.0, 0.0, 0.0);
glPointSize(5.0f);

/****** FOR PROGRAM 2 ******/
/* Turn on z-buffer */
glEnable(GL_DEPTH_TEST);
/* Turn on the backface culling */
glEnable(GL_CULL_FACE);
/* COUTERCLOCKWISE polygons and triangle faces are kept */
glFrontFace(GL_CCW);

glEnable(GL_LIGHTING);
glMaterialfv(GL_FRONT, GL_AMBIENT, matAmbient);
glMaterialfv(GL_FRONT, GL_DIFFUSE, matDiff);

/* Setup LIGHT0 */
glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight);
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight);
glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);

/* Enable the light */
glEnable(GL_LIGHT0);

/* Turn on auto normalization of normal vectors for Opengl */
glEnable(GL_NORMALIZE);
/****** END FOR PROGRAM 2 ****/

printf("\nWelcome to this amazing b-spline drawing program! \n");
printf("It currently allows for up to 50 control points.\n");
printf("Pressing '2', '3', '4', or '5' on keyboard \n");
printf(" will make the spline change to that order.\n");
printf(" The default order is 4, making the spline cubic.\n");
printf("Notice that spline of order 5 will need at least 5 control points to be visible\n");
printf("To make a curve sharp at a certain point (to interpolate through that point\n");
printf(" click a few times on that point. The more you click it,the sharper it gets! :-) \n");
printf("Pressing 'd' on the keyboard while drawing the curve\n");
printf(" will delete the last point of curve.\n");
printf("Pressing 'q' will quit the program. \n");

}

/************************************************** *******************/
void display(void) {

Triangle tri;

/*Clear the screen */
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glColor3f(1.0, 1.0, 1.0);
gluLookAt (0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);

/* These are for testing only */
glutWireCube(3.0);

/***************************** Testing code for triangles ************************/

tri.p1.x = -5.0;
tri.p1.y = 5.0;
tri.p1.z = -50.0;

tri.p2.x = -5.0;
tri.p2.y = -5.0;
tri.p2.z = -50.0;

tri.p3.x = 5.0;
tri.p3.y = -5.0;
tri.p3.z = -40.0;

tri.normal = triangleNormal( tri);

glBegin(GL_TRIANGLES);
glNormal3f(tri.normal.x, tri.normal.y, tri.normal.z);
glVertex3f(tri.p1.x, tri.p1.y, tri.p1.z);
glVertex3f(tri.p2.x, tri.p2.y, tri.p2.z);
glVertex3f(tri.p3.x, tri.p3.y, tri.p3.z);
glEnd();

/********************* End of Testing code for triangles ************************/

/*Draw points in red, spline in blue */
glColor3f(1.0, 0.0, 0.0);
drawPoints();
glColor3f(0.0, 0.0, 1.0);
drawBspline ( 0.0, max_t, CURVE_STEP, ctrlPoints, numOfCtrlPoints);

/********************** Test code for rotation on curve **************************/

rotatePointsOnY ( 100.0, ctrlPoints, rotatedCtrlPoints, numOfCtrlPoints);
drawBspline ( 0.0, max_t, CURVE_STEP, rotatedCtrlPoints, numOfCtrlPoints);

/************** End of Test code for rotation on curve **************************/

glFlush();

glutSwapBuffers();
glutPostRedisplay();

}
/************************************************** *******************/
/* callback function to handle keyboard input */
/************************************************** *******************/
void keyboard(unsigned char key, int x, int y) {

/* Quit on any key */
switch (key) {

case 'q':
exit(0);
case '2':
order = 2;
break;
case '3':
order = 3;
break;
case '4':
order = 4;
break;
case '5':
order = 5;
break;
case 'd':
if (numOfCtrlPoints > order)
numOfCtrlPoints -= 1;
else
printf("\n Can't delete a point where number of control points < order of curve!\n");
break;
default:
break;
}

}
/************************************************** *******************/
/* Callback function to handle the mouse */
/************************************************** *******************/
void mouse (int button, int state, int x, int y) {

GLint viewport [4]; /*holds the viewport data*/
GLdouble mvmatrix[16], projmatrix[16];
GLint real_y; /*OpenGL y coordinate position */
GLdouble wx, wy, wz; /* returned world x, y, z coords */

switch (button) {
case GLUT_LEFT_BUTTON:
if (state == GLUT_DOWN) {

glGetIntegerv (GL_VIEWPORT, viewport);
glGetDoublev (GL_MODELVIEW_MATRIX, mvmatrix);
glGetDoublev (GL_PROJECTION_MATRIX, projmatrix);

/*viewport [3] is height of window in pixels */
/* bottom left of viewport is 0.0, top right is width-1, height -1 */
real_y = viewport[3] - (GLint) y -1;
/*printf ("Coordinates at cursor are (%4d, %4d)\n", x, real_y);*/

/* assume world z coordinate is z = 1.0 */
gluUnProject ((GLdouble) x, (GLdouble) real_y, 1.0, mvmatrix, projmatrix, viewport, &wx, &wy, &wz);
/*printf ("world coords at z=1.0 are (%f, %f, %f)\n", wx, wy, wz);*/

/* check to see if not max number of control points */
if (numOfCtrlPoints < MAX_CTRL_POINTS ) {

numOfCtrlPoints++;

/* write to newPoint */
newPoint.x = wx;
newPoint.y = wy;
newPoint.z = wz;

/* add to array of control points */

ctrlPoints[numOfCtrlPoints-1] = newPoint;
}
else
printf ("\n MAXIMUM NUMBER OF CONTROL POINTS (%d) REACHED ! \n", MAX_CTRL_POINTS);

}
break;
default:
break;
}

}

/************************************************** *******************/
/* Callback function to change the Viewport on resizing the screen */
/************************************************** *******************/
void reshape ( int w, int h) {

glViewport (0,0, (GLsizei)w, (GLsizei)h);
glMatrixMode(GL_PROJECTION);
gluPerspective(45.0, (GLfloat) w / (GLfloat) h, 1.0, 100);
glMatrixMode(GL_MODELVIEW);
}

/************************************************** *******************/
/* draw points */
/************************************************** *******************/
void drawPoints () {

int i;
glBegin (GL_POINTS);
for (i = 0; i < numOfCtrlPoints; i++) {
glVertex3f(ctrlPoints[i].x, ctrlPoints[i].y, ctrlPoints[i].z);
}
glEnd();
}

/************************************************** *******************/
/* Generates standard knot vector for given values of m and L */
/* Source of code: 'Computer graphics using Opengl' by F.S.Hill */
/************************************************** *******************/
void buildKnots (int m, int L, float knotV []) {
/* Builds the standard knot vector for L + 1 control points
and b-spline of order m */
int i;
/* For a given m, there must be a sufficient number of control point */
if (L < (m - 1)) return; /* Too few control points */
for ( i = 0; i <= L + m; i++ ) {
if (i < m) knotV[i] = 0.0;
else if (i <= L)
knotV[i] = i - m + 1; /*i is at least m */
else knotV[i] = L - m + 2; /* i exceeds L */
}
/* set the gloabal variable holding maximum value of t in knot vector*/
max_t = knotV[L+m];
}

/************************************************** *******************/
/* Function to calculate recursive formulation of Nk,m(t) */
/* Source of code: 'Computer graphics using Opengl' by F.S.Hill */
/************************************************** *******************/
float bSpline (int k, int m, float t, float knotV []) {

float denom1, denom2, sum = 0.0;
if (m == 1)
return (t >= knotV[k] && t < knotV[k+1]); /* return 1 or 0 */
/* if m exceeds 1, use recursion */
denom1 = knotV[k+m-1] - knotV[k];
if (denom1 != 0.0)
sum = (t - knotV[k]) * bSpline (k, m-1, t, knotV) / denom1;
denom2 = knotV[k+m] - knotV[k+1];
if (denom2 != 0.0)
sum += (knotV[k+m] - t) * bSpline(k+1, m-1, t, knotV) / denom2;
return sum;
}

/************************************************** *******************/
/* Calculates a 3d point given t and array of control points */
/************************************************** *******************/
Point3d pointOnBspline (float t, Point3d ctrls[], int numOfCtrls) {

Point3d calculatedPoint;
int k;
float bsplineVal;
float knots[MAX_CTRL_POINTS+10];

buildKnots (order, numOfCtrls-1,knots);

calculatedPoint.x = 0.0;
calculatedPoint.y = 0.0;

for (k = 0; k < numOfCtrls; k++ ) {

bsplineVal = bSpline(k, order, t, knots);
calculatedPoint.x += ctrls[k].x * bsplineVal;
calculatedPoint.y += ctrls[k].y * bsplineVal;

}

calculatedPoint.z = ctrls[0].z; /* Should be able to get any value of z points. Assuming they will all line up on z axis */
return calculatedPoint;

}

/************************************************** ********************************/
/* Draw a bSpline curve, given range of t, step - resolution, and control points */
/************************************************** ********************************/
void drawBspline (float tInit, float tEnd, float stepInT, Point3d ctrls[], int numOfCtrls) {

Point3d tempPoint;

glBegin(GL_LINE_STRIP);
while (tInit <= tEnd) {
tempPoint = pointOnBspline(tInit, ctrls, numOfCtrls);
glVertex3f(tempPoint.x, tempPoint.y, tempPoint.z);
tInit += stepInT;
}
glEnd();
}

/************************************************** *******************************************/
/* Take cross product of 2 vectors - in this example Point 3d structur is treated as vector */
/************************************************** *******************************************/
Point3d crossProd (Point3d a, Point3d b) {

Point3d crossPVec;
crossPVec.x = a.y*b.z - a.z*b.y;
crossPVec.y = a.z*b.x - a.x*b.z;
crossPVec.z = a.x*b.y - a.y*b.x;

/* Note, normally this would have to be normalized, but we will use the GL_NORMALIZE to do it for us */
return crossPVec;
}

/************************************************** ***************/
/* Calculate normal of a triangle */
/************************************************** ***************/
Point3d triangleNormal(Triangle tri) {

Point3d vector1, vector2, normal;

/* Calculate the two vector that we need to calculate the cross product */
vector1.x = tri.p1.x - tri.p2.x;
vector1.y = tri.p1.y - tri.p2.y;
vector1.z = tri.p1.z - tri.p2.z;

vector2.x = tri.p2.x - tri.p3.x;
vector2.y = tri.p2.y - tri.p3.y;
vector2.z = tri.p2.z - tri.p3.z;

normal = crossProd(vector1, vector2);

return normal;

}

/************************************************** *****/
/* Multiply a point by a matrix */
/************************************************** *****/
Point3d multPointByMatrix (Point3d p, Matrix3x3 mat) {

float tempZ;
Point3d rp;

/* Get the z value of point */
//tempZ = p.z;
//p.z = 0.0;

rp.x = p.x * mat.n00 + p.y * mat.n01 + p.z * mat.n02;
rp.y = p.x * mat.n10 + p.y * mat.n11 + p.z * mat.n12;
rp.z = p.x * mat.n20 + p.y * mat.n21 + p.z * mat.n22;

/* Add the original z back to the new one */
//p.z += tempZ;

return rp;
}

/************************************************** ****************************************/
/* Rotate a set of points around y axis, given the rotation in degrees */
/************************************************** ****************************************/
void rotatePointsOnY ( float degRotY, Point3d origPts[], Point3d rotatedPts[], int numOfPoints) {

int i;
/* Build rotation matrix */
Matrix3x3 mat;

/* Convert degrees to radians */

mat.n00 = cos(degRotY);
mat.n01 = 0.0;
mat.n02 = sin(degRotY);
mat.n10 = 0.0;
mat.n11 = 1.0;
mat.n12 = 0.0;
mat.n20 = -sin(degRotY);
mat.n21 = 0.0;
mat.n22 = cos(degRotY);

//mat.n00 = cos(degRotY);
//mat.n01 = 0.0;
//mat.n02 = -sin(degRotY);
//mat.n10 = 0.0;
//mat.n11 = 1.0;
//mat.n12 = 0.0;
//mat.n20 = sin(degRotY);
//mat.n21 = 0.0;
//mat.n22 = cos(degRotY);

for (i = 0; i < numOfPoints; i++) {
rotatedPts[i] = multPointByMatrix (origPts[i], mat);
}

}

/************************************************** *******************/
int main(int argc, char** argv) {

/* Standard glut application framework */
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize (WIN_WIDTH, WIN_HEIGHT);
glutInitWindowPosition (100, 100);
glutCreateWindow("CS 388 Assignment#3 by Luke Piasecki and Grzesiek Stozek");
glInit();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard);
glutMouseFunc(mouse);

glutMainLoop();

return 0;

}
/************************************************** *******************/
/************************************************** *******************/

gator
11-11-2003, 07:54 AM
("CS 388 Assignment#3 by Luke Piasecki and Grzesiek Stozek");

Ah, so you want someone else to do your homework?

BigShooter
11-11-2003, 09:32 AM
No, I've done most of the homework.
I'm asking for someone to help me and point out what am I doing wrong :-)
BTW, it's not the assignment anymore. I've done much more in this one that was requested...

BigShooter
11-11-2003, 02:06 PM
Please disregard this post. I've found what I've done wrong! :-)
IT was here:
/* Get the z value of point */
tempZ = p.z;
p.z = 0.0;

rp.x = p.x * mat.n00 + p.y * mat.n01 + p.z * mat.n02;
rp.y = p.x * mat.n10 + p.y * mat.n11 + p.z * mat.n12;
rp.z = p.x * mat.n20 + p.y * mat.n21 + p.z * mat.n22;

/* Add the original z back to the new one */
p.z += tempZ; <- I should be adding this to rp, not p :-)

rgpc
11-11-2003, 07:18 PM
Originally posted by gator:
Ah, so you want someone else to do your homework?

No, they want an answer to a maths question on an Advanced OpenGL forum.

knackered
11-11-2003, 10:06 PM
BigShooter, what's this glut.h you're using?
Please post the contents of this file so we can resolve your problem.

Spurkey
11-12-2003, 08:55 AM
glut.h comes from here:
http://www.opengl.org/developers/documentation/glut/

BigShooter
11-12-2003, 10:27 AM
I'm using the latest glut I've downloaded from the web. Ogl is on WinXP.
As I said though, I've fixed the problem.
For those who made sarcastic comments about my question. First of all, yet it was a math question on ogl forum, but a lot of math questions pop up here as graphics and math usually go together. I thought that a lot of people here could help me. Sorry for that.
As to someone doing my homework, it wasn't a homework. The window title was simply bacause I compied the glut backbone from previous assignment. But wheather or not it is homework, I don't think it makes a difference.
I wasn't asking for anyone to do it for me. I was asking a question, related to graphics. I was having trouble. I really don't think that wheather it is an assignments, project, exam, commerical project or personal, should make any difference. For those who think otherwise, simply don't reply :-)

Sorry, had to say that. For others, thank you for your constant help with my questions.

Luke

Coconut
11-12-2003, 10:46 AM
Originally posted by BigShooter:
I really don't think that wheather it is an assignments, project, exam, commerical project or personal, should make any difference. For those who think otherwise, simply don't reply :-)
Luke

I agree with you 100%, and that's why I am replying. It doesn't matter whether it is an assignment or not. When someone posts two-hundred lines of code and asks for help, I simply won't look at it at all. For those who think otherwise, simply don't reply.