当前位置: 首页 > news >正文

OSG编程指南<十三>:OSG渲染状态

1、前言

  在 OSG 中存在两棵树,即场景树和渲染树。渲染树是一棵以 StateSet 和 RenderLeaf
为节点的树,它可以做到 StateSet 相同的 RenderLeaf 同时渲染而不用切换 OpenGL状态,并且做到尽量少但在多个不同 State 间切换。渲染树在 CullVisitor 的 cull 过程中逐渐创建。后面所讲到的纹理、光照及材质,都是关于渲染状态的控制。

2、渲染状态

  OSG 支持绝大部分的 OpenGL 固定功能管道(fixed function pipeline)渲染,如 Alpha 检验、Blending融合、剪切平面、颜色蒙板、面拣选(face culling)、深度和模板检验、雾效、点和线的光栅化(rasterization)等。OSG 的渲染状态也允许应用程序指定顶点着色(vertex shader)和片段着色(fragment shader)。

2.1 osg::StateSet 类

  osg::StateSet 类派生自 osg::Referenced,以实现更好的数据共享。也就是说,共享同一个 osg::StateSet的 osg::Node 或 osg::Drawable 类不需要额外的代码来清理其内存空间。

  用户的应用程序需要在 osg::StateSet 中设置渲染状态。可以将 StateSet 关联到场景图形中的任意一个节点(Node)或关联到 Drawable 类。正如大部分开发者所知,OpenGL 程序的开发需要尽量使状态量的变化实现最小化,并避免冗余的状态设置,StateSet 对象能够自动实现这些优化过程。在 OSG 遍历整个场景图形时,StateSet 类会对 OpenGL 的状态属性堆栈进行管理。因此,用户程序可以对不同的场景图形子树作不同的状态设置。在每个子树的遍历过程中,OSG 将会高效地执行保存和恢复渲染状态的操作。用户需要尽量使关联到场景图形的 StateSet 最少化。StateSet 越少,内存的占用也越少,OSG在一次场景图形遍历中所耗费的工作量也越少。

  OSG 将渲染状态分成两个部分,分别为渲染属性(Attribute)和渲染模式(Mode)。渲染属性也就是控制渲染特性的状态变量,如雾的颜色或 Blend 融合函数都是 OSG 的状态属性。OSG 中的渲染模式和 OpenGL 的状态特性几乎是一一对应的,这些特性在 OpenGL 中通过函数 glEnable()和 glDisable()进行控制。用户程序可以设置模式量以允许或禁止某个功能,如纹理映射、灯光等。简单来说,渲染模式是指渲染的某个功能,而渲染属性是这个功能的控制变量和参数。如果要设置渲染状态的值,用户程序需要执行以下两步操作:

(1)为将要设置状态的 Node 或 Drawable 对象提供一个 StateSet 实例。
(2)在 StateSet 实例中设置状态的渲染模式和渲染属性。

直接从某个 Node 或 Drawable 对象中获得一个 StateSet 实例可以使用下面的方法:

osg::StateSet* state = obj->getOrCreateStateSet();

  在上面的程序段中,obj 是一个 Node 或 Drawable 实例;getOrCreateStateSet()是这些类定义的方法,这个方法返回一个指向 StateSet 实例的指针,该实例属于 obj。如果 obj 还没有设置过与之关联的StateSet,那么这个方法返回一个新指针并将其关联到 obj 上。

  StateSet 继承自 Referenced 类。与 StateSet 关联的 Node 或 Drawable 类内部使用 ref_ptr<>来引用StateSet 实例,因此,不是长时间引用 StateSet 的情况下,也可以使用标准 C++指针来定义 state。如果state 变量是某个函数内的局部变量,且应用程序不会长时间引用这个StateSet,那么上面代码的使用是完全正确的。上面代码中的 state 变量指向该 obj 对象的 StateSet 指针,当应用程序获得了一个 StateSet的指针时,就可以设置属性和模式了。

2.2 渲染属性和渲染模式

  OSG 为每个状态属性定义了不同的类,以便应用程序采用。所有的属性类均继osg::StateAttribute,osg::StateAttribute 类是一个无法直接实例化的虚基类。

  OSG 将所有的属性和模式分为两大部分,即纹理(texture)和非纹理(non-texture)。本节将主要探讨非纹理渲染状态的设置。纹理渲染状态的设置将在后面的章节讨论。OSG 之所以为纹理属性的设置提供不同的接口,主要是因为纹理属性需要特别为多重纹理设置纹理单元(texture unit)。

1.设置渲染属性(Attribute)

  如果要设置一项属性,首先需要将修改的属性类实例化,设置该类的数值,然后用 osg::StateSet::setAttribute()将其关联到 StateSet。下面的代码段用于实现面剔除(face culling)的属性:

//获取变量 geom 的 StateSet 指针
osg::StateSet*state = geom->getOrCreateStateSet();
//创建并添加 CullFace 属性类
osg::CullFace*cf = new osg::CullFace( osg::CullFace::BACK );
state->setAttribute(cf);

  在上面的代码段中,geom 是一个 Geometry 几何类对象(当然也可以是任何其他派生自 Drawable和 Node 的对象),获取 geom 的 StateSet 指针后,代码创建了一个新的 osg::CullFace 对象,并将其关联到状态量。

2.设置渲染模式(Mode)
  用户可以使用 osg::StateSet::setMode()设置允许或禁止某种模式。例如,下面的代码将打开雾效模式的许可:

//获取一个 StateSet 实例
osg::StateSet*state = geom->getOrCreateStateSet();
//允许这个 StateSet 的雾效模式
state->setMode( GL_FOG, osg::StateAttribute::ON );

setMode()的第一个输入参数可以是任何一个在 glEnable()或 glDisable()中合法的 OpenGL 枚举量Glenum;第二个输入参数可以是 osg::StateAttribute::ON 或 osg::StateAttribute::OFF。事实上,这里用到了位屏蔽技术,这个技术将在后面讲解继承状态时说明。

3.设置渲染属性和模式

  OSG 提供了一个简单的、可以同时设置属性和模式的单一函数接口。在很多情况下,属性和模式之间都存在显著的关系。例如,CullFace 属性的对应模式为 GL_CULL_FACE。如果要将某个属性关联到一个 StateSet,同时要求打开其对应模式的许可,可以使用osg::StateSet::setAttributeAndModes()方法。

下面的代码段将关联 Blend 融合检验的属性,同时许可颜色融合模式。

//创建一个 BlendFunc 属性
osg::BlendFunc*bf = new osg::BlendFunc();
//关联 BlendFunc 并许可颜色融合模式
state->setAttributeAndModes( bf );

  setAttributeAndModes()的第二个输入参数用于允许或禁止第一个参数中渲染属性对应的渲染模
式,其默认值为 ON。这样,用户的应用程序只需用一个函数就可以方便地指定某个渲染属性,并许可其对应的渲染模式。

2.3 状态继承

  当读者设置节点的渲染状态时,这个状态将被赋予当前的节点及其子节点。如果子节点对同一个渲染状态设置了不同的属性参数,那么新的子节点状态参数将会覆盖原有的。也就是说,默认情况下子节点可以改变自身的某个状态参数或者继承父节点的同一个状态。

  状态继承特性在许多情况下都非常实用,但有时渲染可能需要更多特性。假设场景图形中有一个包含了实体多边形几何体的节点,如果要以线框模式来渲染场景图形,读者的程序就需要覆盖这种多边形渲染模式状态,而不论它出现在什么位置。OSG 允许用户根据场景图形中任意位置的渲染属性和模式需求单独改变原有的状态继承特性。可以选择以下几种枚举形式。

osg::StateAttribute::OVERRIDE:如果将一个渲染属性和模式设置为 OVERRIDE,那么所有的子节点都将继承这一属性或模式,子节点对它们的更改将会无效。
osg::StateAttribute::PROTECTED:这种形式可以视为 OVERRIDE 的一个例外。凡是设置为PROTECTED 的渲染属性或模式,均不会受到父节点的影响。
osg::StateAttribute::INHERIT:这种模式强制子节点继承父节点的渲染状态,其效果是子节点
的渲染状态被解除,而使用父节点的状态替代。

  读者可以对这些参数进行位或叠加操作,然后再作为 setAttribute()和 setMode()建立一个场景图形和 setAttributeAndModes()的第二个参数输入。下面的代码段将强制使用线框模式渲染场景图形:

//获取根节点的渲染状态 StateSet
osg::StateSet*state = root->getOrCreateStateSet();
//创建一个 PolygonMode 渲染属性
osg::PolygonMode*pm = new osg::PolygonMode)
osg::PolygonMode::FRONT_AND_BACK, osg::PolygonMode::LINE );
//强制使用线框渲染
state->setAttributeAndModes( pm,osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE );

  使用 PROTECTED 参量可以保证父节点的渲染状态不会覆盖子节点的渲染状态。例如,读者可能创建了一个发光的场景,其中包含有使用亮度照明的光源几何体,如果其父节点禁用了光照,那么光源几何体的渲染将会出错。这时,对光源几何体的 GL_LIGHTING 渲染状态使用 PROTECTED 就可以保证它依然可用。

3、渲染状态示例

3.1 效果

在这里插入图片描述

3.2 源码

// TestOSGProject.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。#include <windows.h>
#include <osgViewer/Viewer>
#include <iostream>
#include <osg/Node>
#include <osg/Geode>
#include <osg/Geometry>
#include <osg/Group>
#include <osg/Billboard>
#include <osg/Texture2D>
#include <osg/Image>
#include <osg/Vec3>
#include <osg/Vec2>
#include <osg/PositionAttitudeTransform>
#include <osg/MatrixTransform>
#include <osgDB/ReadFile>
#include <osgUtil/Optimizer>
#include <osg/ClipNode>
#include <osgViewer/ViewerEventHandlers> //事件监听
#include <osgGA/StateSetManipulator> //事件响应类,对渲染状态进行控制
#include <osgUtil/Simplifier> //简化几何体
#include <osgUtil/DelaunayTriangulator> 
#include <osgUtil/TriStripVisitor>
#include <osgUtil/SmoothingVisitor>#pragma comment(lib, "OpenThreadsd.lib")
#pragma comment(lib, "osgd.lib")
#pragma comment(lib, "osgDBd.lib")
#pragma comment(lib, "osgUtild.lib")
#pragma comment(lib, "osgGAd.lib")
#pragma comment(lib, "osgViewerd.lib")
#pragma comment(lib, "osgTextd.lib")osg::ref_ptr<osg::Node> createClipNode(osg::ref_ptr<osg::Node> subgraph)
{osg::ref_ptr<osg::Group> root = new osg::Group();osg::ref_ptr<osg::StateSet> stateset = new osg::StateSet();//多边形线形绘制模式,正面和反面都绘制osg::ref_ptr<osg::PolygonMode> polymode = new osg::PolygonMode();polymode->setMode(osg::PolygonMode::FRONT_AND_BACK, osg::PolygonMode::LINE);//启用多边形线形绘制模式,并指定状态继承属性为 OVERRIDEstateset->setAttributeAndModes(polymode, osg::StateAttribute::OVERRIDE | osg::StateAttribute::ON);//多边形线形绘制节点osg::ref_ptr<osg::Group> wireframe_subgraph = new osg::Group;//设置渲染状态wireframe_subgraph->setStateSet(stateset.get());wireframe_subgraph->addChild(subgraph.get());root->addChild(wireframe_subgraph.get());osg::ref_ptr<osg::MatrixTransform> transform = new osg::MatrixTransform;//更新回调,实现动态裁剪osg::ref_ptr<osg::NodeCallback> nc = new osg::AnimationPathCallback(subgraph->getBound().center(),osg::Vec3(0.0f, 0.0f, 1.0f), osg::inDegrees(45.0f));transform->setUpdateCallback(nc.get());//创建裁剪节点osg::ref_ptr<osg::ClipNode> clipnode = new osg::ClipNode();osg::BoundingSphere bs = subgraph->getBound();bs.radius() *= 0.4f;//设置裁剪节点的包围盒osg::BoundingBox bb;bb.expandBy(bs);//根据前面指定的包围盒创建 6 个裁剪平面clipnode->createClipBox(bb);//禁用拣选clipnode->setCullingActive(false);transform->addChild(clipnode.get());root->addChild(transform.get());//创建未被裁剪的节点osg::ref_ptr<osg::Group> clippedNode = new osg::Group;clippedNode->setStateSet(clipnode->getStateSet());clippedNode->addChild(subgraph.get());root->addChild(clippedNode.get());return root.get();
}int main()
{//添加到根节点osg::ref_ptr<osg::Group> root = new osg::Group();osg::ref_ptr<osg::Node> childNode = osgDB::readNodeFile("cessna.osg");osg::ref_ptr<osg::Node> node = createClipNode(childNode.get());root->addChild(node.get());//优化场景数据osgUtil::Optimizer optimizer;optimizer.optimize(root.get());osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer();//方便查看在多边形之间切换,以查看三角网viewer->addEventHandler(new osgGA::StateSetManipulator(viewer->getCamera()->getOrCreateStateSet()));viewer->addEventHandler(new osgViewer::StatsHandler());viewer->addEventHandler(new osgViewer::WindowSizeHandler());viewer->setSceneData(root.get());viewer->setUpViewInWindow(600, 600, 1000, 800);return viewer->run();
}

相关文章:

OSG编程指南<十三>:OSG渲染状态

1、前言 在 OSG 中存在两棵树&#xff0c;即场景树和渲染树。渲染树是一棵以 StateSet 和 RenderLeaf 为节点的树&#xff0c;它可以做到 StateSet 相同的 RenderLeaf 同时渲染而不用切换 OpenGL状态&#xff0c;并且做到尽量少但在多个不同 State 间切换。渲染树在 CullVisito…...

不同路径 II(力扣LeetCode)动态规划

不同路径 II 题目描述 一个机器人位于一个 m x n 网格的左上角 &#xff08;起始点在下图中标记为 “Start” &#xff09;。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角&#xff08;在下图中标记为 “Finish”&#xff09;。 现在考虑网格中有障碍物。…...

探索深度学习:从理论到实践的全面指南

探索深度学习&#xff1a;从理论到实践的全面指南 摘要&#xff1a; 本文旨在提供一个关于深度学习的全面指南&#xff0c;带领读者从理论基础到实践应用全方位了解这一技术。我们将介绍深度学习的历史、基本原理、常用算法和应用场景&#xff0c;并通过Python代码示例和Tens…...

统计二叉树中的伪回文路径 : 用位运用来加速??

题目描述 这是 LeetCode 上的 「1457. 二叉树中的伪回文路径」 &#xff0c;难度为 「中等」。 Tag : 「DFS」、「位运算」 给你一棵二叉树&#xff0c;每个节点的值为 1 到 9 。 我们称二叉树中的一条路径是 「伪回文」的&#xff0c;当它满足&#xff1a;路径经过的所有节点值…...

【数据结构】树与二叉树(廿四):树搜索指定数据域的结点(算法FindTarget)

文章目录 5.3.1 树的存储结构5. 左儿子右兄弟链接结构 5.3.2 获取结点的算法1. 获取大儿子、大兄弟结点2. 搜索给定结点的父亲3. 搜索指定数据域的结点a. 算法FindTargetb. 算法解析c. 代码实现a. 使用指向指针的指针b. 直接返回找到的节点 4. 代码整合 5.3.1 树的存储结构 5.…...

vue3怎么提升效率的?为什么vue3比vue2快?效率提升主要在哪些方面?

官方文档中说vue3在 客户端渲染效率比vue2提升了1.3~2倍&#xff0c; SSR渲染效率比vue2提升了2~3倍&#xff0c;那么究竟是怎么提升的呢&#xff1f; 一、静态提升 在 vue3项目中的package.json文件中&#xff0c;可以看到这个 vue/compiler-sfc&#xff0c;它是用来解析(.v…...

C语言文件操作 | 文件分类、文件打开与关闭、文件的读写、文件状态、文件删除与重命名、文件缓冲区

欢迎关注博主 Mindtechnist 或加入【Linux C/C/Python社区】一起学习和分享Linux、C、C、Python、Matlab&#xff0c;机器人运动控制、多机器人协作&#xff0c;智能优化算法&#xff0c;滤波估计、多传感器信息融合&#xff0c;机器学习&#xff0c;人工智能等相关领域的知识和…...

从零开始的c语言日记day37——数组指针练习

一、 取地址数组储存在了*p里&#xff0c;里面储存的是整个数组的地址但本质也是第一个元素的地址解引用后1为4个字节所以就可以打印数组了。但一般不用这种方法 这样更方便一些 打印多维数组 如果不用这样传参&#xff0c;用指针传参怎么做呢&#xff1f; Main里函数的arr表示…...

codeforces 1851F

题目链接 题目大意&#xff1a;给你一个长度为n的数组a, 和一个整数k(2<n<2e5, k<30, a[i]<pow(2,k))。 任选一个x&#xff0c;求(a[i] ^ x) & (a[j] ^ x) 的最大值(1<i,j<n, i!j, x<pow(2,k))。 由于中间有个&&#xff0c;所以我们要求两个数最高…...

js把格式为YYYY-MM-DD HH:mm:ss的时间转换为UTC时间ISO 8601格式

// 要转换的日期字符串 const inputDate 2023-11-25 14:54:01; // 将日期字符串转换为Date对象 const dateObj new Date(inputDate); // 获取时间戳&#xff08;毫秒&#xff09; const timestamp dateObj.getTime(); // 转换格式 const outputDate new Date(tim…...

使用 Java 来读取 Excel 文件,检查每一行中的 URL,并将不符合条件的行标记为红色

-- 日、时、分、秒&#xff0c;这是计时的单位&#xff0c;惜时就应该惜日、惜时、惜分、惜秒。 用 Java 来读取 Excel 文件&#xff0c;检查每一行中的 URL&#xff0c;并将不符合条件的行标记为红色。以下是一个简单的示例&#xff0c;使用 Apache POI 进行 Excel 操作&#…...

雷达公式实现(matlab)

雷达公式实现 代码来源&#xff1a;《雷达系统分析与设计(MATLAB版)(第三版)》 function [snr] radar_eq(pt,freq,g,sigma,b,nf,loss,range) % This program implements Eq.(1.63) %% Inputs:% pt——峰值功率&#xff0c;W% freq——雷达中心频率&#xff0c;Hz% g——天线…...

CMake构建一个转换为3d tile的开源代码成功

之前CMake构建一个转换为3d tile的开源代码&#xff0c;生成解决方案之后&#xff0c;从VS2019打开&#xff1b; 总是报一个错误&#xff0c;跟 mocs_compilation_Debug.cpp 这个QT相关文件有关&#xff0c;它生成的obj&#xff0c;总是报模块计算机x64和目标计算机x86冲突&am…...

Java线程通信

线程通信 案例 package com.itheima.d4;public class ThreadTest {public static void main(String[] args) {Desk desk new Desk();//创建3个生产者线程new Thread(() -> {while (true) {desk.put();}}, "厨师1").start();new Thread(() -> {while (true) {…...

计算4人队形的最可能分布

2 2 2 1 2 2 2 2 2 1 2 2 2 2 2 1 2 2 3 3 3 x 3 3 2 2 2 1 2 2 2 2 2 1 2 2 在6*6的平面上2个点随机分布&#xff0c;有3种分布方式&#xff0c;2a1&#xff0c;2a2&#xff0c;2a3&#xff0c;占比为1&#xff1a;5&#xff1a;1. 3 3 …...

如何解决 Java 中的 IllegalArgumentException 异常?

非法参数异常&#xff08;IllegalArgumentException&#xff09;的抛出是为了表明一个方法被传递了一个非法参数。该异常扩展了 RuntimeException 类&#xff0c;因此属于在 Java 虚拟机&#xff08;JVM&#xff09;运行期间可能抛出的异常。它是一种未检查异常&#xff0c;因此…...

Vue 双向数据绑定

之前通过v-bind来完成的数据绑定&#xff0c;属性值和表达式进行绑定&#xff0c;表达式的值发生变化了属性值也跟着发生变化。 单向数据绑定&#xff1a; <!DOCTYPE html> <html> <head><meta charset"UTF-8"><title>首页</titl…...

电脑开机过程中,程序的启动的顺序是怎么样的?

电脑的启动过程涉及多个步骤,程序按照特定的顺序启动。这个过程通常如下: 电源开启: 当你按下电源按钮时,电源供应器(PSU)开始向电脑的各个组件供电。 自检加电(POST): 这是电脑启动过程的第一步。在这个阶段,基本输入输出系统(BIOS)或统一可扩展固件接口(UEFI)执行…...

JSON详细教程

&#x1f60a;JSON详细教程 &#x1f6a9;JSON简介☃️JSON语法规则&#x1f50a;JSON和JavaScript对象的区别 ☃️JSON数据类型字符串&#x1f50a;数字&#x1f50a;布尔值&#x1f50a;数组&#x1f50a;对象&#x1f50a;Null ☃️JSON对象&#x1f50a;访问JSON对象的值&a…...

DSP介绍及CCS

文章目录 CCS版本编译器CCS使用注意严禁中文 CCS的基本操作新建工程导入现有工程调整字体的大小工程界面恢复标签的使用 仿真盒小虫子进入在线Debug 仿真器芯片TMS320F28355基本介绍特性 DSP中特殊指令dsp指令中的EALLOW EDIS CCS TI官网 版本 CCS版本&#xff1a; CCS8.3.1…...

Python|GIF 解析与构建(5):手搓截屏和帧率控制

目录 Python&#xff5c;GIF 解析与构建&#xff08;5&#xff09;&#xff1a;手搓截屏和帧率控制 一、引言 二、技术实现&#xff1a;手搓截屏模块 2.1 核心原理 2.2 代码解析&#xff1a;ScreenshotData类 2.2.1 截图函数&#xff1a;capture_screen 三、技术实现&…...

变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析

一、变量声明设计&#xff1a;let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性&#xff0c;这种设计体现了语言的核心哲学。以下是深度解析&#xff1a; 1.1 设计理念剖析 安全优先原则&#xff1a;默认不可变强制开发者明确声明意图 let x 5; …...

conda相比python好处

Conda 作为 Python 的环境和包管理工具&#xff0c;相比原生 Python 生态&#xff08;如 pip 虚拟环境&#xff09;有许多独特优势&#xff0c;尤其在多项目管理、依赖处理和跨平台兼容性等方面表现更优。以下是 Conda 的核心好处&#xff1a; 一、一站式环境管理&#xff1a…...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院挂号小程序

一、开发准备 ​​环境搭建​​&#xff1a; 安装DevEco Studio 3.0或更高版本配置HarmonyOS SDK申请开发者账号 ​​项目创建​​&#xff1a; File > New > Create Project > Application (选择"Empty Ability") 二、核心功能实现 1. 医院科室展示 /…...

【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例

文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...

【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表

1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...

vue3 定时器-定义全局方法 vue+ts

1.创建ts文件 路径&#xff1a;src/utils/timer.ts 完整代码&#xff1a; import { onUnmounted } from vuetype TimerCallback (...args: any[]) > voidexport function useGlobalTimer() {const timers: Map<number, NodeJS.Timeout> new Map()// 创建定时器con…...

代码随想录刷题day30

1、零钱兑换II 给你一个整数数组 coins 表示不同面额的硬币&#xff0c;另给一个整数 amount 表示总金额。 请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额&#xff0c;返回 0 。 假设每一种面额的硬币有无限个。 题目数据保证结果符合 32 位带…...

招商蛇口 | 执笔CID,启幕低密生活新境

作为中国城市生长的力量&#xff0c;招商蛇口以“美好生活承载者”为使命&#xff0c;深耕全球111座城市&#xff0c;以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子&#xff0c;招商蛇口始终与城市发展同频共振&#xff0c;以建筑诠释对土地与生活的…...

无人机侦测与反制技术的进展与应用

国家电网无人机侦测与反制技术的进展与应用 引言 随着无人机&#xff08;无人驾驶飞行器&#xff0c;UAV&#xff09;技术的快速发展&#xff0c;其在商业、娱乐和军事领域的广泛应用带来了新的安全挑战。特别是对于关键基础设施如电力系统&#xff0c;无人机的“黑飞”&…...