OSG开发概览

1 OSG基础知识

Ø OSGOpen Scene Graphic 的缩写,OSG1997年诞生于以为滑翔机爱好者之手,Don burns  为了对滑翔机的飞行进行模拟,对openGL的库进行了封装,osg的雏形就这样诞生了,1998Don burns 遇到了同样喜欢滑翔机和计算机图形学的Robert Osfield ,从此Robert Osfield加入了osg小组的开发并一直担任开发小组的组长。

Ø OSG不但有openGL的跨平台的特性和较高的渲染性能,还提供了一系列可供3D程序开发者使用的功能接口,包括2D3D数据文件的加载、纹理字体支持、细节层次(LOD)控制、多线程数据分页处理等。OSG广泛应用于飞行仿真等领域,包括Flightgear,及美国军方投资的仿真项目Delta3d

1.1 计算机绘图的基本知识

Ø 首先要先回顾一下,在显示世界中,我们是如何作画的。

Ø 在现实世界中,绘制一副画,我们需要的东西就是彩笔、白纸。通过选择不同颜色的彩笔,在白纸上移动,就可以将白纸上的不同的点描绘上不同的颜色,而所有这些点连接起来,从人的宏观视野看来,就构成了一副对人有意义的画作。

Ø 类比到计算机的实际中来。在计算机的世界里。作画的过程又是怎样的呢?

Ø 同样,绘制虚拟的图像,也需要“彩笔”和“白纸”。在计算机的世界里,“彩笔”就是Direct3D之类的绘图API函数,而“白纸”就是存储数据的内存。我们在内存中划分出一块区域,其中的数据就是对一个真实世界的模拟。一个数据就描述真实世界中一个点的属性。在我们作画前,他们都只有一个初始值,就像白纸在作画前只有白色一样。而在作画后,每一个数据都有了独特的意义,将整片数据连接在一起看,就是一副有意义的图景。作画的过程就是对内存中的每一个数据进行赋值的过程,相当于用彩笔给白纸上的一个点进行着色。选择不同的API函数,可以画出不同的形状。

1.2 OSG程序框架

Ø 一个最简单的OSG程序如下所示,当然在如果是在VS下面进行编辑的话要进行一些设置,要设置OSGlibinclude目录。


 1 #include<osgDB/ReadFile>2 3 #include<osgViewer/Viewer>4 5  void main()6 7 {8 9 osgViewer::Viewer viewer;
10 
11 viewer.setSceneData(osgDB::readNodeFile("glider.osg"));
12 
13 viewer.realize();
14 
15 viewer.run();
16 
17 }
18  

osgViewer::Viewer viewer 申请了一个viewer,可以理解为申请一个观察器,该观察可以查看模型

viewer.setSceneData(osgDB::readNodeFile("glider.osg")) 这里是设置观察器Viewer中的数据,换句话说,有了观察器,就可以添加模型了

viewer.realize() 这个语句表达的意思非常多,事实上可以定位到Viewer.cpprealize函数,会发现里面的操作非常多,可以理解为这是在渲染前的最后一步,会检查和设置图形上下文,屏幕啊什么的,会让你以前的设置,对Viewer的设置都生效。

viewer.run(); 这一句的意思就是渲染了,如果要解释它的意思的话,可以用下面的几个语句来替代:

while(!viewer.done()){viewer.frame();}.意思也就是说,只要viewer没有结束,那么就绘制它的每一个帧[frame]。

1.3 OSG简单模型控制

1.3.1 添加模型

OSG当中模型是使用osg::Grouposg::Node来装载在一起的,比如同时需要加入两个模型,模型A了模型BAB各自是一个NODE,那么可以使用以下语句来做到,首先使用一个Group,然后Group->addChild(A),同样,之后要Group->addChild(B)。然后再把Group添加到viewer当中就可以了。如图3.1所示AB之间的关系。在这里要申明的是NODEGroup的父类,在类中都有相应的方法可以转到对方,故NodeGroup

是通用的,Node也可以被当作Group来用。

 

aa

 

图 31 AB都加入到Group当中

简单示例代码如下:


1 #include<osgDB/ReadFile>2 3 #include<osgViewer/Viewer>4 5 #include<osg/Node>6 7  void main()8 9 {
10 
11 osgViewer::Viewer viewer;
12 
13 osg::Group * root=new osg::Group();
14 
15 root->addChild(osgDB::readNodeFile("glider.osg"));
16 
17 root->addChild(osgDB::readNodeFile("osgcool.osg"));
18 
19 viewer.setSceneData(root);
20 
21 viewer.realize();
22 
23 viewer.run();
24 
25 }
26  

则运行结果为:

 

x

图 32示例运行结果

1.3.2 删除结点

如果我们不需要某个结点了,比如图3.2我们看那个小飞机很不爽,我们想把它从场景中删除掉。不知道于某种目的,反正现在要删除掉,可能是开始想看见它现在不想看见它了。可以通过removeChild方法,除多个孩子也可以通过removeChildren方法,里面的参数有些需要索引值,有些需要结点本身的指针,读者可以自己尝试。这里要注意的是,如果要删除一个结点,那么该结点下的所有结点都会被删除。如果一个结点被加入到一个组中两次,那么这两次是分别存在的,删除一次还有另一次。删除操作不能说不是个危险的操作,有些时候,尤其在有移动结点等等混在一起时,删除操作有时候会发生一些比较奇怪的现象。在内存映象当中,如果一个模型被读取一次,而用了多次,那么所占用的空间是不会改变的。

1.3.3 隐藏模型与结点开关

Ø 隐藏模型

   隐藏模型其实模型仍在渲染当中,因此损耗并未减少,只不过隐藏了而已,隐藏的确不是个什么好操作,但是有时候对小模型确实也很实用。node->setNodeMask可以设置隐藏与显示。

Ø 节点开关

OSG当中,专门有一个类来负责打开与关闭结点,该类名为osg::Switch,里面有相应的方法来控制它所管理的结点的打开与关闭。

两个方法都能控制模型的显示和隐藏,区别在于隐藏模型方法不会让模型在内存中消失,这样对于小的物体频繁的调用会节省一些时间,而对于有些大的模块在用一次以后可能很久再用第二次,这个时候用节点开关可以将模型销毁,再次使用再调入内存,以防止占用更多的资源。

1.3.4 超级指针

超级指针的机制,其实就是引用一个计数器,这个计数器会计算这个箱子被引用的次数,被别人引用一次这个计数器增加一,别人不用一次,即:释放一次,则计数器减一。当减至0时,内存放掉不用。

们来看使用一个Node的三种方法,对比一下:

Ø //方法一,最好的方法,十分安全,也是OSG中最常用的方法,多少版本它都没变

osg::ref_ptr<osg::Node>aNode(new osg::Node());

group->addChild(aNode.get());

Ø //方法二,也是非常好的方法,有时候不适用,但也十分安全

group->addChild(new osg::Node());

Ø //方法三,非常危险,但是令许多人无故铤而走险的方法

osg::Node*anotherNode=new osg::Node();

group->addChild(anotherNode);

方法一:在new::Node()时申请了一个Node的资源,这时在堆内引用该Node的计算器会被置1。在group->addChild(aNode.get())时又引用了一次,会再加1。在这两次引用都结束时,Node的资源就会被释放。

方法二:这个方法也是很实用的,但是无法引出Node的指针,也许在别处可以用到,事实上会经常用到。如果已经这样做了,得到Node指针也不是不可以的,可以使用NodeVisitor来得到Node的指针,也可以使用findChild方法来做这件事。

方法三:这个应该是最常用,但是最烂的方法了,原因在于如果在osg::Node*antherode=new osg::Node()之后发生了错误,抛出了异常,谁来释放Node所占用的资源呢。而这个异常在后面被捕获,程序正常的走下去,而内存却没有被正常的放掉。

1.3.5 移动/旋转/缩放模型

移动/旋转/缩放其实都是对矩阵进行操作,在OSG当中,矩阵可以当作一个特殊的结点加入到root当中,而矩阵下也可以另入结点,而加入的结点就会被这个矩阵处理过,比如移动过/旋转过/缩放过。在OSG中控制矩阵的类为osg::MatrixTransform

Ø 移动

osg::Matrix::translate

Ø 旋转

osg::Matrix::rotate

Ø 缩放

osg::Matrix::scale

1.4 基本几何图元

1.4.1 基本绘制方法

首先来看一些OSG中的最基本的绘制路数。如果我们要绘制一个正方形,绘制有色彩,未贴图。首先我们必须要申请一个osg::Geometry,把这个Geometry加入到Geode就可以了。在这个Geometry中要设置一些元素,最基本的是顶点Vertex,颜色color,以及顶点的关联方式和法线normal.就可以了。如图3.3所示。

 x

 

图 33几何体绘制过程

1.4.2 可绘制的图元

所有可绘制的图元包括:

Ø POINTS[]

Ø LINES[线]

Ø LINE_STRIP[线带]

Ø LINE_LOOP[闭合线段]

Ø TRIANGLES[三角形]

Ø TRIANGLE_STRIP[三角带]

Ø TRIANGLE_FAN[三角扇]

Ø QUADS[四方块]

Ø QUAD_STRIP[四方块带]

Ø POLYGON[多边形]

OSG中设置直线线宽的专门有一个函数来管理,叫做LineWidth,它本身属于状态与属性类别中的类。事实上也是从那里派生而来。所有设置状态的操作都与此类似。

1.4.3 内置几何类型

如同OpenGL一样,OSG同样有一套内置几何类型,这些几何类型都在类osg::Shape中,这些shape本身都可以本当成一个Draw结点加入到geode中,然后再人geode中添加到root里进行渲染。形状共有九种,分别为:osg::Box[盒子]osg::Capsule[胶囊形]osg::CompositeShape[组合型]osg::Cone[圆锥形]osg::Cylinder[圆柱形]osg::HeightField[高程形]osg::InfinitePlane[有限面]osg::Sphere[球形]osg::TriangleMesh[三角蒙皮]

内置几何类型的渲染过程,如图4.5所示

 bb

 

图 34基本几何图元的添加过程

这里要注意的是,一般的形状态都有特定的因素,比如Box有长宽,圆有半径,以及各个图形所画的精细度都需要指明,这些精细度在球这样的形状上意义还是十分巨大的。在OSG中有专门指明精细度的类,名为:osg::TessellationHints。以球为例,只需要规定,圆心,半径和精细度就可以画出该球。

1.5 交互

1.5.1 交互过程

viewer的主要的功能是控制场景,它是场景的核心类,如果能响应键盘时得到viewer,那么也可以从键盘的响应中控制整个场景。viewer中有一个方法,名为addEventHandler就是专门做这件事情的。他会加入一个事件处理器。于是我们就想,一定要自己写一个事件处理器才行,这就必须要了解事件处理器的格式,只要有一个接口就可以了解它的格式,这个接口就是:osgGA::GUIEventHandler,于是我们可以写一个类A从该类公有派生出来,即:class Apublic osgGA::GUIEventHandler,在里面处理好各种操作然后加入到viewer当中,即:viewer.addEventHadler(new A(里面可以有参数));这样就可以完成操作。

假如类A是一个事件处理类,那么加入类A可以这样理解,如图3.5

 

c

图 35事件A控制场景过程

 

1.5.2 事件类型与响应

代码                 值            事件类型

NONE               0                无事件。

PUSH                 1       鼠标某键按下,在上面代码28行有用到。

RELEASE        2       鼠标某键弹起。

DOUBLECLICK   4       鼠标某键双击。

DRAG         8       鼠标某键拖动。

MOVE      16       鼠标移动。

KEYDOWN    32       键盘上某键按下。

KEYUP      64       键盘上某键弹起。

FRAME      128     应该是鼠标每帧。没用过。

RESIZE      256     窗口大小改变时会有的事件。

SCROLL      512     鼠标轮滚动。

PEN_PRESSURE  1024     手写板的某事件?

PEN_PROXIMITY_ENTER  2048   手写板的某事件?

PEN_PROXIMITY_LEAVE   4096   手写板的某事件?

CLOSE_WINDOWS    8192   关闭窗口。

QUIT_APPLICATION    16384   退出程序。

USER           32768   用户定义。

至于为什么都用2N次方,主要是因为它的二进制编码只有一位是一,判断事件时很好判断,只要年哪位是一就可以了。

1.5.3 PICK

pick主要是通过鼠标的点击来拾取一些物体,或者判断鼠标所点击的位置在哪里。Pick实现的思路如下图所示:

 x

 

图 36pick事件流程

判断射线与viewer中物体相交的方法为发出射线并相交。在OSG中有库函数,osgViewer::View::computeIntersections他共有三个参数:第一个是x屏幕坐标,第二个是Y屏幕坐标,第三个是存放被交的结点以及相交的坐标结点路径等等相关信息。

判断相交结点为我想要的那个结点:只需要判断存放相交射线交场景的结果集中有没有要用的结点就可以了。

 

1.6 漫游

1.6.1 MatrixManipulator

场景的核心管理器是viewer,而漫游必须响应事件,比如鼠标动了,场景也在动。响应事件的类是osgGA::GUIEventHandler。我们想把响应事件的类派生一个新类出来,这个类专门用来根据响应控制viewer。这个类就是osgGA::MatrixManipulator,这个类有一些设置矩阵的公共接口,有了这些接口就可以有效的控制viewer了,根据不同的习惯,大家还会设置不同的控制方式,如同OSG自带的几个操作器,操作都不尽相同。来看一下漫游的主要流程如图6.1

 

s

图 37一般的场景操作器

操作器必须从osgGA::MatrixManipulator派生而来。osgGA::MatrixManipulator有四个可以控制场景的重要接口:


1 virtual void setByMatrix(const osg::Matrixd&matrix)=0
2 
3  virtual void setByInverseMatrix(const osg::Matrixd&matrix)=0
4 
5  virtual osg::Matrixd getMatrix()const=0
6 
7  virtual osg::Matrixd getInverseMatrix()const=0
8  

四个矩阵接口可以有效的向viewer来传递矩阵的相关信息。

1.6.2 碰撞检测

最简单的碰撞检测如下图所示:

 

z

图 38简单的碰撞检测原理图

TravelManipulator.dll中用到的就是如图所示的原理,黑三角形代表没有移动之的位置,控制移动的函数是ChangePosition(osg::Vec3&delta),参数意思是要移动的相对于当前点的增量,在黑三角形没有移动时该函数在计算时先假设一点newPosition为移动后的点,而后通过连接这两个点,而后通过判断与场景的模型是否有交点来判定这个移动可不可以执行,如图所示,两者之间有个大盒子,是穿不过去的,所以只有保持在原地。就算没有这个盒子,移动后的新点又与地面在某种程序上有一个交点,这证明移动是不可行的。这可以防止用户穿过地板到达地下去。

1.6.3 路径漫游

使用path文件的方法如下面示例


1 #include<osgDB/ReadFile>2 3 #include<osgViewer/Viewer>4 5 #include<osg/Node>6 7 #include<osgGA/AnimationPathManipulator>8 9  void main()
10 
11 {
12 
13 osgViewer::Viewer viewer;
14 
15 viewer.setSceneData(osgDB::readNodeFile("glider.osg"));
16 
17  //申请一个操作器,参数为一个path文件。
18  
19 osg::ref_ptr<osgGA::AnimationPathManipulator>amp=new osgGA::AnimationPathManipulator("glider.path");
20 
21  //选择使用这个操作器。
22  
23 viewer.setCameraManipulator(amp.get());
24 
25 viewer.realize();
26 
27 viewer.run();
28 
29 }
30 
31  

我们可以用路径编辑器编辑path文件,或者可以控制程序中的某个物体的运动轨迹然后保存为path文件。

1.7 更新&回调

回调的意思就是说,你可以规定在某件事情发生时启动一个函数,这个函数可能做一些事情。这个函数就叫做回调函数,我们可以使用已有回调函数或者自定义回调函数。

Ø 使用已有回调

已有的回调的类型有很多种,一般很容易就想到的是UpdateCallBack,或者EventCallBack

Ø 自定义回调

自定义回调为从一个回调类型派出生自己的回调,然后具有该种回调的特点等等。

NodeVisitor是一个极有用的类,可以访问结点序列,使用的方法大同小异,NodeVisitor的工作流程如下图所示:

 

v

图 39NodeVisitor工作流程

在主结点accept之后,结点数据立即传至NodeVisitor中去,应用apply函数,可以将数据定任一些操作,更多的操作还是需要硬性的制做与调用。

1.8 粒子系统初步

OSG中提供有专门的粒子系统工具,名字空间为osgParticleOSG对经常使用的粒子模拟都做了专门的类,如:ExplosionEffect用于暴炸的模拟,FireEffect用于火的模拟,ExplosionDebrisEffect用于爆炸后四散的颗粒模拟等等。

OSG中使用粒子系统一般要经历以下几个步骤:

第一步:确定意图(包括粒子的运动方式等等诸多方面)。第二步:建立粒子模版,按所需要的类型确定粒子的角度(该角度一经确定,由于粒子默认使用有Billboard所以站在任何角度看都是一样的),形状(圆形,多边形等等),生命周期等。第三步:建立粒子系统,设置总的属性,第四步:设置发射器(发射器形状,发射粒子的数目变化等),第五步:设置操作(旋转度,风力等等因素)。第六步:加入结点,更新。下图描述了各个部分是协调工作的方式:

 

b

图 310粒子系统各个部分是协调工作的方式

上图中各个部分所对应的类如下图所示

 

v

图 311粒子系统各部分对应的类

 

1.9 视口&LOD&Imposter

1.9.1 多视口

多视口的原理是自己创建所有的相机,包括主相机,这样我们可以随意的添加相机。

首先我们要创建视口必须有以下几件东西,第一,了解整个屏幕的分辩率有多大,这样可以分辩视口的大小,好分割开来。第二,上下文。我们必须自己手动的打开设置上下文。每个视口的数据也不一定非要与主视口的相同。但是矩阵一般是同步的。也就是说:主视口里有栋楼,从视口里可以是平面图什么的。了解整个屏幕的分辩率可以用这个类:osg::GraphicsContext::WindowingSystemInterface意思是说系统接口,可以获得当前环境的各种信息。有一方法叫getScreenResolution,可以得到分辩率。之后上下文了,osg::GraphicsContext里面可以设置窗口大小,缓存什么的,大多数的东西都在这里面设置。

1.9.2 LOD

LODlevel of details

LOD比起PagedLOD而言并非十分的常用,有个地方用的特别多,那就是把一个好好的模型加一个视矩压成一个模型,这个模型比以前的看来就是多了个视矩的控制,远了看不见,近了能看见。

在模型中加LOD头结点的方式如下所示:


1 #include<osgDB/Registry>2 3 #include<osgDB/ReadFile>4 5 #include<osgDB/ReaderWri ter>6 7 #include<osgDB/Wri teFile>8 9 #include<osg/Node>
10 
11 #include<osgViewer/Viewer>
12 
13  int main()
14 
15 {
16 
17 osgViewer::Viewer viewer;
18 
19  //读取模型
20  
21 osg::Node*node=osgDB::readNodeFile("fountain.osg");
22 
23  //隐藏结点
24  
25 node->asGroup()->getChild(0)->setNodeMask(0);
26 
27 viewer.setSceneDa ta(node);
28 
29  //输出结点到free.os g中
30  
31 osgDB::writeNodeFile(*(viewer.getSceneData()),"free.osg",osgDB::Registry
32 
33 ::instance()->getOptions());
34 
35  return 0;
36 
37 }
38 
39  

1.9.3 Imposter

用动态图片来替换场景的实用技术:imposter.可以把它法做LOD一样使用,只不过它

不是变模型变没有,而是使它换成一张图

示例代码如下:设置一个视矩,超过这个视距模型会变为一张动态图


1 #include<osgViewer/Viewer>2 3 #include<osgGA/TrackballManipulator>4 5 #include<osgSim/Impostor>6 7 #include<osgDB/ReadFile>8 9  int main(inta rgc,cha r**a rgv)
10 
11 {
12 
13  //申请viewer
14  
15 osgViewer::Viewer viewer;
16 
17  //读取模型
18  
19 osg::Node*node=osgDB::readNodeFile("ceep.ive");
20 
21  //申请一个i mpos tor结点
22 
23 osgSim::Impos tor*sim=new osgSim::Impostor;
24 
25 //在到之内显示模型,之外显示贴图
26 
27 sim->addChild(node,0,50000);
28 
29 sim->setImpostorThreshold(1000);
30 
31 osg::Group*root=new osg::Group;
32 
33 root->addChild(sim);
34 
35 viewer.setSceneData(root);
36 
37 viewer.realize();
38 
39 viewer.run();
40 
41 return 0;
42 
43 }
44 
45 

1.10 文字&模型阴影

1.10.1 HUD 

HUDhead up display

文字在3D场景中显示往往要经历以下几步:读取字体点阵信息->转化为图像->反走样->最终图像。在反走样期间可以处理可种模糊效果,在最终图像形成时可以设置如何摆放。OSG中有一个TEXT类,提供可很多文字显示的方法,比如


void setFont(Font*font=0)//设置/得到字体,如setFont("fonts/SIMYOU.TTF");void setFont(const std::string&fontfile)const Font*getFont()const//设置/得到字体显示的宽高void setFontResolution(unsigned int width,unsigned int height)unsigned int getFontWidth()constunsigned int getFontHeight()const//设置/得到文字的具体内容

等等,可以很方便的调用

1.10.2 阴影

OSG对阴影的支持也相当的好,可以很容易的写出简单的阴影效果,可以参考例子osgShadow

OSG有一个专门的shadow类来支持阴影效果,提供了很多接口,如:


1 void setBackdropType(BackdropType type)2 3 //说明:设置阴影类型。4 5 void setBackdropOffset(float offset=0.07f)6 7 void setBackdropOffset(float horizontal,float vertical)8 9 //说明:设置阴影的离开程度与方向
10 
11 void setBackdropColor(const osg::Vec4&color)
12 
13 //说明:设置阴影颜色
14 
15 void setColorGradientMode(ColorGradientMode mode)
16 
17 //说明:设置颜色映射方式,可以得到渐变效果
18 

等等

 

PS:本文为几个月前整理,参考书:FreeSouth的《QpenSceneGraph程序设计》



本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/543512.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

hbuilder php xdebug,Hbuilder使用xdebug配置php断点调试

2019独角兽企业重金招聘Python工程师标准>>>##1. 背景不得不说Hbuilder是免费的前端开发工具中比较好用的&#xff0c;而且配合aptana开发php也马马虎虎(毕竟写前端的时候多些)。本人原是搞java的&#xff0c;后来打算用php做些个人项目(因为服务器成本低)&#xff0c…

mx播放器有没有投屏功能_无线投屏、即插即用,投影仪其实可以更智能:明基 E580T...

无论是简单的办公室会议还是小型的线下活动&#xff0c;投影仪都是必不可少的利器&#xff1a;既能有不错的显示效果&#xff0c;也不用受屏幕尺寸的约束。尽管越来越多的智能电视可供电脑连接&#xff0c;但真正派上用场的时候&#xff0c;拎箱就走的投影仪显然是最佳选择。很…

特殊矩阵-对角矩阵

2019独角兽企业重金招聘Python工程师标准>>> 挖坑。 转载于:https://my.oschina.net/aslanjia/blog/651503

vs运行时候冒了这个错:无法启动IIS Express Web 服务器~Win10

后期会在博客首发更新&#xff1a;http://dnt.dkill.net 异常处理汇总-服 务 器 http://www.cnblogs.com/dunitian/p/4522983.html 网上的方法多种&#xff0c;有让安装扩展插件的&#xff0c;有让在程序里面添加Http系列的组件&#xff0c;有其它其它的&#xff0c;可是。。。…

matlab脚本 定时停止_一触即发是什么软件?它是手机上极其强大的一款脚本辅助精灵...

一触即发app是手机上极其强大的一款免root的脚本辅助软件&#xff0c;堪称一键秒杀脚本精灵&#xff0c;除自动化、运行、管理外&#xff0c;还提供了脚本制作文字教程/视频教程&#xff0c;学习社区和图色处理、定时执行、王者荣耀、变量等命令参数和多点找色、多点找图、京东…

笔记本电脑处理器_高通提示低成本5G芯片更强大的笔记本电脑处理器

高通公司总裁克里斯蒂亚诺阿蒙(Cristiano Amon)在今天的柏林IFA贸易展览会的虚拟主题演讲中说&#xff0c;我们将很快看到更便宜的5G手机&#xff0c;以及更多具有更好应用兼容性的Windows-on-Snapdragon笔记本电脑。欧洲主要的电子产品展览会IFA今年被分成​​几个小组活动&am…

为什么6lowpan 要有四个地址_大型监控网络系统如何规划ip地址

本文转自网络对于监控项目来说&#xff0c;很多故障的原因都是跟ip地址设置不当有关&#xff0c;如ip冲突&#xff0c;或者有几路监控图像没有显示等&#xff0c;都是跟ip有一定关联&#xff0c;合理的分配ip地址十分重要。一、为什么要合理分配IP对于小型监控项目来说&#xf…

JAVA中的命令模式实例教程

原文链接 作者&#xff1a;Pankaj Kumar 译者&#xff1a;f0tlo <1357654289qq.com> 命令模式是一种行为模式&#xff0c;因此&#xff0c;它处理的是对象的行为。命令模式为系统中不同的对象提供中性化的交流媒介。根据GoF的定义&#xff0c;命令模式是&#xff1a; 通…

bugku 管理员系统 后台代码_不会吧,这也行?iOS后台锁屏监听摇一摇

[toc] 背景介绍 一般情况下&#xff0c;出于省电、权限、合理性等因素考虑&#xff0c;给人的感觉是很多奇怪的需求安卓可以实现&#xff0c;但是iOS就无法实现&#xff01;今天要介绍的需求也有这种感觉&#xff0c;就是“当 APP 处于后台或锁屏状态时&#xff0c;依旧可以监听…

windows php5.3升级,Windows10系统将PHPNOW升级PHP版本为5.3.5

Windows 10发布很久了&#xff0c;现在大多数人都在使用&#xff0c;在WIN10中使用PHPNOW&#xff0c;觉得自带的PHP版本有点低&#xff0c;所以就想升级下&#xff0c;在网上搜索了一些方法&#xff0c;然后结合自己的实际操作&#xff0c;在这里分享下。1、首先要下载PHP5.3.…

igs无法分配驱动器映射表_硬盘无法使用,用DiskPart进行分区和格式化,非常简单...

如果计算机硬盘出现问题&#xff0c;有时不是硬件上出现了错误&#xff0c;很可能只是逻辑上出现了问题&#xff0c;这时就可以使用DiskPart来快速解决。在Windows 10上&#xff0c;当外部存储(例如U盘、可移动硬盘或SD卡)由于数据损坏或其他问题而停止工作时&#xff0c;可以使…

硬件nat关闭还是开启_超能课堂(173):AfterBurner不止超频,还是绝佳的游戏伴侣...

微星AfterBurner软件可以说是一个相当好用的显卡工具&#xff0c;它好用的超频功能估计都不用我多说了吧&#xff1f;微星并没有把这款软件限制在自己品牌的显卡能用&#xff0c;各个品牌的显卡都能用&#xff0c;无论A卡还是N卡都可以用AfterBurner来超频&#xff0c;软件在超…

mx350显卡天梯图_CPU天梯图与显卡天梯图2020年最新版

最新CPU天梯图较之以往没有太大的变化&#xff0c;前十位置还是那几款。但是继阿里之后&#xff0c;腾讯也开始准备自己制作芯片了&#xff0c;毕竟自研AI芯片的诱惑还是很大的&#xff0c;2020年有不少的厂商都推出了新鲜美味的显卡&#xff0c;有些是老卡翻新做性价比。有的则…

matlab写字,Matlab实现鼠标写字代码

类型&#xff1a;编程工具大小&#xff1a;1.5M语言&#xff1a;中文 评分&#xff1a;1.2标签&#xff1a;立即下载最早的程序&#xff0c;实在忘了从哪里下载的了。能够实现鼠标的手写输入&#xff0c;但是一些不连续的点。tmouse.mfunction tmouse(action)% TMOUSE 本例展示…

from rfc 2068 hypertext怎么解决_你好,打工人!用英语怎么表达“打工人”?可别直接说 worker...

打工人&#xff0c;打工魂&#xff0c;打工人是人上人&#xff01;最近&#xff0c;「打工人」这个词火了&#xff01;几乎一夜之间&#xff0c;很多人在和朋友打招呼时&#xff0c;都自称“打工人”。那“打工人”是什么意思&#xff1f;这里的“打工人”&#xff0c;其实是对…

STM32连续采样_STM32 - 利用双缓冲实现实时曲线显示(续)

前言大概半个月之前捣鼓了下利用STM32实现实时曲线显示&#xff0c;中间又做了一点小改进和扩充&#xff0c;在这里更新一下&#xff1a;利用DMA进行缓冲区到LCD GRAM的像素数据搬运效果更好的曲线绘制策略代码可以在这里找到&#xff1a;<写得比较乱&#xff0c;望谅解( &a…

Vmware虚拟机三种网络模式详解

原文来自http://note.youdao.com/share/web/file.html?id236896997b6ffbaa8e0d92eacd13abbf&typenote 我怕链接会失效&#xff0c;故转载此篇文章。通过这篇文章&#xff0c;我对之前疑惑的地方有了直观的理解&#xff0c;很多地方并没有自己动手实践&#xff0c;所以这篇…

ros 双wan配置_基于ROS搭建简易软件框架实现ROV水下目标跟踪(九)--程序解析之PWM波下发...

模块对应cabin_controllers/serial_to_mcu。模块实现的功能为监听网络中PWM矩阵信息&#xff0c;将其转换成十六进制数据通过串口下发至MCU&#xff0c;实现对推进器电机的控制。模块数据的串口通信借助了ros的serial工具包&#xff08;sudo apt-get install ros-melodic-seria…

2018php项目实战视频教程,2018PHP实战技术VIP在线学习视频课程

课程目录&#xff1a;1-1 疯狂讲义之web简介2-1 从搭建PHP开发环境开始2-2 第一个PHP程序2-3 PHP变量相关知识2-4 PHP数据类型2-5 PHP数据类型之进制转换2-6 PHP数据类型之浮点型2-7 PHP数据类型系统函数简介3-1 PHP数据类型字符串的声明与定义3-2 数据类型之数组、资源、null类…

Struts1.x在MyEclipse中的环境搭建和配置

2019独角兽企业重金招聘Python工程师标准>>> &#xff08;一&#xff09; 先解压Struts-1.3.10-all.zip的文件夹Struts-1.3.10-all备用 -> 打开MyEclipse -> 新建一个 web project -> 在工程名上按右键鼠标选 Properties -> 弹出 Properties 面板 …