首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >OpenGL简单3D机械臂

OpenGL简单3D机械臂
EN

Stack Overflow用户
提问于 2015-04-16 06:49:49
回答 3查看 3.3K关注 0票数 1

我想做一个简单的3D机械臂使用搅拌机。目前我可以导入obj文件和纹理,旋转,平移和缩放。

问题:为了简化,机械臂将有3个部分,底座(旋转的圆柱体)和两个长方体。我对旋转卷发机和长方体没有问题。但这两个长方体必须连接在一起,我不知道该怎么做。当第一个长方体旋转时,我可以使用简单的正弦函数和余弦函数来计算第二个长方体的位置,但我不知道如何测量物体的长度。

第二个问题:我可以在一个obj文件中导出所有3个对象,然后在openGL中对它们进行分割吗?

EN

回答 3

Stack Overflow用户

发布于 2015-04-17 00:45:40

你还没有回复评论,但我想我还是把这段代码贴出来吧。我写这篇文章是为了在OpenGL中渲染一个3D机器手。我有所有手指和手的搅拌器模型文件(由其他人制作),我将它们单独导出到.obj文件中。

最终结果可以在here中看到。如您所见,我还添加了使用鼠标更改视点的功能。我通过反复试验的方法确定了手指指骨的偏移量,但也许您可以使用here中描述的Blender找到点之间的偏移量。我现在不能测试它,因为我的工作电脑上没有Blender。

下面的代码描述了我实现这一点的过程。我把它拆开了,这样我就可以写一些解释了,但是把所有的片段按顺序放在一起,就会生成我的完整函数,来绘制一个连接到手上的single finger。

我的绘图函数以如下方式开始:

代码语言:javascript
复制
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);

现在我们已经在原点上设置好了(根据鼠标的指示旋转),我们可以从绘制手掌开始。不需要移位(它位于原点)。

代码语言:javascript
复制
// DRAW PALM
glColor3f(1.0f, 1.0f, 1.0f); // Use proper color - white
palmHand -> draw();

手掌渲染完成后,我们开始绘制第一个手指。翻译中的1.87f是通过实验确定的。这里的值还取决于我从Blender导出项目的质量,但一旦导出一次,它就不会改变。(实际上,我对我给自己留下的相当自满的评论感到相当惊讶--这段代码已经有几年的历史了)。指骨仅绕一个轴旋转,旋转值(角度)存储在f_p[]中。

代码语言:javascript
复制
// 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);

绘制第二个(中间)方阵的过程与绘制底部方阵的过程相同,只是它绕不同的轴旋转。

代码语言:javascript
复制
// 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中导出它时,我正确地排列了模型。

代码语言:javascript
复制
// 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();

这就完成了单个手指的绘制。现在我们反转所有的旋转和平移回到开始的位置(因为有太多的旋转在路上,你必须确保你的顺序保持一致,否则你会结束在其他地方,手指会到处都是)。

代码语言:javascript
复制
// 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

最后,由于我的模型一边有两个手指,另一个在另一边,所以在绘制其他两个手指之前,我必须旋转:

代码语言:javascript
复制
// CONSTANT: Keep parts right side up
glRotatef(90.0f, 0, 0, 1);

此时,我将对fingers 2和fingers 3遵循相同的过程(基本上是从// DRAW FINGER 1注释开始的代码)。你可能不需要这样做,因为我认为你的模型没有所有这些额外的部分。在这一点上,你可以放弃所有的旋转/平移回到原点,只需以以下内容结束:

代码语言:javascript
复制
glPopMatrix();

并返回到您之前正在做的事情(等待用户输入,等等)。

我使用的draw()函数是使用从.obj文件中提取的数据绘制三角形的标准函数。

票数 1
EN

Stack Overflow用户

发布于 2015-08-28 05:28:04

有关解决方案的更多信息,请访问denavit hartenberg notation

我的解决方案很简单。我有kinematicChain类,我存储了所有模型的位置和方向的向量。我使用for循环遍历这个类中的所有元素,并乘以每个元素的位置和旋转。

假设我们有3个元素,这个链中最后一个元素的位置是(伪代码):

代码语言:javascript
复制
currentElementposition * currentElementorientation 

第二个元素的位置:

代码语言:javascript
复制
(currentElementPosition*currentElementorientation)*positionOfPreviousElement

第一个元素的位置:

代码语言:javascript
复制
(currentElementPosition*currentElementorientation)*positionOfPreviousElement

然后缩放对象。

移动和旋转是4x4矩阵

代码语言:javascript
复制
glm::mat4 rotate;
glm::mat4 move;

我使用的函数:

代码语言:javascript
复制
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;
    }
}
票数 1
EN

Stack Overflow用户

发布于 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

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29662297

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档