osg解析系列-[osg::osgAnimation]-路径运动动画/变形动画/骨骼动画/纹理动画3

本文详细介绍了在osg中实现四种类型的动画,包括路径运动、变形动画、骨骼动画和纹理动画,并提供了相关代码示例,展示了如何使用osgAnimation库创建和管理动画效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

osg的四类动画的实现细节及示例:
1.路径运动动画
2.变形动画
3.骨骼动画
4.纹理动画

变形动画示例:

// M23.11.W4.osgAnimation.Morph.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include "stdafx.h"
#include <Windows.h>

//osg
#include <osg/Texture2D>
#include <osg/ShapeDrawable>
#include <osg/MatrixTransform>
#include <osg/Geometry>
#include <osg/Material>

#include <osgViewer/Viewer>
#include <osgDB/ReadFile>
#include <osgGA/TrackballManipulator>
#include <osgGA/AnimationPathManipulator>

//osgAnimation
#include <osgAnimation/BasicAnimationManager>
#include <osgAnimation/Channel>
#include <osgAnimation/UpdateMatrixTransform>
#include <osgAnimation/StackedTranslateElement>
#include <osgAnimation/StackedRotateAxisElement>

//osgAnimation-skeleton
#include <osgAnimation/Bone>
#include <osgAnimation/Skeleton>
#include <osgAnimation/RigGeometry>
#include <osgAnimation/UpdateBone>
#include <osgAnimation/StackedTransform>
#include <osgAnimation/StackedTranslateElement>
#include <osgAnimation/StackedRotateAxisElement>

//osglib
#pragma comment(lib,"OpenThreads_d.lib")
#pragma comment(lib,"osg_d.lib")
#pragma comment(lib,"osgDB_d.lib")
#pragma comment(lib,"osgFX_d.lib")
#pragma comment(lib,"osgGA_d.lib")
#pragma comment(lib,"osgUtil_d.lib")
#pragma comment(lib,"osgViewer_d.lib")
#pragma comment(lib,"osgShadow_d.lib")
#pragma comment(lib,"osgAnimation_d.lib")

osg::Geode* createAxis()
{
	osg::Geode* geode(new osg::Geode());
	osg::Geometry* geometry(new osg::Geometry());

	osg::Vec3Array* vertices(new osg::Vec3Array());
	vertices->push_back(osg::Vec3(0.0, 0.0, 0.0));
	vertices->push_back(osg::Vec3(1.0, 0.0, 0.0));
	vertices->push_back(osg::Vec3(0.0, 0.0, 0.0));
	vertices->push_back(osg::Vec3(0.0, 1.0, 0.0));
	vertices->push_back(osg::Vec3(0.0, 0.0, 0.0));
	vertices->push_back(osg::Vec3(0.0, 0.0, 1.0));
	geometry->setVertexArray(vertices);

	osg::Vec4Array* colors(new osg::Vec4Array());
	colors->push_back(osg::Vec4(1.0f, 0.0f, 0.0f, 1.0f));
	colors->push_back(osg::Vec4(1.0f, 0.0f, 0.0f, 1.0f));
	colors->push_back(osg::Vec4(0.0f, 1.0f, 0.0f, 1.0f));
	colors->push_back(osg::Vec4(0.0f, 1.0f, 0.0f, 1.0f));
	colors->push_back(osg::Vec4(0.0f, 0.0f, 1.0f, 1.0f));
	colors->push_back(osg::Vec4(0.0f, 0.0f, 1.0f, 1.0f));
	geometry->setColorArray(colors, osg::Array::BIND_PER_VERTEX);
	geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINES, 0, 6));

	geode->addDrawable(geometry);
	return geode;
}

osgAnimation::RigGeometry* createTesselatedBox(int nsplit, float size)
{
	osgAnimation::RigGeometry* riggeometry = new osgAnimation::RigGeometry;

	osg::Geometry* geometry = new osg::Geometry;
	osg::ref_ptr<osg::Vec3Array> vertices(new osg::Vec3Array());
	osg::ref_ptr<osg::Vec3Array> colors(new osg::Vec3Array());
	geometry->setVertexArray(vertices.get());
	geometry->setColorArray(colors.get(), osg::Array::BIND_PER_VERTEX);

	float step = size / static_cast<float>(nsplit);
	float s = 0.5f / 4.0f;
	for (int i = 0; i < nsplit; i++)
	{
		float x = -1.0f + static_cast<float>(i) * step;
		std::cout << x << std::endl;
		vertices->push_back(osg::Vec3(x, s, s));
		vertices->push_back(osg::Vec3(x, -s, s));
		vertices->push_back(osg::Vec3(x, -s, -s));
		vertices->push_back(osg::Vec3(x, s, -s));
		osg::Vec3 c(0.0f, 0.0f, 0.0f);
		c[i % 3] = 1.0f;
		colors->push_back(c);
		colors->push_back(c);
		colors->push_back(c);
		colors->push_back(c);
	}

	osg::ref_ptr<osg::UIntArray> array = new osg::UIntArray;
	for (int i = 0; i < nsplit - 1; i++)
	{
		int base = i * 4;
		array->push_back(base);
		array->push_back(base + 1);
		array->push_back(base + 4);
		array->push_back(base + 1);
		array->push_back(base + 5);
		array->push_back(base + 4);

		array->push_back(base + 3);
		array->push_back(base);
		array->push_back(base + 4);
		array->push_back(base + 7);
		array->push_back(base + 3);
		array->push_back(base + 4);

		array->push_back(base + 5);
		array->push_back(base + 1);
		array->push_back(base + 2);
		array->push_back(base + 2);
		array->push_back(base + 6);
		array->push_back(base + 5);

		array->push_back(base + 2);
		array->push_back(base + 3);
		array->push_back(base + 7);
		array->push_back(base + 6);
		array->push_back(base + 2);
		array->push_back(base + 7);
	}

	geometry->addPrimitiveSet(new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES, array->size(), &array->front()));
	geometry->setUseDisplayList(false);
	riggeometry->setSourceGeometry(geometry);
	return riggeometry;
}


void initVertexMap(osgAnimation::Bone* b0,
	osgAnimation::Bone* b1,
	osgAnimation::Bone* b2,
	osgAnimation::RigGeometry* geom,
	osg::Vec3Array* array)
{
	osgAnimation::VertexInfluenceMap* vim = new osgAnimation::VertexInfluenceMap;
	(*vim)[b0->getName()].setName(b0->getName());
	(*vim)[b1->getName()].setName(b1->getName());
	(*vim)[b2->getName()].setName(b2->getName());
	for (int i = 0; i < (int)array->size(); i++)
	{
		float val = (*array)[i][0];
		if (val >= -1.0f && val <= 0.0f)
			(*vim)[b0->getName()].push_back(osgAnimation::VertexIndexWeight(i, 1.0f));
		else if (val > 0.0f && val <= 1.0f)
			(*vim)[b1->getName()].push_back(osgAnimation::VertexIndexWeight(i, 1.0f));
		else if (val > 1.0f)
			(*vim)[b2->getName()].push_back(osgAnimation::VertexIndexWeight(i, 1.0f));
	}

	geom->setInfluenceMap(vim);
}



int main(int argc, char* argv[])
{
	osg::ArgumentParser arguments(&argc, argv);
	osgViewer::Viewer viewer(arguments);

	viewer.setCameraManipulator(new osgGA::TrackballManipulator());

	osg::ref_ptr<osgAnimation::Skeleton> skelroot = new osgAnimation::Skeleton;
	skelroot->setDefaultUpdateCallback();
	osg::ref_ptr<osgAnimation::Bone> root = new osgAnimation::Bone;
	root->setInvBindMatrixInSkeletonSpace(osg::Matrix::inverse(osg::Matrix::translate(-1.0, 0.0, 0.0)));
	root->setName("root");
	osgAnimation::UpdateBone* pRootUpdate = new osgAnimation::UpdateBone("root");
	pRootUpdate->getStackedTransforms().push_back(new osgAnimation::StackedTranslateElement("translate", osg::Vec3(-1.0f, 0.0f, 0.0f)));
	root->setUpdateCallback(pRootUpdate);

	osg::ref_ptr<osgAnimation::Bone> right0 = new osgAnimation::Bone;
	right0->setInvBindMatrixInSkeletonSpace(osg::Matrix::inverse(osg::Matrix::translate(0.0, 0.0, 0.0)));
	right0->setName("right0");
	osgAnimation::UpdateBone* pRight0Update = new osgAnimation::UpdateBone("right0");
	pRight0Update->getStackedTransforms().push_back(new osgAnimation::StackedTranslateElement("translate", osg::Vec3(1.0f, 0.0f, 0.0f)));
	pRight0Update->getStackedTransforms().push_back(new osgAnimation::StackedRotateAxisElement("rotate", osg::Vec3(0.0f, 0.0f, 1.0f), 0.0));
	right0->setUpdateCallback(pRight0Update);

	osg::ref_ptr<osgAnimation::Bone> right1 = new osgAnimation::Bone;
	right1->setInvBindMatrixInSkeletonSpace(osg::Matrix::inverse(osg::Matrix::translate(1.0, 0.0, 0.0)));
	right1->setName("right1");
	osgAnimation::UpdateBone* pRight1Update = new osgAnimation::UpdateBone("right1");
	pRight1Update->getStackedTransforms().push_back(new osgAnimation::StackedTranslateElement("translate", osg::Vec3(1.0f, 0.0f, 0.0f)));
	pRight1Update->getStackedTransforms().push_back(new osgAnimation::StackedRotateAxisElement("rotate", osg::Vec3(0.0f, 0.0f, 1.0f), 0.0));
	right1->setUpdateCallback(pRight1Update);

	root->addChild(right0.get());
	right0->addChild(right1.get());
	skelroot->addChild(root.get());

	osg::Group* scene = new osg::Group;
	osg::ref_ptr<osgAnimation::BasicAnimationManager> manager = new osgAnimation::BasicAnimationManager;
	scene->setUpdateCallback(manager.get());

	osgAnimation::Animation* anim = new osgAnimation::Animation;
	{
		osgAnimation::FloatKeyframeContainer* keys0 = new osgAnimation::FloatKeyframeContainer;
		keys0->push_back(osgAnimation::FloatKeyframe(0.0, 0.0f));
		keys0->push_back(osgAnimation::FloatKeyframe(3.0, osg::PI_2));
		keys0->push_back(osgAnimation::FloatKeyframe(6.0, osg::PI_2));
		osgAnimation::FloatLinearSampler* sampler = new osgAnimation::FloatLinearSampler;
		sampler->setKeyframeContainer(keys0);
		osgAnimation::FloatLinearChannel* channel = new osgAnimation::FloatLinearChannel(sampler);
		channel->setName("rotate");
		channel->setTargetName("right0");
		anim->addChannel(channel);
	}

	{
		osgAnimation::FloatKeyframeContainer* keys1 = new osgAnimation::FloatKeyframeContainer;
		keys1->push_back(osgAnimation::FloatKeyframe(0.0, 0.0f));
		keys1->push_back(osgAnimation::FloatKeyframe(3.0, 0.0f));
		keys1->push_back(osgAnimation::FloatKeyframe(6.0, osg::PI_2));
		osgAnimation::FloatLinearSampler* sampler = new osgAnimation::FloatLinearSampler;
		sampler->setKeyframeContainer(keys1);
		osgAnimation::FloatLinearChannel* channel = new osgAnimation::FloatLinearChannel(sampler);
		channel->setName("rotate");
		channel->setTargetName("right1");
		anim->addChannel(channel);
	}
	manager->registerAnimation(anim);
	manager->buildTargetReference();

	// let's start !
	manager->playAnimation(anim);

	// we will use local data from the skeleton
	osg::MatrixTransform* rootTransform = new osg::MatrixTransform;
	rootTransform->setMatrix(osg::Matrix::rotate(osg::PI_2, osg::Vec3(1.0f, 0.0f, 0.0f)));
	right0->addChild(createAxis());
	right0->setDataVariance(osg::Object::DYNAMIC);
	right1->addChild(createAxis());
	right1->setDataVariance(osg::Object::DYNAMIC);
	osg::MatrixTransform* trueroot = new osg::MatrixTransform;
	trueroot->setMatrix(osg::Matrix(root->getMatrixInBoneSpace().ptr()));
	trueroot->addChild(createAxis());
	trueroot->addChild(skelroot.get());
	trueroot->setDataVariance(osg::Object::DYNAMIC);
	rootTransform->addChild(trueroot);
	scene->addChild(rootTransform);

	osgAnimation::RigGeometry* geom = createTesselatedBox(4, 4.0f);
	osg::Geode* geode = new osg::Geode;
	geode->addDrawable(geom);
	skelroot->addChild(geode);
	osg::ref_ptr<osg::Vec3Array> src = dynamic_cast<osg::Vec3Array*>(geom->getSourceGeometry()->getVertexArray());
	geom->getOrCreateStateSet()->setMode(GL_LIGHTING, false);
	geom->setDataVariance(osg::Object::DYNAMIC);

	initVertexMap(root.get(), right0.get(), right1.get(), geom, src.get());

	// let's run !
	viewer.setSceneData(scene);
	viewer.realize();
	while (!viewer.done())
	{
		viewer.frame();
	}

	return 0;
}

运行结果:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值