【openframeworks】3DPrimitivesExample 图元示例(C++)

该文提供了一段使用openFrameworks进行3D图形绘制的代码示例,包括三角面片运动模式、物体旋转、深度测试、光照及点光源的使用。示例中展示了球体、平面、盒子等3D图元的绘制,并涉及纹理绑定和视频采集器的应用。
摘要由CSDN通过智能技术生成
                          • AI介绍OF

                          • 3D图元示例

                          • 部分代码

                          • 参考链接

一、AI介绍OF

5cb5c54e4e9b8b37238e23ff4c834741.png

chatgpt

c6c40cf060869ef38c03a3f9f479f47e.png

claude

二、3D图元示例

e3a80acce4e76d75abe6e1448fdd3b6a.png

示例截图

运行演示

三角面片运动模式

三、部分代码

void ofApp::draw() {
  //物体旋转角度
  float spinX = sin(ofGetElapsedTimef()*.35f);
  float spinY = cos(ofGetElapsedTimef()*.075f);
  //按下鼠标  旋转角度置为0
  if (bMousePressed) {
    spinX = spinY = 0.0f;
  }
  //相机全局位置
  cam.setGlobalPosition({ 0,0,cam.getImagePlaneDistance(ofGetCurrentViewport()) });
  cam.begin();//开启相机渲染


  ofEnableDepthTest();//启用深度测试


  ofEnableLighting();//启用光照
  pointLight.enable(); //点光源启用
  pointLight2.enable();
  pointLight3.enable();






  // draw the outer sphere  绘制外轮廓球体
  material.begin();
  ofNoFill();//使用当前绘制颜色将形状绘制为轮廓。
  //使用当前渲染器绘制一个球体。球体是用代表球体中心的 x、y 和 z 坐标绘制的。此函数使用默认原点 z=O 绘制球体。
  ofDrawSphere(0, 0, max(ofGetWidth(),ofGetHeight()));
  material.end();


  if (mode == 1 || mode == 3) texture.getTexture().bind();//绑定纹理:mode==1/3
  if (mode == 2) vidGrabber.getTexture().bind();//视频采集器绑定纹理
  //屏幕宽高
  float screenWidth = ofGetWidth();
  float screenHeight = ofGetHeight();
  //设置3D图元的位置    
  plane.setPosition(   -screenWidth * .5 + screenWidth *  1/4.f, screenHeight *  1.1/6.f, 0);
  box.setPosition(     -screenWidth * .5 + screenWidth *  2/4.f, screenHeight *  1.1/6.f, 0);
  sphere.setPosition(  -screenWidth * .5 + screenWidth *  3/4.f, screenHeight *  1.1/6.f, 0);
  icoSphere.setPosition( -screenWidth * .5 + screenWidth *  1/4.f, screenHeight * -1.1/6.f, 0);
  cylinder.setPosition(  -screenWidth * .5 + screenWidth *  2/4.f, screenHeight * -1.1/6.f, 0);
  cone.setPosition(    -screenWidth * .5 + screenWidth *  3/4.f, screenHeight * -1.1/6.f, 0);


  // Plane 平面//


  plane.rotateDeg(spinX, 1.0, 0.0, 0.0);
  plane.rotateDeg(spinY, 0, 1.0, 0.0);




  //计算变形曲面
  if (mode == 3) {
    deformPlane = plane.getMesh();//平面网格->变形曲面
    // x = columns, y = rows //
    glm::vec2 planeDims = plane.getResolution();//平面分辨率  
    float planeAngleX = ofGetElapsedTimef()*3.6;//平面角度x:随时间增加
    float planeAngleInc = 3.f / (float)planeDims.x;//角度增加量
    glm::vec3 vert;//顶点
    for (size_t i = 0; i < deformPlane.getNumIndices(); i++) {//遍历变形平面的所有顶点
      planeAngleX += planeAngleInc;//计算角度x
      int ii = deformPlane.getIndex(i);//获取顶点索引ii
      vert = deformPlane.getVertex(ii);//获取顶点坐标
      vert.z += cos(planeAngleX) * 50;//顶点的z值 余弦波动
      deformPlane.setVertex(ii, vert);//更新顶点
    }
  }
  //非填充 且 线框
  if (!bFill && bWireframe) {
    // if we are only drawing the wireframe, use
    // the material to draw it, otherwise the material
    // will be bound and unbound for every geometry
    // and the wireframe will be drawn in black
    // 如果我们只绘制线框,则使用材质来绘制它,否则材质将为每个几何体绑定和取消绑定,线框将绘制为黑色
    material.begin();
  }
  //填充模式:绘制平面或者变形曲面
  if (bFill) {
    material.begin();
    ofFill();//绘制填充当前绘制颜色的形状。~~~~f。cpp) void ofApp: drawOf ofSetColor(0,0,255); offillO: ofDrawRect(10,10,100,100); //绘制蓝色填充的矩形)
    if (mode == 3) {
      plane.transformGL();//将 opengl 渲染器的模型视图矩阵设置为此节点转换。
      deformPlane.draw();//绘制变形曲面
      plane.restoreTransformGL();//恢复 opengl 渲染器之前的模型视图变换矩阵。
    }
    else {
      plane.draw();//绘制平面
    }
    material.end();
  }
  //线框模式    绘制平面
  if (bWireframe) {
    ofNoFill();//使用当前绘制颜色将形状绘制为轮廓。~~~~{. cpp) void ofApp: drawOf ofSetColor(0,0,255); 的NoFillO; ofDrawRectangle(10,10,100,100); //只绘制蓝色轮廓)~~~~
    ofSetColor(0, 0, 0);//黑色
    plane.setPosition(plane.getPosition().x, plane.getPosition().y, plane.getPosition().z + 1);//平面位置z+1
    plane.drawWireframe();//绘制线框
    plane.setPosition(plane.getPosition().x, plane.getPosition().y, plane.getPosition().z - 1);//平面位置z-1


  }


  // Box 盒子  角度 //


  box.rotateDeg(spinX, 1.0, 0.0, 0.0);
  box.rotateDeg(spinY, 0, 1.0, 0.0);
  //填充模式:绘制盒子
  if (bFill) {
    material.begin();
    ofFill();
    if (mode == 3) {
      box.transformGL();
      for (int i = 0; i < ofBoxPrimitive::SIDES_TOTAL; i++) {//遍历6个面
        ofPushMatrix();//将 opengl 渲染器的模型视图矩阵设置为此节点变换。
        ofTranslate(boxSides[i].getNormal(0) * sin(ofGetElapsedTimef()) * 50);//这个面沿其法线方向 正弦运动
        boxSides[i].draw();
        ofPopMatrix();
      }
      box.restoreTransformGL();
    }
    else {
      box.draw();
    }
    material.end();
  }
  //线框模式  
  if (bWireframe) {
    ofNoFill();
    ofSetColor(0, 0, 0);
    box.setScale(1.01f);//设置局部统一比例(x、y 和 z 等比例缩放)。
    box.drawWireframe();//绘制线框盒子
    box.setScale(1.f);//恢复统一比例
  }




  // Sphere  球体  设置旋转角度  绕x轴 绕Y轴//
  sphere.rotateDeg(spinX, 1.0, 0.0, 0.0);
  sphere.rotateDeg(spinY, 0, 1.0, 0.0);
  //球体
  if (mode == 3) {
    sphere.setMode(OF_PRIMITIVE_TRIANGLES);//原始三角形球体
    triangles = sphere.getMesh().getUniqueFaces();//球体的三角面片集合
  }
  //填充球体
  if (bFill) {
    material.begin();
    ofFill();
    if (mode == 3) {
      float angle = ofGetElapsedTimef()*3.2;//
      float strength = (sin(angle + .25)) * .5f * 5.f;//正弦移动
      glm::vec3 faceNormal;
      for (size_t i = 0; i < triangles.size(); i++) {//遍历球体的三角面片
        // store the face normal here.
        // we change the vertices, which makes the face normal change
        // every time that we call getFaceNormal //
        // 在这里存储面法线。
        // 我们改变了顶点,这使得面部正常变化
        // 每次我们调用 getFaceNormal //
        faceNormal = triangles[i].getFaceNormal();//获取三角面片法线
        for (int j = 0; j < 3; j++) {
          triangles[i].setVertex(j, triangles[i].getVertex(j) + faceNormal * strength);//三角面片沿法线方向做正弦运动
        }
      }
      sphere.getMesh().setFromTriangles(triangles);//以三角面片集合设置球体
    }
    sphere.draw();//绘制球体
    material.end();
  }
  //绘制球体线框
  if (bWireframe) {
    ofNoFill();
    ofSetColor(0, 0, 0);
    sphere.setScale(1.01f);
    sphere.drawWireframe();
    sphere.setScale(1.f);
  }
 }

参考链接:

https://openframeworks.cc/zh_cn/documentation/

https://openframeworks.cc/download/

https://github.com/openframeworks/openFrameworks/releases/tag/nightly

The End

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值