我想做一个简单的3D机械臂使用搅拌机。目前我可以导入obj文件和纹理,旋转,平移和缩放。
问题:为了简化,机械臂将有3个部分,底座(旋转的圆柱体)和两个长方体。我对旋转卷发机和长方体没有问题。但这两个长方体必须连接在一起,我不知道该怎么做。当第一个长方体旋转时,我可以使用简单的正弦函数和余弦函数来计算第二个长方体的位置,但我不知道如何测量物体的长度。
第二个问题:我可以在一个obj文件中导出所有3个对象,然后在openGL中对它们进行分割吗?

发布于 2015-04-17 00:45:40
你还没有回复评论,但我想我还是把这段代码贴出来吧。我写这篇文章是为了在OpenGL中渲染一个3D机器手。我有所有手指和手的搅拌器模型文件(由其他人制作),我将它们单独导出到.obj文件中。
最终结果可以在here中看到。如您所见,我还添加了使用鼠标更改视点的功能。我通过反复试验的方法确定了手指指骨的偏移量,但也许您可以使用here中描述的Blender找到点之间的偏移量。我现在不能测试它,因为我的工作电脑上没有Blender。
下面的代码描述了我实现这一点的过程。我把它拆开了,这样我就可以写一些解释了,但是把所有的片段按顺序放在一起,就会生成我的完整函数,来绘制一个连接到手上的single finger。
我的绘图函数以如下方式开始:
double t_x, t_y, t_z;
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); // Clear screen and depth buffer
glLoadIdentity();
// Set viewpoint:
gluLookAt(eyex+3.0f, eyey+3.0f, eyez+3.0f, focusx, focusy, focusz, 0, 1, 0);
glPushMatrix();
glRotatef(g_xRotation, 0,1,0); // Rotate with mouse (g_x and g_y are determined elsewhere)
glRotatef(g_yRotation, 1,0,0);现在我们已经在原点上设置好了(根据鼠标的指示旋转),我们可以从绘制手掌开始。不需要移位(它位于原点)。
// DRAW PALM
glColor3f(1.0f, 1.0f, 1.0f); // Use proper color - white
palmHand -> draw();手掌渲染完成后,我们开始绘制第一个手指。翻译中的1.87f是通过实验确定的。这里的值还取决于我从Blender导出项目的质量,但一旦导出一次,它就不会改变。(实际上,我对我给自己留下的相当自满的评论感到相当惊讶--这段代码已经有几年的历史了)。指骨仅绕一个轴旋转,旋转值(角度)存储在f_p[]中。
// DRAW FINGER 1
// CONSTANT: Move to first vertex
glTranslatef(0.0f, 0.0f, 1.87f);
glRotatef(f_p[0].theta, 0, 0, 1); // Do rotation for phalanx 1 with specified angle
glColor3f(16.0f/255.0f, 78.0f/255.0f, 139.0f/255.0f); // Use proper color - blue
phalanx1Hand -> draw();
// CONSTANT: Necessary adjustment because of model file offset (nobody's perfect, okay?)
glTranslatef(0.0f, 0.03f, 0.0f);绘制第二个(中间)方阵的过程与绘制底部方阵的过程相同,只是它绕不同的轴旋转。
// CONSTANT: Move to second vertex
glTranslatef(1.3f, 0.0f, 0.0f);
glRotatef(f_p[1].theta, 0, 1, 0); // Do rotation for phalanx 2 with specified angle
phalanx2Hand -> draw();2号方阵没有额外的偏移量,因为我猜当我从Blender中导出它时,我正确地排列了模型。
// CONSTANT: Rotate to third vertex
glRotatef(-90.0f, 0, 1, 0);
// CONSTANT: Move to third vertex
glTranslatef(2.0f, 0.0f, 0.0f);
glRotatef(f_p[2].theta, 0, 1, 0); // Do rotation for phalanx 3 with specified angle
phalanx3Hand -> draw();这就完成了单个手指的绘制。现在我们反转所有的旋转和平移回到开始的位置(因为有太多的旋转在路上,你必须确保你的顺序保持一致,否则你会结束在其他地方,手指会到处都是)。
// CONSTANT: Return to origin
// Undo rotations and translations in proper order
glRotatef((-1.0f*f_p[2].theta), 0, 1, 0); // Phalanx 3 rotation
glTranslatef(-2.0f, 0.0f, 0.0f); // Phalanx 3 translation
glRotatef(90.0f, 0, 1, 0); // Rotation to Phalanx 3
glRotatef((-1.0f*f_p[1].theta), 0, 1, 0); // Phalanx 2
glTranslatef(-1.3f, -0.03f, 0.0f); // Phalanx 2 translation and adjustment
glRotatef((-1.0f*f_p[0].theta), 0, 0, 1); // Rotation to Phalanx 1
glTranslatef(0.0f, 0.0f, -1.87f); // Phalanx 1 translation最后,由于我的模型一边有两个手指,另一个在另一边,所以在绘制其他两个手指之前,我必须旋转:
// CONSTANT: Keep parts right side up
glRotatef(90.0f, 0, 0, 1);此时,我将对fingers 2和fingers 3遵循相同的过程(基本上是从// DRAW FINGER 1注释开始的代码)。你可能不需要这样做,因为我认为你的模型没有所有这些额外的部分。在这一点上,你可以放弃所有的旋转/平移回到原点,只需以以下内容结束:
glPopMatrix();并返回到您之前正在做的事情(等待用户输入,等等)。
我使用的draw()函数是使用从.obj文件中提取的数据绘制三角形的标准函数。
发布于 2015-08-28 05:28:04
有关解决方案的更多信息,请访问denavit hartenberg notation
我的解决方案很简单。我有kinematicChain类,我存储了所有模型的位置和方向的向量。我使用for循环遍历这个类中的所有元素,并乘以每个元素的位置和旋转。
假设我们有3个元素,这个链中最后一个元素的位置是(伪代码):
currentElementposition * currentElementorientation 第二个元素的位置:
(currentElementPosition*currentElementorientation)*positionOfPreviousElement第一个元素的位置:
(currentElementPosition*currentElementorientation)*positionOfPreviousElement然后缩放对象。
移动和旋转是4x4矩阵
glm::mat4 rotate;
glm::mat4 move;我使用的函数:
void Model::moveModel(std::vector<glm::vec3> & positions, std::vector<glm::vec3> & orienations, int id)
{
try
{
if (positions.size() != orienations.size()) throw "Size of positions vector should be equal to orienations vector";
glm::mat4 objPosition;
for (int i = id ; i >= 0 ; --i)
{
rotate = glm::eulerAngleYXZ(orienations[i].y, orienations[i].x, orienations[i].z);
move = glm::translate(glm::mat4(), positions[i]);
objPosition = (move * rotate) * objPosition;
}
objScale = scale(glm::mat4(), objSize); // scaling object
objPosition = objPosition * objScale;
glUniformMatrix4fv(objPositionID, 1, GL_FALSE, &objPosition[0][0]);
glUniformMatrix4fv(perspectiveGL, 1, GL_FALSE, &perspective[0][0]);
glUniformMatrix4fv(lookAtGL, 1, GL_FALSE, &lookAt[0][0]);
glUniform3f(lightPositionGL, lightPosition.x, lightPosition.y, lightPosition.z); // przesłanie 3 liczb float
}
catch(char const * errorMsg)
{
std::cout << errorMsg << std::endl;
}
}发布于 2015-04-16 07:04:07
你有没有考虑过像操纵人的手臂一样操纵物体?这样,所有对象都被链接在一起,并且不会失去同步。然后,可以将动画作为一个整体应用于装备。更少的计算,对你来说更容易。
示例(本站点的其他页面也很有帮助):http://www.blender.org/api/htmlI/x7613.html http://www.blender.org/api/htmlI/x7891.html
参考:http://wiki.blender.org/index.php/Doc:2.6/Manual/Rigging
https://stackoverflow.com/questions/29662297
复制相似问题