Я работаю над текущим проектом, где я хочу выровнять звенья цепи так, чтобы она соответствовала контурам кривой Безье. В настоящее время я выполняю следующие шаги.Как повернуть объект вокруг локальной оси в OpenGL?
- Рисование кривой.
- Используйте список отображения, чтобы создать одну ссылку на цепочку.
- Используйте цикл FOR для многократного вызова функции, которая вычисляет угол между двумя точками на кривой, возвращает угол и ось, вокруг которой должна быть повернута линия.
- Поверните на угол «a» и переведите на новое место, поместите ссылку в новое положение.
Редактировать: Я также должен сказать, что центры двух полутор должны лежать на кривой Безье. Также я знаю, что метод, который я использую для рисования тора, я утомительно, позже я буду использовать TRIANGLE_FAN или QUAD_STRIP, чтобы более эффективно рисовать тор.
Хотя на первый взгляд эта логика выглядит так, что она будет правильно изображать цепочку, конечный результат - это не то, что я себе представлял. Вот картина того, как выглядит цепочка.
Я читал, что вы должны перевести объект в начало координат до поворота? Я бы просто вызвал glTranslate (0,0,0), а затем выполнил шаг 4 сверху?
Я включил соответствующий код из того, что я сделал до сих пор, я был бы признателен за любые предложения, которые помогут мне правильно работать с кодом.
/* this function calculates the angle between two vectors oldPoint and new point contain the x,y,z coordinates of the two points,axisOfRot is used to return the x,y,z coordinates of the rotation axis*/
double getAxisAngle(pointType oldPoint[],
pointType newPoint[],pointType axisOfRot[]){
float tmpPoint[3];
float normA = 0.0,normB = 0.0,AB = 0.0,angle=0.0;
int i;
axisOfRot->x= oldPoint->y * newPoint->z - oldPoint->z * newPoint->y;
axisOfRot->y= oldPoint->z * newPoint->x - oldPoint->x * newPoint->z;
axisOfRot->z= oldPoint->x * newPoint->y - oldPoint->y * newPoint->x;
normA=sqrt(oldPoint->x * oldPoint->x + oldPoint->y * oldPoint->y + oldPoint->z *
oldPoint->z);
normB=sqrt(newPoint->x * newPoint->x + newPoint->y * newPoint->y + newPoint->z *
newPoint->z);
tmpPoint[0] = oldPoint->x * newPoint->x;
tmpPoint[1] = oldPoint->y * newPoint->y;
tmpPoint[2] = oldPoint->z * newPoint->z;
for(i=0;i<=2;i++)
AB+=tmpPoint[i];
AB /= (normA * normB);
return angle = (180/PI)*acos(AB);
}
/* this function calculates and returns the next point on the curve give the 4 initial points for the curve, t is the tension of the curve */
void bezierInterpolation(float t,pointType cPoints[],
pointType newPoint[]){
newPoint->x = pow(1 - t, 3) * cPoints[0].x +3 * pow(1 - t , 2) * t * cPoints[1].x + 3
* pow(1 - t, 1) * pow(t, 2) * cPoints[2].x + pow(t, 3) * cPoints[3].x;
newPoint->y = pow(1 - t, 3) * cPoints[0].y +3 * pow(1 - t , 2) * t * cPoints[1].y + 3
* pow(1 - t, 1) * pow(t, 2) * cPoints[2].y + pow(t, 3) * cPoints[3].y;
newPoint->z = pow(1 - t, 3) * cPoints[0].z +3 * pow(1 - t , 2) * t * cPoints[1].z + 3
* pow(1 - t, 1) * pow(t, 2) * cPoints[2].z + pow(t, 3) * cPoints[3].z;
}
/* the two lists below are used to create a single link in a chain, I realize that creating a half torus using cylinders is a bad idea, I will use GL_STRIP or TRIANGLE_FAN once I get the alignment right
*/
torusList=glGenLists(1);
glNewList(torusList,GL_COMPILE);
for (i=0; i<=180; i++)
{
degInRad = i*DEG2RAD;
glPushMatrix();
glTranslatef(cos(degInRad)*radius,sin(degInRad)*radius,0);
glRotated(90,1,0,0);
gluCylinder(quadric,Diameter/2,Diameter/2,Height/5,10,10);
glPopMatrix();
}
glEndList();
/*! create a list for the link , 2 half torus and 2 columns */
linkList = glGenLists(1);
glNewList(linkList, GL_COMPILE);
glPushMatrix();
glCallList(torusList);
glRotatef(90,1,0,0);
glTranslatef(radius,0,0);
gluCylinder(quadric, Diameter/2, Diameter/2, Height,10,10);
glTranslatef(-(radius*2),0,0);
gluCylinder(quadric, Diameter/2, Diameter/2, Height,10,10);
glTranslatef(radius,0, Height);
glRotatef(90,1,0,0);
glCallList(torusList);
glPopMatrix();
glEndList();
Наконец вот код для создания трех звеньев в цепи
t=0.031;
bezierInterpolation(t,cPoints,newPoint);
a=getAxisAngle(oldPoint,newPoint,axisOfRot);
glTranslatef(newPoint->x,newPoint->y,newPoint->z);
glRotatef(a,axisOfRot->x,axisOfRot->y,axisOfRot->z);
glCallList(DLid);
glRotatef(-a,axisOfRot->x,axisOfRot->y,axisOfRot->z);
glTranslatef(-newPoint->x,-newPoint->y,-newPoint->z);
oldPoint[0]=newPoint[0];
bezierInterpolation(t+=GAP,cPoints,newPoint);
a=getAxisAngle(oldPoint,newPoint,axisOfRot);
glTranslatef(newPoint->x,newPoint->y,newPoint->z);
glRotatef(90,0,1,0);
glRotatef(a,axisOfRot->x,axisOfRot->y,axisOfRot->z);
glCallList(DLid);
glRotatef(-a,axisOfRot->x,axisOfRot->y,axisOfRot->z);
glRotatef(90,0,1,0);
glTranslatef(-newPoint->x,-newPoint->y,-newPoint->z);
oldPoint[0]=newPoint[0];
bezierInterpolation(t+=GAP,cPoints,newPoint);
a=getAxisAngle(oldPoint,newPoint,axisOfRot);
glTranslatef(newPoint->x,newPoint->y,newPoint->z);
glRotatef(-a,axisOfRot->x,axisOfRot->y,axisOfRot->z);
glCallList(DLid);
glRotatef(a,axisOfRot->x,axisOfRot->y,axisOfRot->z);
glTranslatef(-newPoint->x,-newPoint->y,newPoint->z);
Моя программа уже содержит инструкцию MODELVIEW, которая задана в функции main(). Как я уже отметил в комментарии к этому отображению Список «Я понимаю, что создание полутора тора с использованием цилиндров - это плохая идея, я буду использовать GL_STRIP или TRIANGLE_FAN, как только я получу выравнивание справа ". Использование только тора не сделает цепочку реалистичной, поэтому вы можете создать цепочку, используя два полутора тора и два цилиндра. Для упрощения этой статьи я упростил программу, забрав цикл for и большую часть функции main(). благодарит за вашу помощь. – NeatRobot
Так вы правильно определили способ перевода и ротации? – Ketan
Нет, я попробовал Переместить исходную ссылку на начало координат с помощью glTranslatef (0,0,0); а затем вызов glRotate(); за которым следует glTranslate() в исходное положение, а затем передавая ссылку, но у меня по-прежнему есть та же проблема, что и центры двух половинных торов, не находящиеся на кривой. – NeatRobot