我正在尝试使用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。
答案 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之前。