OSG中几何体的绘制(二)

2023-12-17

5. 几何体操作

在本章的前言中就讲到,场景都是由基本的绘图基元构成的,基本的绘图基元构成简单的几何体,简单的几何体构成复杂的几何体,复杂的几何体最终构造成复杂的场景。当多个几何体组合时,可能存在多种降低场景渲染效率的原因。在很多3D引擎中,都提供了对场景的几何体进行修改的操作,以达到最优渲染效率。虽然最优渲染效率只是一个理想状态,但一定的几何体操作在相当程度上可以提高渲染效率。

在OSG中,为了获得所需的性能和渲染的效率,osgUtil库提供了一些通用的几何体运算,这些几何体运算主要包括 osgUtil::Simplifier (简化)、osgUtil::SmoothingVisitor(生成法线)、osgUtil::DelaunayTriangulator (生成 Delaunay 三角网工具)和osgUtil::TriStripVisitor (条带化)等。

下面就来介绍几种常用的几何体操作。

5.1 简化几何体

简化几何体(osgUtil::Simplifier)类继承自osg::NodeVisitor类,它采用访问器的方式遍历几何体并对其进行简化处理,在后面的章节将会详细说明访问器的工作机制。

osgUtil::Simplifier 的继承关系图如图4-14 所示

图4-14 osgUtil::Simplifier 的继承关系图

osgUtil::Simplifier 类对几何体的简化主要需要设置两个方面的参数,即当几何体样本比率小于1设置点的误差限制;当几何体的样本比率大于 1 时,设置边的长度限制。通过对点的误差或者边时,的长度的限制简化不必要的点和边,然后通过平滑处理和条带化渲染几何体,进而达到提高渲染效率的目的,也可以用于自动生成低层次模型。一般来说,样本比率越大,简化越少;样本比率越小,简化越多。优化可以直接调用下面的函数:

  1. virtual void apply(osg::Gcode &geode) // 应用于叶节点
  2. void simplify(osg::Geometry &geometry)/ 简化儿何体

这两个函数同样可用于osg::Node节点,不过,关联实例时需要使用accept()方法osgUtil::Simplifer 简化采用的是 边塌陷算法 ,对于这个算法笔者并没有深入研究。记得在邮件列表中也提到了 Robert,关于这个算法的文档已经丢失。目前,网上很少有关于这方面的文档。至于算法是如何实现的,有兴趣的朋友可以进行源码研究。如果读者研究出了结果,欢迎到OSG中国官方讨论区(http://bbs.OsgChina.org)发帖。

5.2 简化几何体示例

简化几何体(osgUtil::Simplifier)示例的代码如程序清单4-5所示。

  1. void simplifier_4_5( const string &strDataFolder)
  2. {
  3. // 创建 Viewer 对象,场景浏览器
  4. osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer();
  5. osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
  6. traits->x = 40;
  7. traits->y = 40;
  8. traits->width = 600;
  9. traits->height = 480;
  10. traits->windowDecoration = true ;
  11. traits->doubleBuffer = true ;
  12. traits->sharedContext = 0;
  13. osg::ref_ptr<osg::GraphicsContext> gc = osg::GraphicsContext::createGraphicsContext(traits.get());
  14. osg::ref_ptr<osg::Camera> camera = new osg::Camera;
  15. camera->setGraphicsContext(gc.get());
  16. camera->setViewport( new osg::Viewport(0, 0, traits->width, traits->height));
  17. GLenum buffer = traits->doubleBuffer ? GL_BACK : GL_FRONT;
  18. camera->setDrawBuffer(buffer);
  19. camera->setReadBuffer(buffer);
  20. viewer->addSlave(camera.get());
  21. // 切换网格模式,方便比较模型的区别
  22. viewer->addEventHandler( new osgGA::StateSetManipulator(viewer->getCamera()->getOrCreateStateSet()));
  23. osg::ref_ptr<osg::Group> root = new osg::Group();
  24. // 设置样本比率,样本比率越大,简化越少
  25. float sampleRatio = 0.3f; // 样本比率越小,简化越多
  26. float maxError = 4.0f; // 设置点的最大误差
  27. // 创建简化对象
  28. osgUtil::Simplifier simplifier(sampleRatio, maxError);
  29. // 读取牛的模型
  30. string strDataPath = strDataFolder + "cow.osg" ;
  31. osg::ref_ptr<osg::Node> node1 = osgDB::readNodeFile(strDataPath);
  32. // 深拷贝牛的模型到 node2 节点
  33. osg::ref_ptr<osg::Node> node2 = (osg::Node*)(node1->clone(osg::CopyOp::DEEP_COPY_ALL));
  34. // 创建一个位置变换节点
  35. osg::ref_ptr<osg::PositionAttitudeTransform> pat = new osg::PositionAttitudeTransform();
  36. pat->setPosition(osg::Vec3(10.0f, 0.0f, 0.0f)); // 设置位置
  37. pat->addChild(node2.get()); // 添加子节点
  38. pat->accept(simplifier); // 简化处理
  39. // 添加到场景
  40. root->addChild(node1.get());
  41. root->addChild(pat.get());
  42. // 优化场景数据
  43. osgUtil::Optimizer optimizer;
  44. optimizer.optimize(root.get());
  45. viewer->setSceneData(root.get());
  46. viewer->realize();
  47. viewer->run();
  48. }

运行程序,截图如图4-15所示

图4-15简化几何体示例截图

5.3 Delaunay三角网绘制

1.TIN 模型

在数字地形建模中,不规则三角网(TIN)通过从不规则离散分布的数据点生成的连续三角面来逼近地形表面。就表达地形信息的角度而言,TIN 模型的优点是它能以不同层次的分辨率来描述地形表面。与格网数据模型相比,TIN 模型在某一特定分辨率下能用更少的空间和时间更精确地表示更加复杂的表面。特别是当地形包含有大量特征,如断裂线、构造线时,TIN 模型能更好地顾及这些特征从而能更精确合理地表达地表形态。

对于TIN模型,其基本要求有以下3点

(1)TIN 是唯一的。

(2)力求最佳三角形几何形状。

(3)保证最邻近的点构成三角形。

在所有可能的三角网中, 狄洛尼(Delaunay)三角网在地形拟合方面表现最为出色 ,常用于 TIN的生成。当不相交的断裂线等被作为预先定义的限制条件作用于 TIN 的生成当中时,就必须考虑带约束条件的狄洛尼三角网。

目前,狄洛尼三角网生成的算法比较多,传统的算法主要包括两种,即 Lawson 算法以及Bowyer-Watson 算法。后来经过该传统算法改进的算法就多了,这里不专门对这些算法予以介绍,可参考相关论文。

2.osgUtil::DelaunayTriangulator 类

上面介绍了狄洛尼(Delaunay)三角网的特性、生成算法及应用,下面来看一下OSG中的狄洛尼三角网。

osgUtil::DelaunayTriangulator 类直接继承自osg::Referenced 类,继承关系图如图4-16所示。

图4-16 osgUtil::DelaunayTriangulator 的继承关系图

创建狄洛尼三角网有如下3个步骤:

(1) 创建顶点数组。

(2) 创建一个osgUtil::DelaunayTriangulator对象,并初始化顶点数组,同时生成三角网,程序代码如下:

  1. bool triangulate() // 开始生成三角网格

(3) 创建一个几何体对象,把osgUtil::DelaunayTriangulator 类对象生成的绘制图元加入到几何体中。在生成狄洛尼三角网时,读者还可以添加一些限制条件,限制条件可以是点、线或多边形,例如:

void addInputConstraint(DelaunayConstraint*dc) // 添加限制条件

通过这么多的讲解,读者应该清楚了狄洛尼三角网的绘制方法了吧。有兴趣的读者可以研究关于狄洛尼三角网的算法。

5.4 Delaunay三角网绘制示例

Delaunay三角网绘制(osgUtil::DelaunayTriangulator)示例的代码如程序清单46所示。

  1. void delaunay_4_6()
  2. {
  3. osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer();
  4. osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
  5. traits->x = 40;
  6. traits->y = 40;
  7. traits->width = 600;
  8. traits->height = 480;
  9. traits->windowDecoration = true ;
  10. traits->doubleBuffer = true ;
  11. traits->sharedContext = 0;
  12. osg::ref_ptr<osg::GraphicsContext> gc = osg::GraphicsContext::createGraphicsContext(traits.get());
  13. osg::ref_ptr<osg::Camera> camera = new osg::Camera;
  14. camera->setGraphicsContext(gc.get());
  15. camera->setViewport( new osg::Viewport(0, 0, traits->width, traits->height));
  16. GLenum buffer = traits->doubleBuffer ? GL_BACK : GL_FRONT;
  17. camera->setDrawBuffer(buffer);
  18. camera->setReadBuffer(buffer);
  19. viewer->addSlave(camera.get());
  20. // 方便查看在多边形之间切换,以查看三角网
  21. viewer->addEventHandler( new osgGA::StateSetManipulator(viewer->getCamera()->getOrCreateStateSet()));
  22. osg::ref_ptr<osg::Group> root = new osg::Group();
  23. // 创建顶点数组
  24. osg::ref_ptr<osg::Vec3Array> coords = new osg::Vec3Array();
  25. // 计算顶点数组的大小
  26. unsigned int n = sizeof (vertex) / sizeof ( float [3]);
  27. // 添加顶点数据
  28. for (unsigned int i = 0; i < n; i++)
  29. {
  30. coords->push_back(osg::Vec3(vertex[i][0], vertex[i][1], vertex[i][2]));
  31. }
  32. // 创建 Delaunay 三角网对象
  33. osg::ref_ptr<osgUtil::DelaunayTriangulator> dt = new osgUtil::DelaunayTriangulator(coords.get());
  34. dt->triangulate(); // 生成三角网
  35. // 创建几何体
  36. osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry();
  37. geometry->setVertexArray(coords.get()); // 设置顶点数组
  38. geometry->addPrimitiveSet(dt->getTriangles()); // 加入到绘图基元
  39. // 添加到叶节点
  40. osg::ref_ptr<osg::Geode> geode = new osg::Geode();
  41. geode->addDrawable(geometry.get());
  42. root->addChild(geode.get());
  43. // 优化场景数据
  44. osgUtil::Optimizer optimizer;
  45. optimizer.optimize(root.get());
  46. viewer->setSceneData(root.get());
  47. viewer->realize();
  48. viewer->run();

}

运行程序,截图如图4-17所示

图4-17 Delaunay 三角网绘制示例截图

5.5 三角带绘制

三角带绘制(osgUtil::TriStripVisitor)类继承自osgUtil::BaseOptimizerVisitor 类,它采用访问器的机制遍历场景中的几何体,实现三角带绘制,以提高染效率。osgUtil::TriStripVisitor 的继承关系图如图4-18所示。

图4-18 osgUtil::TriStripVisitor 的继承关系图

下面对osgUtil::TriStripVisitor 的两个常用成员函数予以说明。

  1. void stripify(osg::Geometry &drawable) // 条带化几何体
  2. virtual void apply(osg::Geode &geode) // 应用于叶节点

从上面可以看出,它同样可应用于叶节点。值得注意的是,关联叶节点实例时需要调用 accept()方法。

大多数图形卡并不直接支持索引三角网。在渲染三角形时,一般是将3个顶点同时提交,这样共享的顶点会多次提交,三角形用到一次就提交一次。因为内存和图形硬件间的数据传输是瓶颈,所以很多API和硬件支持特殊的三角网格式以减少传输量。基本思想是排序点和面,使显卡中已有的三角形不需要再次传输。

这里,我们只讨论三角带,三角带是一个三角形列表,其中每个三角形都与前一个三角形共享一边。在一种最理想的状态下,三角带可以用 N+2个顶点表示存个面。N很大时,每个三角形平均发送一个顶点。在实践中,很多情况下,很多网格是一个三角带无法表达的,此时就需要多个三角带来联合绘制。因为我们希望最小化发往图形卡的顶点数,所以,三角带的数目应该尽可能得少,即三角带越长越好。从另一个方面来说,分别渲染两个长度为N的三角带所需要的时间比渲染一个长度为2N 的三角带要长,即使2N 的三角带中三角形的个数多于两个分开的三角带中的三角形个数的和,因为建立各三角带需要额外的处理时间。

学习了上面的基础知识,读者再去看关于这部分的源代码就会感觉非常易懂了,这些更多是原理的问题。

5.6 三角带绘制示例

三角带绘制(osgUtil::TriStripVisitor)示例的代码如程序清单4-7所示。

  1. osg::ref_ptr<osg::Geometry> createQuad1() // 创建一个四边形节点
  2. {
  3. // 创建一个几何体对象
  4. osg::ref_ptr<osg::Geometry> geom = new osg::Geometry();
  5. // 创建顶点数组,注意顶点的添加顺序是逆时针的
  6. osg::ref_ptr<osg::Vec3Array> v = new osg::Vec3Array();
  7. v->push_back(osg::Vec3(0.0f, 0.0f, 0.0f)); // 添加数据
  8. v->push_back(osg::Vec3(1.0f, 0.0f, 0.0f));
  9. v->push_back(osg::Vec3(1.0f, 0.0f, 1.0f));
  10. v->push_back(osg::Vec3(0.0f, 0.0f, 1.0f));
  11. geom->setVertexArray(v.get()); // 设置顶点数据
  12. // 创建纹理坐标
  13. osg::ref_ptr<osg::Vec2Array> vt = new osg::Vec2Array();
  14. vt->push_back(osg::Vec2(0.0f, 0.0f)); // 添加数据
  15. vt->push_back(osg::Vec2(1.0f, 0.0f));
  16. vt->push_back(osg::Vec2(1.0f, 1.0f));
  17. vt->push_back(osg::Vec2(0.0f, 1.0f));
  18. geom->setTexCoordArray(0, vt.get()); // 设置纹理坐标
  19. // 创建颜色数组
  20. osg::ref_ptr<osg::Vec4Array> vc = new osg::Vec4Array();
  21. vc->push_back(osg::Vec4(1.0f, 0.0f, 0.0f, 1.0f)); // 添加数据
  22. vc->push_back(osg::Vec4(0.0f, 1.0f, 0.0f, 1.0f));
  23. vc->push_back(osg::Vec4(0.0f, 0.0f, 1.0f, 1.0f));
  24. vc->push_back(osg::Vec4(1.0f, 1.0f, 0.0f, 1.0f));
  25. geom->setColorArray(vc.get()); // 设置颜色数组
  26. geom->setColorBinding(osg::Geometry::BIND_PER_VERTEX); // 设置颜色的绑定方式为单个顶点
  27. // 创建法线数组
  28. osg::ref_ptr<osg::Vec3Array> nc = new osg::Vec3Array();
  29. nc->push_back(osg::Vec3(0.0f, -1.0f, 0.0f)); // 添加法线
  30. geom->setNormalArray(nc.get()); // 设置法线数组
  31. geom->setNormalBinding(osg::Geometry::BIND_OVERALL); // 设置法线的绑定方式为全部顶点
  32. geom->addPrimitiveSet( new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, 4)); // 添加图元,绘图基元为四边形
  33. return geom.get();
  34. }
  35. void TriStripVisitor_4_7()
  36. {
  37. // 创建 Viewer 对象,场景浏览器
  38. osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer();
  39. osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
  40. traits->x = 40;
  41. traits->y = 40;
  42. traits->width = 600;
  43. traits->height = 480;
  44. traits->windowDecoration = true ;
  45. traits->doubleBuffer = true ;
  46. traits->sharedContext = 0;
  47. osg::ref_ptr<osg::GraphicsContext> gc = osg::GraphicsContext::createGraphicsContext(traits.get());
  48. osg::ref_ptr<osg::Camera> camera = new osg::Camera;
  49. camera->setGraphicsContext(gc.get());
  50. camera->setViewport( new osg::Viewport(0, 0, traits->width, traits->height));
  51. GLenum buffer = traits->doubleBuffer ? GL_BACK : GL_FRONT;
  52. camera->setDrawBuffer(buffer);
  53. camera->setReadBuffer(buffer);
  54. viewer->addSlave(camera.get());
  55. // 方便查看在多边形之间切换,以查看三角网
  56. viewer->addEventHandler( new osgGA::StateSetManipulator(viewer->getCamera()->getOrCreateStateSet()));
  57. osg::ref_ptr<osg::Group> root = new osg::Group();
  58. // 创建一个几何体对象
  59. osg::ref_ptr<osg::Geometry> geometry = createQuad1();
  60. // 对几何体进行条带化
  61. osgUtil::TriStripVisitor stripper;
  62. stripper.stripify(*(geometry.get()));
  63. // 添加到叶节点
  64. osg::ref_ptr<osg::Geode> geode = new osg::Geode();
  65. geode->addDrawable(geometry.get());
  66. root->addChild(geode.get()); // 添加到场景
  67. // 优化场景数据
  68. osgUtil::Optimizer optimizer;
  69. optimizer.optimize(root.get());
  70. viewer->setSceneData(root.get());
  71. viewer->realize();
  72. viewer->run();
  73. }

运行程序,截图如图4-19所示。

图4-19 三角带绘制示例截图

5.7 生成顶点法向量

生成顶点法向量(osgUtil::SmoothingVisitor)类继承自osg::NodeVisitor 类,它采用 访问器机制 ,遍历场景中的几何体,生成顶点法向量。它的继承关系图如图4-20所示

图4-20 osgUtil::SmoothingVisitor的继承关系图

下面对osgUtil::SmoothingVisitor的一个常用成员函数予以说明

  1. static void smooth(osg::Geometry &geo);

该函数用于生成顶点法向量,调用时需要注意,这是一个静态函数。

在很多应用程序中,网格上的各点都需要一个表面法向量,它的用处非常广泛,例如:

  • 计算光照。
  • 背面剔除。
  • 模拟粒子系统在表面的“弹跳”效果。
  • 通过只需要正面而加速碰撞检测。

通常我们在绘制几何体时都会指定法线。当得到一个模型,它本身并没有法向量时,则有必要通过现有的数据生成。通常,表面法向量可能保存于三角形级或顶点级,其中的一个技巧就是平均相邻三角形的表面法向量,并将结果标准化。当然,这要求知道三角形的法向量。一般可以这样假设,三角形的顶点按逆时针排列,通过叉积就可以计算外表面的法向量。当然,在有些情况下,顶点的顺序是未知且比较混乱的,这样就比较麻烦了。这个笔者也没有仔细深入研究,推荐读者看一下《计算非固定结构序列的多边形的顶点法线》这篇论文。通过平均三角形法向量求得顶点法向量是一种经验性的方法,不具有通用性。虽然在很多情况下都可以正确地工作,但有些情况下还是无法正常使用的,在使用布告板时,一定要注意这点,这时生成顶点法线的方法就会失效。因为布告板由两个三角形背靠构造而成,它的两个法向量是相反的,其平均值为 0,所以不能初始化,这时只能采用别的方法来处理,如“双面”三角形等。

5.8 生成顶点法向量示例

生成顶点法向量(osgUtil::SmoothingVisitor)示例的代码如程序清单4-8所示

  1. osg::ref_ptr<osg::Geometry> createQuad2() // 创建一个四边形节点
  2. {
  3. // 创建一个几何体对象
  4. osg::ref_ptr<osg::Geometry> geom = new osg::Geometry();
  5. // 创建顶点数组,注意顶点的添加顺序是逆时针的
  6. osg::ref_ptr<osg::Vec3Array> v = new osg::Vec3Array();
  7. v->push_back(osg::Vec3(0.0f, 0.0f, 0.0f)); // 添加数据
  8. v->push_back(osg::Vec3(1.0f, 0.0f, 0.0f));
  9. v->push_back(osg::Vec3(1.0f, 0.0f, 1.0f));
  10. v->push_back(osg::Vec3(0.0f, 0.0f, 1.0f));
  11. geom->setVertexArray(v.get()); // 设置顶点数据
  12. // 创建纹理坐标
  13. osg::ref_ptr<osg::Vec2Array> vt = new osg::Vec2Array();
  14. vt->push_back(osg::Vec2(0.0f, 0.0f)); // 添加数据
  15. vt->push_back(osg::Vec2(1.0f, 0.0f));
  16. vt->push_back(osg::Vec2(1.0f, 1.0f));
  17. vt->push_back(osg::Vec2(0.0f, 1.0f));
  18. geom->setTexCoordArray(0, vt.get()); // 设置纹理坐标
  19. // 创建颜色数组
  20. osg::ref_ptr<osg::Vec4Array> vc = new osg::Vec4Array();
  21. vc->push_back(osg::Vec4(1.0f, 0.0f, 0.0f, 1.0f)); // 添加数据
  22. vc->push_back(osg::Vec4(0.0f, 1.0f, 0.0f, 1.0f));
  23. vc->push_back(osg::Vec4(0.0f, 0.0f, 1.0f, 1.0f));
  24. vc->push_back(osg::Vec4(1.0f, 1.0f, 0.0f, 1.0f));
  25. // 设置颜色数组
  26. geom->setColorArray(vc.get());
  27. geom->setColorBinding(osg::Geometry::BIND_PER_VERTEX); // 设置颜色的绑定方式为单个顶点
  28. geom->addPrimitiveSet( new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, 4)); // 添加图元,绘图基元为四边形
  29. return geom.get();
  30. }
  31. void smoothingVisitor_4_8()
  32. {
  33. // 创建 Viewer 对象,场景浏览器
  34. osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer();
  35. osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
  36. traits->x = 40;
  37. traits->y = 40;
  38. traits->width = 600;
  39. traits->height = 480;
  40. traits->windowDecoration = true ;
  41. traits->doubleBuffer = true ;
  42. traits->sharedContext = 0;
  43. osg::ref_ptr<osg::GraphicsContext> gc = osg::GraphicsContext::createGraphicsContext(traits.get());
  44. osg::ref_ptr<osg::Camera> camera = new osg::Camera;
  45. camera->setGraphicsContext(gc.get());
  46. camera->setViewport( new osg::Viewport(0, 0, traits->width, traits->height));
  47. GLenum buffer = traits->doubleBuffer ? GL_BACK : GL_FRONT;
  48. camera->setDrawBuffer(buffer);
  49. camera->setReadBuffer(buffer);
  50. viewer->addSlave(camera.get());
  51. osg::ref_ptr<osg::Group> root = new osg::Group();
  52. // 创建一个几何体对象 , 注意,几何体并没有指定法线
  53. // 如果你注释下面生成顶点法线的代码,你就可以看到
  54. // 光照的差别
  55. osg::ref_ptr<osg::Geometry> geometry = createQuad2();
  56. // 生成顶点法线
  57. osgUtil::SmoothingVisitor::smooth(*(geometry.get()));
  58. // 添加到叶节点
  59. osg::ref_ptr<osg::Geode> geode = new osg::Geode();
  60. geode->addDrawable(geometry.get());
  61. root->addChild(geode.get()); // 添加到场景
  62. // 优化场景数据
  63. osgUtil::Optimizer optimizer;
  64. optimizer.optimize(root.get());
  65. viewer->setSceneData(root.get());
  66. viewer->realize();
  67. viewer->run();
  68. }

运行程序,截图如图4-21所示

图4-21生成顶点法向量示例截图

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

OSG中几何体的绘制(二) 的相关文章

随机推荐

  • 008 Windows注册表

    一 注册表基础 1 概述 注册表 Registry 繁体中文版 Windows 操作系统称之为登录档案 是 Microsoft Windows 中的一个重要的数据库 用于 存储系统 和 应用程序 的设置信息 早在 Windows 3 0 推
  • 时序预测 | Python实现CNN电力需求预测

    时序预测 Python实现CNN电力需求预测 目录 时序预测 Python实现CNN电力需求预测 预测效果 基本描述 程序设计 参考资料
  • 海尔2024届秋招/校招内推信息/内推码

    公司名称 海尔 内推码 GHJ110 内推来源 内推鸭小程序 官方招聘网站 海尔招聘 海尔官方招聘网站
  • 每日一练2023.12.17——大笨钟的心情【PTA】

    题目链接 L1 077 大笨钟的心情 题目要求 有网友问 未来还会有更多大笨钟题吗 笨钟回复说 看心情 本题就请你替大笨钟写一个程序 根据心情自动输出回答 输入格式 输入在一行中给出 24 个 0 100 区间内的整数 依次代表大笨钟在一天
  • 挖矿木马应急响应-案例分析

    挖矿木马应急响应 案例分析 linux 终端无法使用系统资源使用异常高 首先解决linux命令无法使用的问题 显示libc so 6 没有重新连接一下libc文件 查看日志 发现木马运行成功后就日志一直报libc错误 根据信息向上插在日志
  • 2023年总结,讲讲我的故事吧,十年

    文章目录 2023 前十年 后十年 周末 本该是提升自己的最好时机 也该是出去玩的大好时光 但是毫无意外的 在家躺了一天 单纯的有点累 2023年 发生了好多事情 又好像没发生几件事 可能毕业季的我 走过了太多复杂的心路历程吧 身边的人 是
  • 服务器安全的威胁和防范

    由于服务器发挥着至关重要的作用 因此存储在服务器上的机密数据和信息非常具有价值 做好服务器安全至关重要 常见的服务器 安全隐患 包括 1 恶意的攻击 遭受CC攻击和DDoS攻击 导致游戏或是网站打不开 严重影响业务开展 2 网站挂马 网站被
  • 代码随想录算法训练营Day3 | 203.移除链表元素、707.设计链表、59.螺旋矩阵II

    LeetCode 203 移除链表元素 本题思路 就是常规的移除链表中的元素的操作 需要注意的点 头节点 head val val 的情况的处理 如果 head val val 就要继续往后 head head next 因此我们要遍历到第
  • 最强姿态模型 mmpose 使用实例

    mmpose 介绍 https blog csdn net jacke121 article details 135040186 图片姿态实例 本机地址 B project pose mmpose dev 1 x Copyright c O
  • Arrays.asList()方法:陷阱与解决之道

    在Java编程中 Arrays类提供了一系列用于操作数组的实用方法 其中 Arrays asList 方法是一个常用的方法 用于快速将数组转换为List集合 然而 这个方法存在一些潜在的陷阱 可能导致出现意外的行为 本文将介绍 Arrays
  • DSP捕获输入简单笔记

    程序 cap c Created on 2023年12月16日 Author My PC include cap h void cap init EALLOW SysCtrlRegs PCLKCR3 bit GPIOINENCLK 1 gp
  • 蓝禾2024届秋招/校招内推信息/内推码

    公司名称 蓝禾 内推码 SQDPVPM 内推来源 内推鸭小程序 官方招聘网站 https lanhevip jobs feishu cn index m position external referral code SQDPVPM
  • 007 Windows组策略

    组策略的应用 1 基本概念 组策略是一组策略的集合 组策略 英语 Group Policy 是 微软 Windows NT 家族操作系统的一个特性 它可以控制 用户帐户 和计算机帐户的工作环境 组策略提供了操作系统 应用程序 和 活动目录
  • 剑指 Offer(第2版)面试题 35:复杂链表的复制

    剑指 Offer 第2版 面试题 35 复杂链表的复制 剑指 Offer 第2版 面试题 35 复杂链表的复制 解法1 模拟 剑指 Offer 第2版 面试题 35 复杂链表的复制 题目来源 48 复杂链表的复刻 解法1 模拟 算法 复制原
  • mmpose 使用笔记

    目录 自己整理的可以跑通的代码 图片demo 检测加关键点 自己整理的可以跑通的代码 最强姿态模型 mmpose 使用实例 CSDN博客 图片demo python demo image demo py tests data coco 00
  • 2023“楚怡杯”湖南省赛“信息安全管理与评估“--数字取证调查(高职组)

    2023 楚怡杯 湖南省 信息安全管理与评估 高职组 任务书 2023 楚怡杯 湖南省 信息安全管理与评估 高职组 任务书 第一阶段竞赛项目试题 第二阶段竞赛项目试题 第二部分 数字取证调查 需
  • python快速实现简单的图片透明化

    整张图片透明化的完整代码如下 import os import glob from PIL import Image def convert to transparent image path output folder image Ima
  • Llama 架构分析

    从代码角度进行Llama 架构分析 Llama 架构分析 前言 Llama 架构分析 分词 网络主干 DecoderLayer
  • 牛客小白月赛83 解题报告

    题目链接 https ac nowcoder com acm contest 72041 question A题 解题思路 签到 代码 include
  • OSG中几何体的绘制(二)

    5 几何体操作 在本章的前言中就讲到 场景都是由基本的绘图基元构成的 基本的绘图基元构成简单的几何体 简单的几何体构成复杂的几何体 复杂的几何体最终构造成复杂的场景 当多个几何体组合时 可能存在多种降低场景渲染效率的原因 在很多3D引擎中