osg之黑夜背景地月系显示

news2024/11/24 4:02:39

目录

效果

 代码


效果

 代码


/**
* Lights test. This application is for testing the LightSource support in osgEarth.
* 灯光测试。此应用程序用于测试osgEarth中的光源支持。
*/
#include "stdafx.h"
#include <osgViewer/Viewer>
#include <osgEarth/Notify>
#include <osgEarth/Lighting>
#include <osgEarth/PhongLightingEffect>
#include <osgEarth/NodeUtils>
#include <osgEarthUtil/EarthManipulator>
#include <osgEarthUtil/ExampleResources>
#include <osgEarthUtil/Ephemeris>
#include <osgEarthUtil/Shadowing>

#define LC "[lights] "

using namespace osgEarth;
using namespace osgEarth::Util;

int
usage(const char* name)
{
	OE_NOTICE
		<< "\nUsage: " << name << " file.earth" << std::endl
		<< MapNodeHelper().usage() << std::endl;

	return 0;
}

// converts a double-precision Vec3d to an equivalent single-precision Vec4f position
// as needed for light positions.
// Vec3d转换为Vec4f ,根据光源位置的需要
osg::Vec4
worldToVec4(const osg::Vec3d& ecef)
{
	osg::Vec4 result(0.0f, 0.0f, 0.0f, 1.0f);
	osg::Vec3d d = ecef;
	while (d.length() > 1e6)// 避免光源位置太远??
	{
		d *= 0.1;
		result.w() *= 0.1;
	}
	return osg::Vec4(d.x(), d.y(), d.z(), result.w());
}

// 生成随机颜色
osg::Vec4
randomColor()
{
	float r = (float)rand() / (float)RAND_MAX;
	float g = (float)rand() / (float)RAND_MAX;
	float b = (float)rand() / (float)RAND_MAX;
	return osg::Vec4(r, g, b, 1.0f);
}

// 添加光源
osg::Group*
addLights(osg::View* view, osg::Node* root, int lightNum)
{
	// 获取地理坐标系
	MapNode* mapNode = MapNode::get(root);
	const SpatialReference* mapsrs = mapNode->getMapSRS();
	const SpatialReference* geosrs = mapsrs->getGeographicSRS();

	osg::Vec3d world;
	osg::Group* lights = new osg::Group();

	// Add a directional light that simulates the sun - but skip this if a sky
	// was already added in the earth file.
	// 添加模拟太阳的平行光
	// 但如果地球文件中已经添加了天空,则跳过此操作。
	if (lightNum == 0)
	{
		// Ephemeris 星历表类,给出了自然发生的天体天体的位置;
		// 其中包括太阳和月亮。
		// 还包括一些相关的实用程序功能。
		Ephemeris e;
		DateTime dt(2016, 8, 10, 14.0);// 设置UTC时间
		CelestialBody sun = e.getSunPosition(dt); // 设置天体相对于地球的位置。
		world = sun.geocentric;// 太阳的地理位置

		// 定义太阳光
		osg::Light* sunLight = new osg::Light(lightNum++);
		world.normalize();// 归一化
		sunLight->setPosition(osg::Vec4d(world, 0.0));

		sunLight->setAmbient(osg::Vec4(0.2, 0.2, 0.2, 1.0));// 环境光照
		sunLight->setDiffuse(osg::Vec4(1.0, 1.0, 0.9, 1.0));// 漫反射光照

		// osg::LightSource 用于定义场景中的灯光的叶节点。
		osg::LightSource* sunLS = new osg::LightSource();
		sunLS->setLight(sunLight);

		lights->addChild(sunLS);

		// 为root节点 投射阴影
		ShadowCaster* caster = osgEarth::findTopMostNodeOfType<ShadowCaster>(root);
		if (caster)
		{
			OE_INFO << "Found a shadow caster!\n";
			caster->setLight(sunLight);
		}
		std::cout << "because no skyNode,so create sunLS" << std::endl;
	}

#if 1	// 这里主要是为测试加载其他光源
	// A red spot light. A spot light has a real position in space 
	// and points in a specific direciton. The Cutoff and Exponent
	// properties control the cone angle and sharpness, respectively
	// 一束红光。拥有真实的位置和光方向。
	// “Cutoff”和“Exponent”属性分别控制圆锥体角度和锐度
	{
		// 定义光照射 地点
		GeoPoint p(geosrs, -121, 34, 5000000., ALTMODE_ABSOLUTE);
		p.toWorld(world);

		// 定义光
		osg::Light* spot = new osg::Light(lightNum++);
		spot->setPosition(worldToVec4(world));
		spot->setAmbient(osg::Vec4(0, 0.2, 0, 1));
		spot->setDiffuse(osg::Vec4(1, 0, 0, 1));
		spot->setSpotCutoff(20.0f);
		spot->setSpotExponent(100.0f);

		// point straight down at the map:直接指向地图
		world.normalize();
		spot->setDirection(-world);

		// 光源叶子节点
		osg::LightSource* spotLS = new osg::LightSource();
		spotLS->setLight(spot);

		lights->addChild(spotLS);
	}

	// A green point light. A Point light lives at a real location in 
	// space and lights equally in all directions.
	// 绿灯。点光源位于空间中的真实位置,并在所有方向上均匀发光。
	{
		// 定义光照射 地点
		GeoPoint p(geosrs, -45, -35, 1000000., ALTMODE_ABSOLUTE);
		p.toWorld(world);

		// 定义光
		osg::Light* point = new osg::Light(lightNum++);
		point->setPosition(worldToVec4(world));
		point->setAmbient(osg::Vec4(0, 0, 0, 1));
		point->setDiffuse(osg::Vec4(1.0, 1.0, 0.0, 1));

		// 光源叶子节点
		osg::LightSource* pointLS = new osg::LightSource();
		pointLS->setLight(point);

		lights->addChild(pointLS);
	}
#endif

	// Generate the necessary uniforms for the shaders.
	// 为着色器生成必要的uniforms。
	// GenerateGL3LightingUniforms类的作用:遍历图形,查找灯光和材质,
	//		并为它们生成静态 Uniforms 或动态剔除回调,
	//		以便它们可以使用核心配置文件着色器。
	GenerateGL3LightingUniforms gen;
	lights->accept(gen);

	return lights;
}



int
main(int argc, char** argv)
{
	osg::ArgumentParser arguments(&argc, argv);

	// help?
	if (arguments.read("--help"))
		return usage(argv[0]);

	// create a viewer:
	osgViewer::Viewer viewer(arguments);

	// Whether to test updating material
	// 是否测试更新材质
	bool update = arguments.read("--update");

	// Tell the database pager to not modify the unref settings
	viewer.getDatabasePager()->setUnrefImageDataAfterApplyPolicy(true, false);

	// install our default manipulator (do this before calling load)
	viewer.setCameraManipulator(new EarthManipulator(arguments));

	// disable the small-feature culling
	viewer.getCamera()->setSmallFeatureCullingPixelSize(-1.0f);

	// 在添加光源之前,需要关闭viewer本身的光
	viewer.setLightingMode(viewer.NO_LIGHT);

	// load an earth file, and support all or our example command-line options
	osg::ref_ptr<osg::Node> node = MapNodeHelper().load(arguments, &viewer);
	if (node.valid())
	{
		MapNode* mapNode = MapNode::get(node.get());
		if (!mapNode)
			return -1;

		// Example of a custom material for the terrain.
		// 地形自定义材质示例。
		osg::ref_ptr< osg::Material > material = 0;
		if (update)// 开启update属性后,会创建material,进而调用回调方法,随机更改影像颜色
		{
			OE_NOTICE << "Custom material" << std::endl;
			material = new osg::Material;// 材质决定材质颜色
			material->setDiffuse(osg::Material::FRONT, osg::Vec4(1, 1, 1, 1));//漫反射光照    
			material->setAmbient(osg::Material::FRONT, osg::Vec4(1, 1, 1, 1));// 环境光照
			// Attach our StateAttributeCallback so that uniforms are updated.绑定材质回调
			material->setUpdateCallback(new MaterialCallback());
			mapNode->getOrCreateStateSet()->setAttributeAndModes(material);
		}

		// Does a Sky already exist (loaded from the earth file)?
		SkyNode* sky = osgEarth::findTopMostNodeOfType<SkyNode>(node.get());
		if (!sky)// 如果没有深空节点
		{
			std::cout << "no skyNode " << std::endl;
			// Add phong lighting.添加标签照明???
			PhongLightingEffect* phong = new PhongLightingEffect();
			phong->attach(node->getOrCreateStateSet());
		}

		// 添加光源. 当没有sky时,才会采用addLights中,创建光源的方式添加。
		osg::Group* lights = addLights(&viewer, node.get(), sky ? 1 : 0);

		mapNode->addChild(lights);

		viewer.setSceneData(node.get());
		while (!viewer.done())
		{
			if (viewer.getFrameStamp()->getFrameNumber() % 100 == 0)
			{
				// 每100帧,随机生成一个颜色
				if (material)
				{
					material->setDiffuse(osg::Material::FRONT, randomColor());
				}
			}
			viewer.frame();
		}
		return 0;
	}
	else
	{
		return usage(argv[0]);
	}
}

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

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

相关文章

基于pytorch使用特征图输出进行特征图可视化

使用特征图输出进行特征图可视化 文章目录 前言效果展示获取某一层特征图输出原图方法一&#xff1a;使用IntermediateLayerGetter类方法二&#xff1a;使用hook机制&#xff08;推荐&#xff09; 总结 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 例…

Redis系列之实现分布式自增主键

软件环境 JDK 1.8 SpringBoot 2.2.1 Maven 3.2 Mysql 8.0.26 redis 6.2.14 Mybatis Plus 3.4.3.4 开发工具 IntelliJ IDEA smartGit 一、实现原理 使用Redis来实现分布式的主键自增主要是依赖于Redis的INCR命令&#xff0c;调用INCR命令的对应key&#xff0c;其数值…

nginx图片资源管理转发

目标: 服务器上面 /home/images 里面作为文件资源管理器 代码: server {listen 80;server_name hello.world.cn;#apple-app和接口的关联文件location ~.*(images/miniapp)*\.(gif|jpg|jpeg|png)$ {root /home/;try_files $uri $uri/ 404;add_header Cache-Control &q…

垂直领域大模型落地思考

相比能做很多事&#xff0c;但每件事都马马虎虎的通用大模型&#xff1b;只能做一两件事&#xff0c;但这一两件事都能做好&#xff0c;可被信赖的垂直大模型会更有价值。这样的垂直大模型能帮助我们真正解决问题&#xff0c;提高生产效率。 本文将系统介绍如何做一个垂直领域…

某银行软件测试笔试题,满分一百你能得多少分?

&#xff08;时间90分钟&#xff0c;满分100分&#xff09; 考试要求&#xff1a;计算机相关专业试题 一、填空题&#xff08;每空1分&#xff0c;共10分&#xff09; 1. ______验证___是保证软件正确实现特定功能的一系列活动和过程。 2. 按开发阶段分&#xff0c;软件测试可…

暖通空调系统使用Modbus转Profinet网关应用配置案例

PLC通过兴达易控Modbus转Profinet网关&#xff08;XD-MDPN100)控制暖通空调的温度、湿度。作为控PLC可以通过Modbus传输到Profinet网关&#xff0c;与空调系统的压缩机进行通信&#xff0c;从而准确控制单元的加热、加湿、冷却和减湿。PLC可以实时监控和调整空调系统的运行状态…

java版本转换小工具

工作之余写了一个转换小工具&#xff0c;具有以下功能&#xff1a; 时间戳转换Base64编码/解码URL编码/解码JSON格式化 时间戳转换 package org.binbin.container.panel;import javax.swing.*; import java.awt.*; import java.text.DateFormat; import java.text.SimpleDat…

C语言 预处理详解

目录 1.预定义符号 2.#define 2.1#define 定义标识符 2.2#define 定义宏 2.3#define 替换规则 2.4#和## 2.4.1# 的作用 2.4.2## 的作用 2.5 带有副作用的宏参数 2.6宏和函数的对比 对比 **2.7内联函数 2.8命名约定 3.#undef **4.命令行定义 5.条件编译 常…

李开复创业公司零一万物开源迄今为止最长上下文大模型:Yi-6B和Yi-34B,支持200K超长上下文

本文来自DataLearnerAI官方网站&#xff1a;李开复创业公司零一万物开源迄今为止最长上下文大模型&#xff1a;Yi-6B和Yi-34B&#xff0c;支持200K超长上下文 | 数据学习者官方网站(Datalearner)https://www.datalearner.com/blog/1051699285770532 零一万物&#xff08;01.AI…

C语言 每日一题 11.9 day15

数组元素循环右移问题 一个数组A中存有N&#xff08; > 0&#xff09;个整数&#xff0c;在不允许使用另外数组的前提下&#xff0c;将每个整数循环向右移M&#xff08;≥0&#xff09;个位置&#xff0c;即将A中的数据由&#xff08;A0​A1⋯AN−1&#xff09;变换为&…

爱剪辑如何将视频旋转90度,详细操作流程

爱剪辑是一款电脑端常用的视频剪辑类软件&#xff0c;基本上囊括了视频剪辑所需的所有功能&#xff0c;此处主要介绍&#xff0c;爱剪辑是如何对视频进行旋转操作的&#xff0c;水平旋转或者垂直旋转爱剪辑都是可以操作的&#xff0c;整体操作的详细过程将在下方为大家讲解。 …

Linux进程控制(2)

Linux进程控制(2) &#x1f4df;作者主页&#xff1a;慢热的陕西人 &#x1f334;专栏链接&#xff1a;Linux &#x1f4e3;欢迎各位大佬&#x1f44d;点赞&#x1f525;关注&#x1f693;收藏&#xff0c;&#x1f349;留言 本博客主要内容讲解了进程等待收尾内容和进程的程序…

【Codeforces】Codeforces Round 905 (Div. 3)

Problem - 1883C - Codeforces 这题当时想复杂了。 题目大意&#xff1a; 给一串数组和一个数字k&#xff0c;求对数组进行多少次操作能是他们的乘积是k的倍数。 操作是选定一个数加上1。 这题需要抓住一个点k属于[2,5]&#xff0c;2&#xff0c;3&#xff0c;4&#xff0c;5中…

python连接mysql进行查询

pymysql连接工具类 import pymysql 数据库连接工具类 class MySQLConnection:def __init__(self, host, port, user, password, database):self.host hostself.port portself.user userself.password passwordself.database databaseself.conn Noneself.cursor None# …

Umdh进行内存泄露分析软件的下载、安装与使用

1 下载与安装 1.1 软件介绍 Umdh一款轻量级的内存泄露分析工具UMDH&#xff08;User-Mode Dump Heap&#xff09;&#xff0c;是 Debugging Tools for Windows 里面的一个工具&#xff0c;主要通过分析比较进程的Heap Stack trace信息来发现内存泄露。 Umdh内存泄露分析适用…

Spring Boot 请求/actuator/beans 无法访问 返回404

问题复现 在保证项目加入了spring-boot-starter-actuator依赖&#xff0c;并成功启动后。通过浏览器进行访问&#xff0c;返回如下图结果&#xff1a; 问题排查 1. 查看日志 从日志中可以看到基于路径’/actuator’下只暴露了一个端点 2. 访问http://localhost:8080/actua…

【309. 买卖股票的最佳时机含冷冻期】

目录 一、题目解析 二、算法原理 三、代码实现 class Solution { public:int maxProfit(vector<int>& prices) {int nprices.size();vector<vector<int>> dp(n,vector<int>(3));dp[0][0]-prices[0];dp[0][1]0;dp[0][2]0;for(int i1;i<n;i){dp…

HTML的表单标签和无语义标签的讲解

HTML的表单标签 表单是让用户输入信息的重要途径, 分成两个部分: 表单域: 包含表单元素的区域. 重点是 form 标签. 表单控件: 输入框, 提交按钮等. 重点是 input 标签 form 标签 使用form进行前后端交互.把页面上,用户进行的操作/输入提交到服务器上 input 标签 有很多形态,能…

12V升压36V芯片,2A输出方案

12V升压36V芯片是一款专为EPC/笔记本车载适配器升压、升降压转换以及手持设备供电等应用领域设计的芯片。它具有12V升压至36V的功能&#xff0c;输出电流可达2A&#xff0c;采用外置MOS管&#xff0c;5V-35V的宽输入电压范围&#xff0c;参数特点包括高效率、宽输入电压范围、内…

基于GCC的工具objdump实现反汇编

一&#xff1a;objdump介绍 在 Linux中&#xff0c;一切皆文件。 Linux 编程实际上是编写处理各种文件的代码。系统由许多类型的文件组成&#xff0c;但目标文件具有一种特殊的设计&#xff0c;提供了灵活和多样的用途。 目标文件是包含带有附加地址和值的助记符号的路线图。这…