qt opengl 加载3d模型(obj格式)

2023-11-09

     和一般c++程序加载3d模型一样,解读出数据内容,再用一个常规的着色程序就可以了。

我实现的效果如下,采用的免费模型

  实现思路和前面的略有不同,就是把自己生成顶点、纹理、法线的过程变成从文件读取了。

我的obj文件如下 

mtllib C:\Users\Animation\Desktop\XNALara\data\dummy\Vanquish - Augmented Reaction Suit\vanquish.mtl
g Model001_24_Vanquish_1.0_0.0_0.0
usemtl Model001_Material001
v 0.1132252 1.45228 0.0713402
vn 0.452102 0.483883 0.749307
vt 0.946289 0.365723

....

f -800/-800/-800 -810/-810/-810 -808/-808/-808
f -808/-808/-808 -799/-799/-799 -800/-800/-800
f -801/-801/-801 -800/-800/-800 -798/-798/-798
f -798/-798/-798 -802/-802/-802 -801/-801/-801
f -802/-802/-802 -798/-798/-798 -797/-797/-797
f -797/-797/-797 -803/-803/-803 -802/-802/-802
f -803/-803/-803 -797/-797/-797 -796/-796/-796

然后这里会有一个空行,下面的内容格式和上面保持一致,如此有几个循环

mtllib C:\Users\Animation\Desktop\XNALara\data\dummy\Vanquish - Augmented Reaction Suit\vanquish.mtl
g Model001_24_Vanquish_1.0_0.0_0.0
usemtl Model001_Material001
v 0.1132252 1.45228 0.0713402
vn 0.452102 0.483883 0.749307
vt 0.946289 0.365723

....

f -800/-800/-800 -810/-810/-810 -808/-808/-808
f -808/-808/-808 -799/-799/-799 -800/-800/-800
f -801/-801/-801 -800/-800/-800 -798/-798/-798
f -798/-798/-798 -802/-802/-802 -801/-801/-801
f -802/-802/-802 -798/-798/-798 -797/-797/-797
f -797/-797/-797 -803/-803/-803 -802/-802/-802
f -803/-803/-803 -797/-797/-797 -796/-796/-796 

关于obj文件的介绍我就不说了,百度吧。

解析如下

bool ObjLoader::load(QString fileName, QVector<float> &vPoints,QVector<float> &tPoints,QVector<float> &nPoints)
{
    if(fileName.mid(fileName.lastIndexOf('.')) != ".obj"){
        qDebug() << "file is not a obj file";
        return false;
    }

    QFile objFile(fileName);
    if(!objFile.open(QIODevice::ReadOnly)){
        qDebug() << "open" << fileName << "failed";
        return false;
    }

    QVector<float> vertextPoints,texturePoints,normalPoints;
    QVector<std::tuple<int,int,int>> facesIndexs;
    while (!objFile.atEnd()) {
        QByteArray lineData = objFile.readLine();
        lineData = lineData.remove(lineData.count() - 2,2);
        if(lineData.isEmpty()){
            for(auto &verFaceInfo : facesIndexs){
                int vIndex = std::get<0>(verFaceInfo);
                int tIndex = std::get<1>(verFaceInfo);
                int nIndex = std::get<2>(verFaceInfo);
                int vPointSizes = vertextPoints.count() / 3;
                int tPointSizes = texturePoints.count() / 2;
                int nPointSizes = normalPoints.count() / 3;
                vPoints << vertextPoints.at((vPointSizes + vIndex) * 3);
                vPoints << vertextPoints.at((vPointSizes + vIndex) * 3 + 1);
                vPoints << vertextPoints.at((vPointSizes + vIndex) * 3 + 2);

                tPoints << texturePoints.at((tPointSizes + tIndex) * 2);
                tPoints << texturePoints.at((tPointSizes + tIndex) * 2 + 1);

                nPoints << normalPoints.at((nPointSizes + nIndex) * 3);
                nPoints << normalPoints.at((nPointSizes + nIndex) * 3 + 1);
                nPoints << normalPoints.at((nPointSizes + nIndex) * 3 + 2);
            }
            vertextPoints.clear();
            texturePoints.clear();
            normalPoints.clear();
            facesIndexs.clear();
            continue;
        }

        QList<QByteArray> strValues = lineData.split(' ');
        QString dataType = strValues.takeFirst();
        if(dataType == "v"){
            std::transform(strValues.begin(),strValues.end(),std::back_inserter(vertextPoints),[](QByteArray &str){
                return str.toFloat();
            });
        }else if(dataType == "vt"){
            std::transform(strValues.begin(),strValues.end(),std::back_inserter(texturePoints),[](QByteArray &str){
                return str.toFloat();
            });
        }else if(dataType == "vn"){
            std::transform(strValues.begin(),strValues.end(),std::back_inserter(normalPoints),[](QByteArray &str){
                return str.toFloat();
            });
        }else if(dataType == "f"){
            std::transform(strValues.begin(),strValues.end(),std::back_inserter(facesIndexs),[](QByteArray &str){
                QList<QByteArray> intStr = str.split('/');
                return std::make_tuple(intStr.first().toInt(),intStr.at(1).toInt(),intStr.last().toInt());
            });
        }
    }
    objFile.close();
}

 这样解析出来的数据就按顺序放入容器了,接下的步骤和前面一样的,写个常用渲染器,用就可以了

#ifndef GENERICRENDER_H
#define GENERICRENDER_H

#include <QOpenGLShaderProgram>
#include <QOpenGLExtraFunctions>
#include <QOpenGLTexture>
#include <QOpenGLBuffer>
class GenericRender
{
public:
    GenericRender() = default;
    void initsize(QString filename,QImage &textureImg);
    void render(QOpenGLExtraFunctions *f,QMatrix4x4 &pMatrix,QMatrix4x4 &vMatrix,QMatrix4x4 &mMatrix,QVector3D &cameraLocation,QVector3D &lightCation);

private:
    QOpenGLTexture *texture_{nullptr};
    QOpenGLBuffer vbo_;
    QOpenGLShaderProgram program_;
    QVector<float> vertPoints_,texturePoints_,normalPoints_;
};

#endif // GENERICRENDER_H
#include "genericrender.h"
#include "utils/objloader.h"
void GenericRender::initsize(QString filename, QImage &textureImg)
{
    program_.addCacheableShaderFromSourceFile(QOpenGLShader::Vertex,"vsrc.vert");
    program_.addCacheableShaderFromSourceFile(QOpenGLShader::Fragment,"fsrc.frag");
    program_.link();

    ObjLoader objModelLoader;
    objModelLoader.load(filename,vertPoints_,texturePoints_,normalPoints_);
    QVector<float> points;
    points << vertPoints_ << texturePoints_ << normalPoints_;
    vbo_.create();
    vbo_.bind();
    vbo_.allocate(points.data(),points.count() * sizeof(float));

    texture_ = new QOpenGLTexture(textureImg);
    texture_->setWrapMode(QOpenGLTexture::ClampToEdge);
    texture_->setMinMagFilters(QOpenGLTexture::Nearest,QOpenGLTexture::Linear);
}

void GenericRender::render(QOpenGLExtraFunctions *f, QMatrix4x4 &pMatrix, QMatrix4x4 &vMatrix, QMatrix4x4 &mMatrix, QVector3D &cameraLocation, QVector3D &lightCation)
{
    f->glEnable(GL_DEPTH_TEST);
    program_.bind();
    vbo_.bind();
    f->glActiveTexture(GL_TEXTURE0 + 0);
    program_.setUniformValue("uPMatrix",pMatrix);
    program_.setUniformValue("uVMatrix",vMatrix);
    program_.setUniformValue("uMMatrix",mMatrix);
    program_.setUniformValue("uLightLocation",lightCation);
    program_.setUniformValue("uCamera",cameraLocation);
    program_.setUniformValue("sTexture",0);

    program_.enableAttributeArray(0);
    program_.enableAttributeArray(1);
    program_.enableAttributeArray(2);
    program_.setAttributeBuffer(0,GL_FLOAT,0,3,3*sizeof(GLfloat));
    program_.setAttributeBuffer(1,GL_FLOAT,vertPoints_.count() * sizeof(GLfloat),2,2*sizeof(GLfloat));
    program_.setAttributeBuffer(2,GL_FLOAT,(vertPoints_.count() + texturePoints_.count()) * sizeof(GLfloat),3,3*sizeof(GLfloat));
    texture_->bind(0);
    f->glDrawArrays(GL_TRIANGLES,0,vertPoints_.count()/3);

    program_.disableAttributeArray(0);
    program_.disableAttributeArray(1);
    program_.disableAttributeArray(2);
    texture_->release();
    vbo_.release();
    program_.release();
    f->glDisable(GL_DEPTH_TEST);
}

 其shader如下

#version 330
uniform mat4 uPMatrix,uVMatrix,uMMatrix;
uniform vec3 uLightLocation,uCamera;
layout (location = 0) in vec3 aPosition;
layout (location = 1) in vec2 aTextureCoord;
layout (location = 2) in vec3 aNormal;
smooth out vec2 vTextureCood;
smooth out vec4 vAmbient;
smooth out vec4 vDiffuse;
smooth out vec4 vSpecular;

void pointLight(in vec3 normal,inout vec4 ambient,inout vec4 diffuse,inout vec4 specular,in vec4 lightAmbient,in vec4 lightDiffuse,in vec4 lightSpecular,in float shininess){
    ambient = lightAmbient;

    vec3 normalTarget = aPosition + normal;
    vec3 newNormal = normalize((uMMatrix * vec4(normalTarget,1)).xyz - (uMMatrix * vec4(aPosition,1)).xyz);
    vec3 eye = normalize(uCamera - (uMMatrix * vec4(aPosition,1)).xyz);
    vec3 vp = normalize(uLightLocation - (uMMatrix * vec4(aPosition,1)).xyz);
    vec3 halfVector = normalize(eye + vp);

    float nDotViewPotision = max(0.0,dot(newNormal,vp));
    diffuse = lightDiffuse * nDotViewPotision;

    float nDotViewHalfVector = dot(newNormal,halfVector);
    float powerFactor = max(0.0,pow(nDotViewHalfVector,shininess));
    specular = lightSpecular * powerFactor;
}

void main(void)
{
    gl_Position = uPMatrix * uVMatrix * uMMatrix * vec4(aPosition,1);
    vec4 ambient = vec4(0.0,0.0,0.0,0.0),diffuse = vec4(0.0,0.0,0.0,0.0),specular = vec4(0.0,0.0,0.0,0.0);
    pointLight(aNormal,ambient,diffuse,specular,vec4(0.6,0.6,0.6,1.0),vec4(0.8,0.8,0.8,1.0),vec4(0.9,0.9,0.9,1),50);
    vAmbient = ambient;
    vDiffuse = diffuse;
    vSpecular = specular;
    vTextureCood = aTextureCoord;
}
#version 330
uniform sampler2D sTexture;
in vec2 vTextureCood;
in vec4 vAmbient;
in vec4 vDiffuse;
in vec4 vSpecular;
out vec4 fragColor;

void main(void)
{
    vec4 finalColor = texture2D(sTexture,vTextureCood);
    finalColor = finalColor * (vAmbient + vDiffuse + vSpecular);
    fragColor = finalColor;
}

在qwidget界面中调用如下

#ifndef WIDGET_H
#define WIDGET_H

#include <QOpenGLWidget>
#include <QTimer>
#include "genericrender.h"

class Widget : public QOpenGLWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = 0);
    ~Widget();

protected:
    void initializeGL() override;
    void resizeGL(int w,int h) override;
    void paintGL() override;

private:
    GenericRender render_;
    QTimer tm_;
    QVector3D cameraLocation_,lightLocation_;
    QMatrix4x4 pMatrix_;
    qreal angleX_,angleY,anglZ_;

private slots:
    void slotTimeout();
};

#endif // WIDGET_H
#include "widget.h"
#include "utils/objloader.h"

Widget::Widget(QWidget *parent)
    : QOpenGLWidget(parent)
{
    connect(&tm_,SIGNAL(timeout()),this,SLOT(slotTimeout()));
    tm_.start(30);
}

Widget::~Widget()
{

}

void Widget::initializeGL()
{
    render_.initsize("vanquish.obj",QImage("vanquish.jpg"));
    cameraLocation_.setX(0);
    cameraLocation_.setY(0);
    cameraLocation_.setZ(3);
    lightLocation_.setX(10);
    lightLocation_.setY(10);
    lightLocation_.setZ(1);
}

void Widget::resizeGL(int w, int h)
{
    pMatrix_.setToIdentity();
    pMatrix_.perspective(45,float(w)/h,0.01f,100.0f);
}

void Widget::paintGL()
{
    QOpenGLExtraFunctions *f = QOpenGLContext::currentContext()->extraFunctions();
    f->glClearColor(0.0f,0.0f,0.0f,1.0f);
    f->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    QMatrix4x4 vMatrix;
    vMatrix.lookAt(cameraLocation_,QVector3D(0,0,0),QVector3D(0,1,0));

    QMatrix4x4 mMatrix;
    mMatrix.translate(0,-0.8);
//    mMatrix.rotate(angleX_,1,0,0);
    mMatrix.rotate(angleY,0,1,0);
//    mMatrix.rotate(anglZ_,0,0,1);
    render_.render(f,pMatrix_,vMatrix,mMatrix,cameraLocation_,lightLocation_);
}

void Widget::slotTimeout()
{
    angleX_ += 5;
    angleY += 5;
    anglZ_ += 5;
    update();
}

 到此结束。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

qt opengl 加载3d模型(obj格式) 的相关文章

  • MAC 上的 QT/C++ - 未设置应用程序图标

    我正在努力解决的奇怪问题 在与我的 pro QT 项目文件相同的文件夹中 我有一个 Resources myIcon png 我试图将其设置为我构建的应用程序的图标 在 OSX 上运行 我阅读了文档 它建议在 pro 文件中添加 ICON
  • 仅将非模态 QDialog 窗口放置在我的应用程序顶部,而不是所有应用程序顶部

    我有一个 QDialog 窗口 它应该始终位于我的应用程序顶部 它不是模态的 用户可以随时与对话框和主应用程序进行交互 使用窗口保持在顶部提示在某种程度上实现了这一点 但是 该对话框仍然位于所有其他正在运行的应用程序 例如记事本 chrom
  • SDL 鼠标位置调整大小后裁剪

    我在 SDL 中的鼠标位置上遇到了一些奇怪的行为 如果我将窗口大小调整得更大 则任一鼠标事件的 x y 位置似乎都限制为原始窗口的宽度和高度 如果我缺少一些函数调用来告诉 SDL 鼠标区域的大小已增加 应用程序的相关部分 void Resi
  • 使用 C# 截取任何外部应用程序的屏幕截图

    我们有一个 C WPF 应用程序 我们想要在其中截取我们启动的任意应用程序的屏幕截图 即 我们可以引用我们启动的进程 应用程序可能已最小化或位于其他窗口后面 但我们仍然只需要单个应用程序的图像 而不是重叠像素 我知道使用 BitBlt 或的
  • 如何在 C++ 运行时更改 QML 对象的属性?

    我想在运行时更改 QML 对象的文本 我尝试如下 但文本仍然为空 这是后端类 class BackEnd public QObject Q OBJECT Q PROPERTY QString userFieldText READ userF
  • PyQt5 的 OpenGL 模块和版本控制问题(调用不正确的 _QOpenGLFunctions_(ver))

    我一直在努力得到PyQt5 helloGL 示例代码 https github com baoboa pyqt5 blob master examples opengl hellogl py编译 当我尝试构建解决方案时 我得到 Traceb
  • GoQt 致命错误:QAbstractAnimation:没有这样的文件或目录

    我尝试编译 Qt 来开发桌面应用程序 我按照 Qt 网站上的官方 wiki 指南的说明进行操作 当我尝试go run示例文件夹中的示例 我收到错误 去运行 home pinkya rabbit workspace go1programs s
  • 如何在带有预编译头的项目中使用google protobuf

    我有一个包含多个项目的解决方案 我的项目 但不是全部 使用预编译头 我决定使用 protobuf 但遇到了一个问题 在 protoc exe 从 proto 生成 pb h 后 我尝试包含标头并收到错误 预编译标头未包含在 pb h 中 我
  • 加权 Voronoi 的 CGAL 2D APOLLONIUS 图 - 如何生成和获取面和顶点?

    我正在尝试根据阿波罗尼乌斯图生成加权沃罗诺伊 我正在使用 CGAL 库 我找不到如何从 apollonius 获取面和顶点的好例子 我有以下类型定义 typedef double NT typedef CGAL Cartesian lt N
  • 从布局中按名称获取小部件

    如果我想从 python Qt 的布局中获取特定的小部件 我应该如何进行 到目前为止我所做的 for i in range self ui horizontalLayout 14 count here it does fail name s
  • QGraphicsScene::clear 不会改变 sceneRect

    我有一个 QGraphicsScene 场景 和 QGraphicsView graphicsView 我有一个画图的方法 当我需要重绘所有图形时 我调用这个方法 一切都好 但我意识到 scene gt clear 不会改变 sceneRe
  • 在 Qt5 中,是否需要 Q_INVOKABLE 来从 QML 调用公共 QObject 函数?

    我刚刚意识到我可以调用暴露于 QML 的对象的几乎任何函数 现在我对 Q INVOKABLE 很好奇 Qt5docs http doc qt io qt 5 qtqml cppintegration exposecppattributes
  • 如何在 Qt 中以编程方式制作一条水平线

    我想弄清楚如何在 Qt 中制作一条水平线 这很容易在设计器中创建 但我想以编程方式创建一个 我已经做了一些谷歌搜索并查看了 ui 文件中的 xml 但无法弄清楚任何内容 ui 文件中的 xml 如下所示
  • 如何将图像显示为缩略图

    我有一个QTreeView显示硬盘驱动器和目录 我也有一个QListView显示图像文件如下 但我想将图像显示为缩略图 如下所示 My code mainWidget mainWidget QWidget parent QWidget pa
  • 与 Qt 项目的静态链接

    我有一个在 Visual Studio 2010 Professional 中构建的 Qt 项目 但是 当我运行它 在调试或发布模式下 时 它会要求一些 Qt dll 如果我提供 dll 并将它们放入 System32 中 它就可以工作 但
  • Opengl 像素完美 2D 绘图

    我正在研究 2d 引擎 它已经工作得很好 但我不断收到像素错误 例如 我的窗口是 960x540 像素 我从 0 0 到 959 0 画一条线 我希望扫描线 0 上的每个像素都会被设置为一种颜色 但事实并非如此 最右边的像素没有被绘制 当我
  • Qt 插槽是否与其他代码并行运行?

    在此函数示例中 void MyClass myFunction emit MySignal1 emit MySignal2 如果我有slot1倾听MySignal1 and slot2倾听MySignal2 1 Is slot1总是会在之前
  • QT从QTableWidgetItem继承到Widget并覆盖'<'运算符

    我想要一个QTableWidget具有定制的某些单元QProgressBars 并且我希望能够对包含这些的列进行排序 我的定制QProgressBar继承自两者QProgressBar and QTableWidgetItem 并且我正在覆
  • Qt - 无法让 lambda 工作[重复]

    这个问题在这里已经有答案了 我有以下功能 我想在其中修剪我的std set
  • Qt - 设置不可编辑的QComboBox的显示文本

    我想将 QComboBox 的文本设置为某些自定义文本 不在 QComboBox 的列表中 而不将此文本添加为 QComboBox 的项目 此行为可以在可编辑的 QComboBox 上实现QComboBox setEditText cons

随机推荐

  • JVM——垃圾回收器

    JVM 垃圾回收器 按照工作模式分 可以分为并发式垃圾回收器和独占式垃圾回收器 并发式垃圾回收器与应用程序线程交替工作 以尽可能减少应用程序的停顿时间 独占式垃圾回收器 stop the world 一旦运行 就停止应用程序中的所有用 户线
  • Qt 在循环中超时跳出

    常见的一个需求 在一段循环中 给定一个最大运行时间 当循环时间超出时 终止 常用于一些工控场合 对节拍有要求的项目 在此简单的做一个总结记录 主要使用Qt的 QElapsedTimer 类 调用QElapsedTimer中的成员函数elap
  • MySQL技术内幕 InnoDB存储引擎 学习笔记 第八章 备份与恢复

    备份方法 1 热备 在数据库运行中直接备份 对正在运行的数据库没有任何影响 这种方式在MySQL官方手册中称为Online Backup 2 冷备 在数据库停止的情况下备份 这种备份最简单 一般只需拷贝相关的数据库物理文件即可 这种方式在M
  • Vnc配置

    2017 04 15 1 在terminal中输入vncconfig 弹出小窗 勾选对应选项 注意 不要关闭这个小窗 不要关闭这个小窗 不要关闭这个小窗 2 vncconfig nowin 在linux选中文字后 无需其他按键 直接在win
  • 智慧农业物联网系统解决方案

    一 方案背景 随着城市的发展 人们对于生活水准的要求也越来越高 对于食物的品质需求也越来越高 我作为世界农业大国 农业的发展优势慢慢降低 智慧化农业将带来一次新的农业结构改革 农业的根本问题是效率不高 效益不强 效能不够 原因在于各生产要素
  • Python自动操作 GUI 神器——PyAutoGUI

    我们以前讲过怎样使用 Python 在浏览器中实现页面自动化操作 不管用哪种方式实现 都是通过定位页面中的元素来进行相应的操作 今天我们来聊一聊如何在桌面实现自动化操作 与浏览器页面自动化操作类似 桌面自动化操作也是需要定位鼠标在桌面的位置
  • map的常用用法详解

    头文件 include
  • 基于S函数的BP神经网络PID控制器及simulink仿真

    基于S函数的BP神经网络PID控制器及simulink仿真 文章目录 文章来源和摘要 S函数的编写格式和运行步骤 simulink模型结构 S函数模型初始化部分代码理解 S函数模型更新部分 S函数模型输出部分 S函数完整代码附录 文章来源和
  • 第三方网站/系统使用微信扫码登录

    微信扫码登录网站 微信开放平台 在我们做某个平台或者系统时 都需要有一个登录功能 传统的用户名 密码登录模式看起来似乎并没有手机扫码直接登录来的方便 那么在前端实现上 如何实现微信扫码登录呢 授权流程 第三方发起微信授权登录请求 微信用户允
  • 病例对照研究中,如何对年龄、性别、教育程度进行频数匹配?

    病例对照研究中 如何对年龄性别进行频数匹配 案例一 两组被试匹配 案例二 三组被试匹配 背景 使用默认匹配方法 衡量匹配效果 调整参数 其他匹配方法 参考 案例一 两组被试匹配 案例二 三组被试匹配 背景 我经常遇到的数据情形是 有两组被试
  • 实现【企业微信自建应用使用uni-app H5 开发】,并解决【uni-app集成微信JSSDK(wx、jWeixin)变量冲突问题】

    目录 企业微信的开发与调试 企业微信应用主体逻辑 登录 构造网页授权链接 企业微信SDK配置 demo案例 重要bug修复方法 总结 企业微信的开发与调试 在本地开发基础代码和UI 发布到测试环境进行测试 无法本地调试接口 因为web浏览器
  • AltiumDesigner15.1导出3D PDF 图文教程

    ALtiumDesigner更新的速度就一个字 快 不过从15 4 15出来 貌似很久都没有更新了 等了很久 今天终于出来了 O O哈哈 因为早就耳闻AD15 1会带有3D输出功能 能够直接输出到PDF 这个好玩的功能 怎么能错过 本文就是
  • 时序基本介绍——Jitter与Skew区别

    在时序分析当中 有些基础概念还是要认真了解的 时钟抖动 Clock Jitter 和时钟偏移 Clock Skew 经常容易混淆 时序设计中 对于时钟的要求是非常严格的 因此FPGA中也有专用的时钟管脚 对应着专用的时钟区域BUFG BUF
  • 技术工具类:IDEA集成SonarQube并使用

    1 安装插件 从 File gt Settings gt Plugins 搜索 sonar 如下图 直接点击安装即可 安装成功后重启IDEA 在Settings gt Tools 中找到 SonarLint 如下图 在Coniguratio
  • uni-app提供开箱即用的SSR支持

    SSR 服务端渲染 可以给SPA站点带来两大核心优势 更好的SEO 更快的首屏渲染 很多uni app开发者都在积极尝试SSR 但大多没入门就放弃了 原因在于SSR颇高的技术门槛 vue js 官网在介绍 SSR 章节时的描述如下 本指南将
  • Python pycharm(windows版本)部署spark环境

    一 部署本地spark环境 1 1 安装好JDK 下载并安装好jdk1 7 配置完环境变量 1 2 Spark环境变量配置 去http spark apache org downloads html网站下载相应hadoop对应的版本 我下载
  • GD32 ADC检测电压

    GD32 ADC检测电压 https blog csdn net yangkunhenry article details 112757855 GD32的参考电压在规格书上没有查到 但是由于GD32 和STM32的 某种关系 STM32 的
  • 基本农田卫星地图查询_谷歌地图 最新版v7.3.0

    谷歌地图整合Google的本地搜索以及驾车指南两项服务 能够鸟瞰世界 将取代目前桌面搜索软件 谷歌地图可在虚拟世界中如同一只雄鹰在大峡谷中自由飞翔 登陆峡谷顶峰 潜入峡谷深渊 谷歌地图使用界面 相关软件 版本说明 下载地址 谷歌卫星地图下载
  • 感受了一下myspace

    今天去 www myspace com 看了看 感觉还可以 这里是年轻人交流的一个平台 可以了解当前世界年轻的喜好 他们做什么 有想些什么 可以和自己对比 把握时代信息 我觉得还是有点必要 就想当初我进入 天涯 时一样 希望从中能学到一些东
  • qt opengl 加载3d模型(obj格式)

    和一般c 程序加载3d模型一样 解读出数据内容 再用一个常规的着色程序就可以了 我实现的效果如下 采用的免费模型 实现思路和前面的略有不同 就是把自己生成顶点 纹理 法线的过程变成从文件读取了 我的obj文件如下 mtllib C User