用OpenSceneGraph实现的NeHe OpenGL教程 - 第十一课

Orbbec-Gemini-335 深度相机 Python SDK 编译与配置全记录(Windows 环境) 本篇博客将围绕 Windows 系统下 Orbbec SDK 的 Python 配置与编译过程进行详细说明,主要使用的是官方提供的 pyorbbecsdk Python wrapper 项目以及 Orbbec SDK V2 Python Wrapper 配置指南,并记录了安装与配置过程中遇到的若干问题及解决办法。 阅读详情
  • 简介

这节课我们将创建一个以正弦波方式飘动的旗帜。本课所用到的知识在前面的课程中都有讲解,并没有什么新的内容


  • 实现

首先创建我们的场景,关于旗帜的顶点坐标在NeHe教程中已经有非常详细的介绍,本文就不在赘述了。

	float points[45][45][3];
	for(int x=0; x<45; x++)
	{
		for(int y=0; y<45; y++)
		{
			points[x][y][0]=float((x/5.0f)-4.5f);
			points[x][y][1]=float((y/5.0f)-4.5f);
			points[x][y][2]=float(sin((((x/5.0f)*40.0f)/360.0f)*3.141592654*2.0f));
		}
	}

	osg::Group *root = new osg::Group;

	osg::MatrixTransform *zoomMT = new osg::MatrixTransform;
	zoomMT->setMatrix(osg::Matrix::translate(0.0, 0.0, -12.0));

	osg::MatrixTransform *xRotMT = new osg::MatrixTransform;
	xRotMT->setUpdateCallback(new XRotCallback);
	osg::MatrixTransform *yRotMT = new osg::MatrixTransform;
	yRotMT->setUpdateCallback(new YRotCallback);
	osg::MatrixTransform *zRotMT = new osg::MatrixTransform;
	zRotMT->setUpdateCallback(new ZRotCallback);

	osg::Geometry *flagGeometry = new osg::Geometry;
	flagGeometry->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);

	osg::PolygonMode *polygonMode = new osg::PolygonMode(osg::PolygonMode::FRONT, osg::PolygonMode::LINE);
	flagGeometry->getOrCreateStateSet()->setAttribute(polygonMode);

	osg::Vec3Array *flagVertexArray = new osg::Vec3Array;
	osg::Vec2Array *textureArray = new osg::Vec2Array;

	for(int x = 0; x < 44; x++ )
	{
		for(int y = 0; y < 44; y++ )
		{
			double float_x, float_y, float_xb, float_yb;

			float_x = float(x)/44.0f;
			float_y = float(y)/44.0f;
			float_xb = float(x+1)/44.0f;
			float_yb = float(y+1)/44.0f;

			textureArray->push_back(osg::Vec2( float_x, float_y));
			textureArray->push_back(osg::Vec2( float_x, float_yb ));
			textureArray->push_back(osg::Vec2( float_xb, float_yb ));
			textureArray->push_back(osg::Vec2( float_xb, float_y ));

			flagVertexArray->push_back(osg::Vec3( points[x][y][0], points[x][y][1], points[x][y][2]));
			flagVertexArray->push_back(osg::Vec3( points[x][y+1][0], points[x][y+1][1], points[x][y+1][2]));
			flagVertexArray->push_back(osg::Vec3( points[x+1][y+1][0], points[x+1][y+1][1], points[x+1][y+1][2]));
			flagVertexArray->push_back(osg::Vec3( points[x+1][y][0], points[x+1][y][1], points[x+1][y][2]));

		}
	}

	osg::Image *textureImage = osgDB::readImageFile("Data/Tim.bmp");
	osg::Texture2D *texture2D = new osg::Texture2D;
	texture2D->setImage(textureImage);
	texture2D->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR);
	texture2D->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);

	flagGeometry->setTexCoordArray(0, textureArray);
	flagGeometry->getOrCreateStateSet()->setTextureAttributeAndModes(0, texture2D);
	flagGeometry->setVertexArray(flagVertexArray);
	flagGeometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, 7744));
	flagGeometry->setUpdateCallback(new GeometryCallback);
	flagGeometry->setUseDisplayList(false);
	flagGeometry->setUseVertexBufferObjects(true);

	osg::Geode *flagGeode = new osg::Geode;
	flagGeode->addDrawable(flagGeometry);

	root->addChild(zoomMT);
	zoomMT->addChild(xRotMT);
	xRotMT->addChild(yRotMT);
	yRotMT->addChild(zRotMT);
	zRotMT->addChild(flagGeode);

	return root;
为了实现OpenGL中glPolygonMode的效果(实现旗帜的一面用线框显示), 代码中使用了osg::PolygonMode来完成设置

为了实现动态的旋转效果,和前面课程一样定义了UpdateCallback

class XRotCallback : public osg::NodeCallback
{

public:

	XRotCallback() : _angle(0){}

	virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
	{

		if (dynamic_cast<osg::MatrixTransform*>(node))
		{
			osg::MatrixTransform *rot = dynamic_cast<osg::MatrixTransform*>(node);
			rot->setMatrix(osg::Matrix::rotate(_angle, osg::X_AXIS));

			_angle += osg::DegreesToRadians(0.3);
		}

		traverse(node, nv);
	}

	double _angle;
};

为了实现旗帜的飘动效果,与NeHe教程中类似,我们需要时刻去修改顶点数据,通过osg::Drawable的UpdateCallback可以做到,它与osg::Node的UpdateCallback类似,所不同的是需要重载的函数为update函数而不是Node中的operator()函数,在代码中我使用了NeHe的points数组来实现(之前直接修改vertexArray总是失败,希望读者可以给出直接修改vertexArray方式的代码)

class GeometryCallback : public osg::Drawable::UpdateCallback
{

public:
	virtual void update(osg::NodeVisitor* nv, osg::Drawable* drawable)
	{
		osg::Geometry *geometry = dynamic_cast<osg::Geometry*>(drawable);
		if (!geometry)
		{
			return;
		}

		osg::Vec3Array *vertexArray = dynamic_cast<osg::Vec3Array*>(geometry->getVertexArray());
		if (vertexArray)
		{
			float points[45][45][3];
			int i = 0;

			for(int x = 0; x < 44; x++ )
			{
				for(int y = 0; y < 44; y++ )
				{
					points[x][y][0] = vertexArray->at(i).x();
					points[x][y][1] = vertexArray->at(i).y();
					points[x][y][2] = vertexArray->at(i).z();

					++i;
					points[x][y+1][0] = vertexArray->at(i).x();
					points[x][y+1][1] = vertexArray->at(i).y();
					points[x][y+1][2] = vertexArray->at(i).z();

					++i;
					points[x+1][y+1][0] = vertexArray->at(i).x();
					points[x+1][y+1][1] = vertexArray->at(i).y();
					points[x+1][y+1][2] = vertexArray->at(i).z();

					++i;
					points[x+1][y][0] = vertexArray->at(i).x();
					points[x+1][y][1] = vertexArray->at(i).y();
					points[x+1][y][2] = vertexArray->at(i).z();

					++i;
				}
			}

			static int wiggle_count = 0;
			float hold;

			if( wiggle_count == 2 )
			{
				for(int y = 0; y < 45; y++ )
				{
					hold=points[0][y][2];
					for(int x = 0; x < 44; x++)
					{
						points[x][y][2] = points[x+1][y][2];
					}
					points[44][y][2]=hold;
				}
				wiggle_count = 0;
			}
			wiggle_count++;


			vertexArray->clear();
			for(int x = 0; x < 44; x++ )
			{
				for(int y = 0; y < 44; y++ )
				{
					vertexArray->push_back(osg::Vec3( points[x][y][0], points[x][y][1], points[x][y][2]));
					vertexArray->push_back(osg::Vec3( points[x][y+1][0], points[x][y+1][1], points[x][y+1][2]));
					vertexArray->push_back(osg::Vec3( points[x+1][y+1][0], points[x+1][y+1][1], points[x+1][y+1][2]));
					vertexArray->push_back(osg::Vec3( points[x+1][y][0], points[x+1][y][1], points[x+1][y][2]));
				}
			}
			vertexArray->dirty();
		}
	}
};
另外一个需要注意的地方:需要将flagGeomerty的加载方式修改为VBO的方式,不要使用DisplayList,代码中已经设置。

最后编译运行程序,一个飘动的旗帜出现了


附:本课源码(源码中可能存在错误和不足,仅供参考)

#include "../osgNeHe.h"

#include <QtCore/QTimer>
#include <QtGui/QApplication>
#include <QtGui/QVBoxLayout>

#include <osgViewer/Viewer>
#include <osgDB/ReadFile>
#include <osgQt/GraphicsWindowQt>

#include <osg/MatrixTransform>

#include <osgDB/ReadFile>
#include <osg/Texture2D>
#include <osg/PolygonMode>


//////////////////////////////////////////////////////////////////////////
//RotCallback

class XRotCallback : public osg::NodeCallback
{

public:

	XRotCallback() : _angle(0){}

	virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
	 {
		
		 if (dynamic_cast<osg::MatrixTransform*>(node))
		 {
			 osg::MatrixTransform *rot = dynamic_cast<osg::MatrixTransform*>(node);
			 rot->setMatrix(osg::Matrix::rotate(_angle, osg::X_AXIS));

			 _angle += osg::DegreesToRadians(0.3);
		 }
		 
		 traverse(node, nv);
	 }

	double _angle;
};


class YRotCallback : public osg::NodeCallback
{
public:

	YRotCallback() : _angle(0){}

	virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
	{

		if (dynamic_cast<osg::MatrixTransform*>(node))
		{
			osg::MatrixTransform *rot = dynamic_cast<osg::MatrixTransform*>(node);
			rot->setMatrix(osg::Matrix::rotate(_angle, osg::Y_AXIS));

			_angle += osg::DegreesToRadians(0.2);
		}


		traverse(node, nv);
	}

	double _angle;
};


class ZRotCallback : public osg::NodeCallback
{
public:

	ZRotCallback() : _angle(0){}

	virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
	{
		if (dynamic_cast<osg::MatrixTransform*>(node))
		{
			osg::MatrixTransform *rot = dynamic_cast<osg::MatrixTransform*>(node);
			rot->setMatrix(osg::Matrix::rotate(_angle, osg::Z_AXIS));

			_angle += osg::DegreesToRadians(0.4);
		}
		traverse(node, nv);
	}

	double _angle;
};

//End
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
//变换Geometry的顶点

class GeometryCallback : public osg::Drawable::UpdateCallback
{

public:
	virtual void update(osg::NodeVisitor* nv, osg::Drawable* drawable)
	{
		osg::Geometry *geometry = dynamic_cast<osg::Geometry*>(drawable);
		if (!geometry)
		{
			return;
		}

		osg::Vec3Array *vertexArray = dynamic_cast<osg::Vec3Array*>(geometry->getVertexArray());
		if (vertexArray)
		{
			float points[45][45][3];
			int i = 0;

			for(int x = 0; x < 44; x++ )
			{
				for(int y = 0; y < 44; y++ )
				{
					points[x][y][0] = vertexArray->at(i).x();
					points[x][y][1] = vertexArray->at(i).y();
					points[x][y][2] = vertexArray->at(i).z();
					
					++i;
					points[x][y+1][0] = vertexArray->at(i).x();
					points[x][y+1][1] = vertexArray->at(i).y();
					points[x][y+1][2] = vertexArray->at(i).z();
					
					++i;
					points[x+1][y+1][0] = vertexArray->at(i).x();
					points[x+1][y+1][1] = vertexArray->at(i).y();
					points[x+1][y+1][2] = vertexArray->at(i).z();

					++i;
					points[x+1][y][0] = vertexArray->at(i).x();
					points[x+1][y][1] = vertexArray->at(i).y();
					points[x+1][y][2] = vertexArray->at(i).z();

					++i;
				}
			}

			static int wiggle_count = 0;
			float hold;

			if( wiggle_count == 2 )
			{
				for(int y = 0; y < 45; y++ )
				{
					hold=points[0][y][2];
					for(int x = 0; x < 44; x++)
					{
						points[x][y][2] = points[x+1][y][2];
					}
					points[44][y][2]=hold;
				}
				wiggle_count = 0;
			}
			wiggle_count++;


			vertexArray->clear();
			for(int x = 0; x < 44; x++ )
			{
				for(int y = 0; y < 44; y++ )
				{
					vertexArray->push_back(osg::Vec3( points[x][y][0], points[x][y][1], points[x][y][2]));
					vertexArray->push_back(osg::Vec3( points[x][y+1][0], points[x][y+1][1], points[x][y+1][2]));
					vertexArray->push_back(osg::Vec3( points[x+1][y+1][0], points[x+1][y+1][1], points[x+1][y+1][2]));
					vertexArray->push_back(osg::Vec3( points[x+1][y][0], points[x+1][y][1], points[x+1][y][2]));
				}
			}
			vertexArray->dirty();
		}
	}
};

//////////////////////////////////////////////////////////////////////////



class ViewerWidget : public QWidget, public osgViewer::Viewer
{
public:
	ViewerWidget(osg::Node *scene = NULL)
	{
		QWidget* renderWidget = getRenderWidget( createGraphicsWindow(0,0,100,100), scene);

		QVBoxLayout* layout = new QVBoxLayout;
		layout->addWidget(renderWidget);
		layout->setContentsMargins(0, 0, 0, 1);
		setLayout( layout );

		connect( &_timer, SIGNAL(timeout()), this, SLOT(update()) );
		_timer.start( 10 );
	}

	QWidget* getRenderWidget( osgQt::GraphicsWindowQt* gw, osg::Node* scene )
	{
		osg::Camera* camera = this->getCamera();
		camera->setGraphicsContext( gw );

		const osg::GraphicsContext::Traits* traits = gw->getTraits();

		camera->setClearColor( osg::Vec4(0.0, 0.0, 0.0, 1.0) );
		camera->setViewport( new osg::Viewport(0, 0, traits->width, traits->height) );
		camera->setProjectionMatrixAsPerspective(45.0f, static_cast<double>(traits->width)/static_cast<double>(traits->height), 0.1f, 100.0f );
		camera->setViewMatrixAsLookAt(osg::Vec3d(0, 0, 1), osg::Vec3d(0, 0, 0), osg::Vec3d(0, 1, 0));

		this->setSceneData( scene );

		return gw->getGLWidget();
	}

	osgQt::GraphicsWindowQt* createGraphicsWindow( int x, int y, int w, int h, const std::string& name="", bool windowDecoration=false )
	{
		osg::DisplaySettings* ds = osg::DisplaySettings::instance().get();
		osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
		traits->windowName = name;
		traits->windowDecoration = windowDecoration;
		traits->x = x;
		traits->y = y;
		traits->width = w;
		traits->height = h;
		traits->doubleBuffer = true;
		traits->alpha = ds->getMinimumNumAlphaBits();
		traits->stencil = ds->getMinimumNumStencilBits();
		traits->sampleBuffers = ds->getMultiSamples();
		traits->samples = ds->getNumMultiSamples();

		return new osgQt::GraphicsWindowQt(traits.get());
	}

	virtual void paintEvent( QPaintEvent* event )
	{ 
		frame(); 
	}

protected:

	QTimer _timer;
};



osg::Node*	buildScene()
{

	float points[45][45][3];
	for(int x=0; x<45; x++)
	{
		for(int y=0; y<45; y++)
		{
			points[x][y][0]=float((x/5.0f)-4.5f);
			points[x][y][1]=float((y/5.0f)-4.5f);
			points[x][y][2]=float(sin((((x/5.0f)*40.0f)/360.0f)*3.141592654*2.0f));
		}
	}

	osg::Group *root = new osg::Group;

	osg::MatrixTransform *zoomMT = new osg::MatrixTransform;
	zoomMT->setMatrix(osg::Matrix::translate(0.0, 0.0, -12.0));

	osg::MatrixTransform *xRotMT = new osg::MatrixTransform;
	xRotMT->setUpdateCallback(new XRotCallback);
	osg::MatrixTransform *yRotMT = new osg::MatrixTransform;
	yRotMT->setUpdateCallback(new YRotCallback);
	osg::MatrixTransform *zRotMT = new osg::MatrixTransform;
	zRotMT->setUpdateCallback(new ZRotCallback);

	osg::Geometry *flagGeometry = new osg::Geometry;
	flagGeometry->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);

	osg::PolygonMode *polygonMode = new osg::PolygonMode(osg::PolygonMode::FRONT, osg::PolygonMode::LINE);
	flagGeometry->getOrCreateStateSet()->setAttribute(polygonMode);

	osg::Vec3Array *flagVertexArray = new osg::Vec3Array;
	osg::Vec2Array *textureArray = new osg::Vec2Array;

	for(int x = 0; x < 44; x++ )
	{
		for(int y = 0; y < 44; y++ )
		{
			double float_x, float_y, float_xb, float_yb;

			float_x = float(x)/44.0f;
			float_y = float(y)/44.0f;
			float_xb = float(x+1)/44.0f;
			float_yb = float(y+1)/44.0f;
			
			textureArray->push_back(osg::Vec2( float_x, float_y));
			textureArray->push_back(osg::Vec2( float_x, float_yb ));
			textureArray->push_back(osg::Vec2( float_xb, float_yb ));
			textureArray->push_back(osg::Vec2( float_xb, float_y ));

			flagVertexArray->push_back(osg::Vec3( points[x][y][0], points[x][y][1], points[x][y][2]));
			flagVertexArray->push_back(osg::Vec3( points[x][y+1][0], points[x][y+1][1], points[x][y+1][2]));
			flagVertexArray->push_back(osg::Vec3( points[x+1][y+1][0], points[x+1][y+1][1], points[x+1][y+1][2]));
			flagVertexArray->push_back(osg::Vec3( points[x+1][y][0], points[x+1][y][1], points[x+1][y][2]));

		}
	}

	osg::Image *textureImage = osgDB::readImageFile("Data/Tim.bmp");
	osg::Texture2D *texture2D = new osg::Texture2D;
	texture2D->setImage(textureImage);
	texture2D->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR);
	texture2D->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);

	flagGeometry->setTexCoordArray(0, textureArray);
	flagGeometry->getOrCreateStateSet()->setTextureAttributeAndModes(0, texture2D);
	flagGeometry->setVertexArray(flagVertexArray);
	flagGeometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, 7744));
	flagGeometry->setUpdateCallback(new GeometryCallback);
	flagGeometry->setUseDisplayList(false);
	flagGeometry->setUseVertexBufferObjects(true);

	osg::Geode *flagGeode = new osg::Geode;
	flagGeode->addDrawable(flagGeometry);

	root->addChild(zoomMT);
	zoomMT->addChild(xRotMT);
	xRotMT->addChild(yRotMT);
	yRotMT->addChild(zRotMT);
	zRotMT->addChild(flagGeode);

	return root;
}



int main( int argc, char** argv )
{
	QApplication app(argc, argv);
	ViewerWidget* viewWidget = new ViewerWidget(buildScene());
	viewWidget->setGeometry( 100, 100, 640, 480 );
	viewWidget->show();
	return app.exec();
}





《C#零基础入门之百识百例》(七)算数运算符 -- 圆的面积 运算符是一种告诉编译器执行特定的数学或逻辑操作的符号。C# 有丰富的内置运算符,本文带你学习C# 中算数运算符。 阅读详情

相关推荐

消费级显卡跑大模型:RTX 3060 12G 部署 70 亿参数 AI 编程助手的优化实战

本文详细介绍了如何在消费级显卡RTX 3060 12G上,通过量化、投机解码和分页KV-Cache等核心优化技术,成功部署并流畅运行70亿参数的CodeLlama-7B编程助手。文章提供了从环境配置、模型准备到参数调优的完整实战笔记,实测显存占用降至7.3GB,生成速度达21.7 token/秒,为开发者和技术爱好者提供了可行的本地AI部署方案。

weixin_29053067的博客 1261

osg::ref_ptr<osg::Image> image = osgDB::readImageFile(fileName); image指针为空

前言 使用《OpenSceneGraph Quick Start Guide》中文版及源码,里面的一个例子TextureMapping,在我本机上运行没有问题,但拷贝到公司电脑,发现总是运行异常,无法读取纹理图片, 调试到136行 image创建出来总是为空,纹理文件是有的, #include "osgDB/ReadFile" #include "osg/Geode" #include "osg/Geometry" #include "osg/StateSet" #include "osg/StateAt

aoxuestudy的专栏 1752

维护测试监控LLM应用

LangFuse: 开源 + SaaS(免费/付费),LangSmith 平替,可集成 LangChain 也可直接对接 OpenAI API;LangSmith: LangChain 的官方平台,SaaS 服务(免费/付费),非开源,企业版支持私有部署;调试 Prompt 的 Playground测试/验证系统的相关指标数据集管理各种指标监控与统计:访问量、响应时长、Token 费等等。

SunnyRivers 1782

OpenSceneGraph纹理API开发指南【OSG】

前面的教程中,我们用彩虹的所有颜色画了一个正方形。然而,还有另一种成为纹理映射的技术,将光栅二维图像应用于三维几何。在这种情况下,效果不是针对几何体的顶点,而是通过栅格化场景更改获得的所有像素的数据。这种技术可以显着增加最终图像的真实感和细节。OSG 支持多种纹理属性和纹理模式。但是,在讨论纹理之前,让我们先谈谈OSG如何在光栅图像上运行。为了处理光栅图像,OSG提供了一个特殊的类osg ::Image ,它在其自身中存储图像数据,最终用于对象的纹理处理。

新缸中之脑 1672

国内优秀MES开源框架

一套springboot 开源框架 代码标准规范化。 界面展示 演示地址 http://wangziyangmes.pzzd.xyz 用户名admin 密码123 系统管理 工艺管理 计划管理 物料管理 *用户管理* *工艺路线管理* 工单下达...

q707231019的博客 2万+

【SECS】初识SECS协议

项目标题的第一位和第二位告诉下面有多少字节表示项目的长度。而项目的长度是指项目标题后面的字节数,这里第一个字节就是项目标题。1个字节可以表示的最大长度是0-255,所以只要项目标题后面的字节数小于等于254,都是0x01。

weixin_48618536的博客 1644

osg osgDB::readImageFile 返回空指针 已解决

osg osgDB::readImageFile 返回空指针

PHP代码的博客 1055

在 ABAP Cloud 中玩转 CL_ABAP_PARALLEL 并行处理:从原理到实战

ABAP并行处理框架CL_ABAP_PARALLEL解析 本文系统介绍了SAP ABAP环境中实现并行处理的CL_ABAP_PARALLEL框架。该框架通过封装异步RFC和对话进程,为开发者提供了面向对象的API,显著提升大批量数据处理的效率。 文章首先分析了ABAP环境需要并行处理的原因:传统的串行处理在面对百万级数据时效率低下。然后详细介绍了CL_ABAP_PARALLEL的设计思路,它是一个"小型线程池"式的同步并行框架,适用于批量计算场景。此外,文章重点讲解了控制并行任务的关键参

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 341

OSG:中级篇 文件IO类

一.简介 #include <osgDB/ReadFile> #include <osgDB/WriteFile> 二.读取数据 osgDB::readCommandLine() osgDB::readFile() osgDB::readHeightFieldFile() osgDB::readImageFile...

weixin_30716141的博客 248

数据库课程案例——电力公司收费管理系统分析与实践,完整带SQL语句

某电力公司收费管理信息系统实现客户信息、用电类型(类别号、类别名、电价)及业务员管理;实现客户用电信息管理(客户号、月份、用电类别号、用电度数);实现客户费用管理(客户号、月份、费用、收费标志),收费标志的默认值为“未收”;实现收费登记(客户、月份、应收费用、实收费用、业务员),并自动修改收费标志(用触发器实现);创建触发器,实现收费时自动更加应收费用和实收费用,计算本次结余,然后修改客户信息表中的结余金额;创建存储过程统计指定月份应收费用和实收费用;创建存储过程查询指定月份未交费的用户信息,以便崔费;创建

qq_44242804的博客 2763

S32DS S32K312 LPSPI + DMA配置异步SPI

配置DMA->Specific Configuration->Dma Logic Channel->Configuration->Global。SpiPhyUnitMapping:将该配置Mapping到某一路Spi,此工程配置为Spi1,遂选择LPSPI_1。配置的该路SPI的片选ID,此处ID对应配置Pin脚时lpspi_pcs后的下表(本工程此处为PCS3)配置该路SPI对应的SPI硬件单元ID,本工程配置为Lpspi1,因此配置为CSIB1。首先配置SPI的Pin脚,此处使用的是LPSPI_1。

希望我的博客,能帮上你解决学习中工作中所遇到的问题 2364

OpenSceneGraph实现的NeHe OpenGL教程 - 第十一课

简介 这节课我们将创建一个以正弦波方式飘动的旗帜。本课所用到的知识在前面的课程中都有讲解,并没有什么新的内容 实现 首先创建我们的场景,关于旗帜的顶点坐标在NeHe教程中已经有非常详细的介绍,本文就不在赘述了。 [cpp] view plain copy   float points[45][45][3];

ALLENJIAO的专栏 717

Python爬虫实战:爬取携程旅游平台数据,我拆解了动态反爬+Cookie续命(附完整可运行代码)

反爬类型表现形式应对思路sign参数返回403/空数据逆向JS还原加密逻辑Cookie时效登录后1小时Cookie失效定时刷新Cookie/保存登录态行为检测爬取过快触发验证码模拟真人延时/随机点击IP封禁单IP爬取超50条数据被封付费代理池/降低请求频率爬取携程旅游平台数据的核心,不是“简单的HTTP请求”,而是“理解平台的反爬逻辑并合规适配”——从sign参数破解到Cookie维护,再到行为模拟,每一步都是对HTTP协议、前端加密、用户行为的深度理解。

专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 1715

用OpenSceneGraph实现的NeHe OpenGL教程 - 第一课

简介 OpenSceneGraph是一个开放源码,跨平台的图形开发包,它为诸如飞行器仿真,游戏,虚拟现实,科学计算可视化这样的高性能图形应用程序开发而设计。它基于场景图的概念,它提供一个在OpenGL之上的面向对象的框架,从而能把开发者从实现和优化底层图形的调用中解脱出来,并且它为图形应用程序的快速开发提供很多附加的实用工具。 NeHe教程是目前针对初学者来说最

Frank的专栏 1万+

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

用OpenSceneGraph实现的NeHe OpenGL教程 - 第二十四课

简介 NeHe教程在这节课中向我们介绍了如何读取显卡支持的OpenGL的扩展,如何使用Targa(TGA)图像文件作为纹理,以及如何利用OpenGL的剪裁区域来滚动屏幕文字。 在OpenInventor中没有相关的函数来获取OpenGL的扩展信息,我们只能通过直接调用OpenGL来获得这些信息。OpenInventor的纹理节点自动支持使用Targa(TGA)图像文件作为纹理,所以我们

Frank的专栏 2317

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

OpenSceneGraph实现的NeHe OpenGL教程 - 第二十四课

简介 NeHe教程在这节课中向我们介绍了如何读取显卡支持的OpenGL的扩展,如何使用Targa(TGA)图像文件作为纹理,以及如何利用OpenGL的剪裁区域来滚动屏幕文字。osg支持tga格式的文件读取,因此不需要像NeHe课程那样解析TGA格式,有兴趣的读者可以查看osgPlugins库中的ReaderWriterTGA.cpp文件了解osg是如何读取TGA图片格式的。

ALLENJIAO的专栏 1110

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

用OpenSceneGraph实现的NeHe OpenGL教程 - 第三十八课

简介 这节课NeHe教我们怎样把图片

Frank的专栏 2303

用OpenSceneGraph实现的NeHe OpenGL教程 - 第二十五课

简介 NeHe教程在这节课中向我们介绍了如何从文件加载3D模型,并且平滑的从一个模型变换为另一个模型。两个模型之间平滑过渡的算法其实是很简单的,首先我们要保证两个模型要有相同数目的顶点,然后我们分别计算每个点从一个模型移动到另外一个模型时,中间的位置数据。我们将这个过程显示出来就会产生模型平滑过渡的效果。

Frank的专栏 1747

用OpenSceneGraph实现的NeHe OpenGL教程 - 第十二课

简介 本课NeHe教程主要是使用了OpenGL中的显示列表。OpenGL的显示列表是加速OpenGL性能的一种重要的手段。OpenGl的几何体绘制方法主要包括立即模式、顶点数组、显示列表和VBO。在OSG中显示列表是大部分OSG程序所使用的默认绘制优化行为,因此不需要我们去像OpenGL那样进行设置。 实现 首先创建整个场景,本课中我使用了OSG中预定义的几种基本形体,(os

Frank的专栏 7883

OpenSceneGraph实现的NeHe OpenGL教程 - 第一课

目录(?)[-] 简介创建一个osg窗口 简介 OpenSceneGraph是一个开放源码,跨平台的图形开发包,它为诸如飞行器仿真,游戏,虚拟现实,科学计算可视化这样的高性能图形应用程序开发而设计。它基于场景图的概念,它提供一个在OpenGL之上的面向对象的框架,从而能把开发者从实现和优化底层图形的调用中解脱出来,并且它为图形应用程序的快速

ALLENJIAO的专栏 1201

OpenSceneGraph实现的NeHe OpenGL教程 - 第三十二课

简介 本节课NeHe课程主要想我们介绍了OpenGL中的拾取(Selection)的方式来和场景中的物体进行交换,在OSG中并没有封装OpenGL中的拾取方式,而是用了更高效的一种方式来实现与场景中的模型进行求交的操作,对于OSG这样处理的原因可以参考OSG中的这个MailList: New to OSG, some questions (selection buffer, para

ALLENJIAO的专栏 541

OpenSceneGraph实现的NeHe OpenGL教程 - 第三十课

简介 这节课NeHe课程实现了在场景中进行碰撞检测以及简单的物理作用(碰撞之后的反弹),碰撞检测三维图形学中一个比较高级的主题,本课只涉及了简单的规则几何体之间的碰撞检测,更复杂的实例需要读者去更深入的学习。 实现 本课中碰撞检测的算法包括线与平面的求交检测、线与圆柱体的求交、以及球体之间的碰撞检测,这些碰撞检测的原理可以参考NeHe中的介绍。 具体实现在如下几

ALLENJIAO的专栏 722

用OpenSceneGraph实现的NeHe OpenGL教程 - 第二十九课

简介 这节课NeHe

Frank的专栏 1753

用OpenSceneGraph实现的NeHe OpenGL教程 - 第十五课

简介 NeHe这节课主要讨论OpenGL怎样给文字赋予纹理贴图。OpenGL使用glTexGen函数给文字自动生成纹理坐标。在OSG中,使用osg::TexGen这个继承自StateAttribute的类来实现相同的效果 实现 首先将创建3D的字体,代码如下: osg::Geode *fontGeode = new osg::Geode;     osg::I

Frank的专栏 1780

用OpenSceneGraph实现的NeHe OpenGL教程 - 第十七课

简介 本节课需要实现的内容是使用纹理贴图来模拟文字效果。使用这种技术显示文字的好处在于程序的效果在任何机器上都是相同的。而我们前面讨论的显示文字的方法都是依赖于当前系统中所包含的字体,所以前面讨论的技术在不同的机器上有可能会有不同的显示效果。 使用纹理贴图来显示文字的原理很简单,实际上这些文字是一个一个的四边形,只是为它们贴上了文字的纹理。 实现 首先我们实现场景中的墙面的

Frank的专栏 1921

用OpenSceneGraph实现的NeHe OpenGL教程 - 第二课

这节课主要工作是在场景中添加一个三角形和一个四边形。本节新增加一个函数buildScene,这个函数将在场景中创建一个三角形和一个四边形。 osg场景介绍 在添加场景之前,先对osg的场景结果有一个了解,osg采用场景树的方式来组织场景,如下图所示: 场景已节点(Node)的方式来组织,包括组节点Group(用来管理节点),空间变换节点(MatrixTransform),细节

Frank的专栏 3860
上一篇: 用OpenSceneGraph实现的NeHe OpenGL教程 - 第十课
下一篇: 用OpenSceneGraph实现的NeHe OpenGL教程 - 第十二课
csxiaoshui
博客等级 码龄16年 873粉丝 158原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值