-2

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.

Community
  • 1
  • 1
niceman
  • 2,653
  • 29
  • 57
  • 2
    So where are you stuck? There is no question in this question. – BDL Oct 28 '15 at 16:44
  • It's not exactly the same question, but the basic problem is the same as the one here: http://stackoverflow.com/questions/24705225/opengl-rotation-from-velocity-vector. My answer there shows how to calculate a rotation matrix from a orientation vector. The translation part will hopefully be obvious. – Reto Koradi Oct 29 '15 at 04:05
  • see http://stackoverflow.com/a/25182327/2521214 and look how I make the `glCircle3D` function .... you just compute vertexes of 2 such circles and render as 2 triangle fans and 1 quad strip .... where the second circle has `position` shifted by `height * normal` vector – Spektre Oct 29 '15 at 09:46

1 Answers1

0

my problem is solved, this is the function :

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);
    center-=pos;
    glPushMatrix();
    glTranslatef(center.X(),center.Y(),center.Z());
    glRotatef(theta,axis.Y(),axis.X(),0);
    glutSolidCylinder(radius,height,50,50);
    glPopMatrix();
}

I just had to put glTranslatef before glRotatef.

niceman
  • 2,653
  • 29
  • 57