I'm trying to draw a cylinder using freeglut's glutSolidCylinder in a position and axis that I give.
What I want here is a function like this :
void DrawCylinder(float radius,float height,Vector3 center,Vector3 axis)
such that
DrawCylinder(0.5,0.5, Vector3(0.5,0.5,0), Vector3(0,1,0))
will draw a cylinder whose center is (0.5,0.5,0)
and its axis is along the y-axis.
I need this function to be general, that is to work whatever position and axis I give it, I found this related question which is very specific.
here is where I'm stuck:
#include <iostream>
#include <GL/freeglut.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <cmath>
#define PI 3.141592653589f
#define PIdiv180 (PI/180.0f)
class Vector3
{
private:
float x,y,z;
public:
Vector3(float coordx=0,float coordy=0,float coordz=0)
: x(coordx),y(coordy),z(coordz){}
Vector3(const Vector3 &v) : x(v.x),y(v.y),z(v.z){}
float X() const { return x; }
float Y() const { return y; }
float Z() const { return z; }
float length() const { return sqrt(x*x+y*y+z*z); }
float operator*(const Vector3 &v) const
{
return x*v.x+y*v.y+z*v.z;
}
static float anglebetweeninradian(const Vector3 &v1,const Vector3 &v2)
{
return acos((v1*v2)/(v1.length()*v2.length()));
}
Vector3 operator-(const Vector3 &other) const
{
return Vector3(x-other.x,y-other.y,z-other.z);
}
Vector3 &operator =(const Vector3& other)
{
x=other.x;
y=other.y;
z=other.z;
return *this;
}
Vector3 &operator -=(const Vector3& other)
{
x-=other.x;
y-=other.y;
z-=other.z;
return *this;
}
Vector3 Rotate(Vector3 v,const float &theta1) const
{
float a = 0, b = 0, c = 0;
float theta=(float)(theta1*PIdiv180);
a=(cos(theta)+(v.x*v.x)*(1-cos(theta)))*x;
a+=(v.x*v.y*(1-cos(theta))-v.z*sin(theta))*y;
a+=(v.x*v.z*(1-cos(theta))+v.y*sin(theta))*z;
b=(v.y*v.x*(1-cos(theta))+v.z*sin(theta))*x;
b+=(cos(theta)+v.y*v.y*(1-cos(theta)))*y;
b+=(v.y*v.z*(1-cos(theta))-v.x*sin(theta))*z;
c=(v.z*v.x*(1-cos(theta))-v.y*sin(theta))*x;
c+=(v.z*v.y*(1-cos(theta))+v.x*sin(theta))*y;
c+=(cos(theta)+v.z*v.z*(1-cos(theta)))*z;
return Vector3(a, b, c);
}
};
using namespace std;
void DrawCylinder(float radius,float height,Vector3 center,Vector3 axis)
{
Vector3 pos=Vector3(0,0,height/2);
float theta=Vector3::anglebetweeninradian(axis,Vector3(0,0,1))/PIdiv180;
pos=pos.Rotate(Vector3(axis.Y(),axis.X(),0),theta);
glPushMatrix();
glRotatef(theta,axis.Y(),axis.X(),0);
center-=pos;
glTranslatef(center.X(),center.Y(),center.Z());
glutSolidCylinder(radius,height,50,50);
glPopMatrix();
}
void idle(void)
{
glutPostRedisplay();
}
void display()
{
glClear(GL_DEPTH_BUFFER_BIT);
glColor3f(1,0,0);
glLoadIdentity();
DrawCylinder(0.5,0.5,Vector3(0,0,0),Vector3(0,-1,0));
glutSwapBuffers();
}
void init()
{
glClearColor(1, 1, 1, 1);
glEnable(GL_LIGHTING);
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHT0);
const GLfloat light_ambient[] = { 1.0f, 1.0f, 1.0f, 0.0f };
const GLfloat light_diffuse[] = { 1.0f, 1,1, 1.0f };
const GLfloat light_specular[] = { 1.0f, 1.0f, 1.0f, 1.0f };
const GLfloat light_position[] = { 0.0f, 1, 0.0f, 1.0f };
const GLfloat light_shininess[] = { 50.0f };
const GLfloat light_emissive[] = { 1, -1, 1, 0 };
glEnable(GL_COLOR_MATERIAL);
glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
glLightfv(GL_LIGHT0, GL_EMISSION, light_emissive);
glMaterialfv(GL_FRONT, GL_SPECULAR, light_specular);
glMaterialfv(GL_FRONT, GL_SHININESS, light_shininess);
}
int main(int argc,char *argv[])
{
glutInit(&argc,argv);
glutInitWindowSize(640,480);
glutInitWindowPosition(300,200);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
glutCreateWindow("FoosBall");
glutDisplayFunc(display);
glutIdleFunc(idle);
init();
glutMainLoop();
return 0;
}
EDIT
What I'm doing here is rotate the cylinder around the cross product of the specified axis and the z-axis with angle equal to the angle between the two vectors, and after the rotation I translate the cylinder from the position of its center after rotation to the center specified.
Unfortunately this didn't work , when I try to draw it at (0,0,0) along the y-axis it gets positioned up (0,0,0) (maybe (0,0.25,0)),the rotation part works as expected, it's just the translation part that doesn't work.
So what should I do ?
Note
For Now I have to use the old opengl.