在旧的opengl中绘制具有定义的中心和轴的圆柱体

时间:2015-10-28 16:22:42

标签: c++ opengl freeglut

我正在尝试使用freeglut的glutSolidCylinder在我给出的位置和轴上绘制一个圆柱体。

我想要的是这样的功能:

void DrawCylinder(float radius,float height,Vector3 center,Vector3 axis)

这样

DrawCylinder(0.5,0.5, Vector3(0.5,0.5,0), Vector3(0,1,0)) 

将绘制一个圆心,其中心为(0.5,0.5,0),其轴沿y轴。

我需要这个函数是通用的,即无论我给它的位置和轴是什么,我都找到了this相关的问题,这个问题非常具体。

这是我被困的地方:

#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;
}

修改

我在这里做的是围绕指定轴和z轴的叉积旋转圆柱体,其角度等于两个矢量之间的角度,并且在旋转之后我将圆柱体从其位置平移旋转到指定中心后居中。

不幸的是,这不起作用,当我尝试沿着y轴在(0,0,0)绘制它时,它被定位(0,0,0)(可能是(0,0.25,0)) ,旋转部分按预期工作,它只是不起作用的翻译部分。

那我该怎么办?

注意

现在我必须使用旧的opengl。

1 个答案:

答案 0 :(得分:0)

我的问题解决了,这就是功能:

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();
}

我只需要把glTranslatef放在glRotatef之前。