Bullet(Cocos2dx)之创建地形

Bullet(Cocos2dx)之创建地形,第1张

概述Bullet提供了几个类btBvhTriangleMeshShape,btHeightfieldTerrainShape去创建一些网格图形,首先了解btHeightfieldTerrainShape,通过高度图数据创建一个3D地形。 A static mesh that is optimised for and described by the surface of a height map. 官

Bullet提供了几个类btBvhTriangleMeshShapebtHeightfIEldTerrainShape去创建一些网格图形,首先了解btHeightfIEldTerrainShape,通过高度图数据创建一个3D地形。

Astaticmeshthatisoptimisedforanddescribedbythesurfaceofaheightmap.

官网解释:http://bulletphysics.com/Bullet/BulletFull/classbtHeightfieldTerrainShape.html#a90d823ba5f44871a0bcfce0174177223

建议先阅读官网介绍

首先可以下几个效果图


根据高度图数据.raw生成的高度地形图

参数设置HeightfIEldInfoinfo(128,_heightmapData.getBytes(),PHY_UCHAR,1.6f/uData,-1.f,1.f,btVector3(25.f/uData,25.f/uData));

(uData_heightmapData的最大值)


自定义数据生成高度地形图(PHY_float)

参数设置HeightfIEldInfoinfo(128,mapData,PHY_float,btVector3(1.f,1.f));

mapData自定义数据,随机0~1的数据



自定义数据生成高度地形图(PHY_float)

参数设置PHY_SHORT,1.f));

mapData自定义数据0,1的数据


Bullet自带的Demo中的例子


btHeightfIEldTerrainShape有两个构造函数,这里分析较复杂的一个

btHeightfIEldTerrainShape(

intheightStickWIDth,x轴总宽度

intheightStickLength,z轴总长度

比如wIDth=128,length=64则x轴方向为128,z轴方向为64

constvoID*heightfIEldData,高度数据

btScalarheightScale,每个字节*heightScale=实际高度

btScalarminHeight,最小高度

btScalarmaxHeight,最大高度

地形原点=(minHeight+maxHeight)*0.5

intupaxis,方向轴取值0=x,1=y,2=z,决定地形的朝向,类似法向量

PHY_ScalarTypeheightDataType,数据格式3种,PHY_SHORT,PHY_float

boolflipQuadEdges 方形裁剪

);


举个例子

50*50数据

for(inti=0;i<50;++i)

{

for(intj=0;j<50;++j)

{

heightmap[i*50+j]=j%2;

}

}

对于heightmap[i*50+j]

1.如果为0,minHeight=0.f,maxHeight=6.f;

最低点正好为-3.f

2.如果为0,maxHeight=12.f;

最低点正好为-6.f

3.如果为0,maxHeight=3.f;

最低点正好为-1.5f

1.如果为2,maxHeight=6.f;

最低点正好为-4.f

2.如果为2,maxHeight=12.f;

最低点正好为-7.f

3.如果为2,maxHeight=3.f;

最低点正好为-2.5f

地形偏移offsetY=-(minHeight+maxHeight);

不推荐minHeight+maxHeight<0,不稳定

heightScale*value(heightfIEldData[i])为实际高度

高度计算:

对于PHY_UCHAR

最低点y=offsetY+min(heightfIEldData);minY=0

最高点y=offsetY+max(heightfIEldData)*heightScale;

对于PHY_SHORT,PHY_float

最高点y=offsetY+max(heightfIEldData)*heightScale;

最低点y=offsetY+min(heightfIEldData)*heightScale;

注意:

网格间隔不要过大,过大会出现物体穿过。

自定义数据类型简化参数传递

struct HeightfIEldInfo{	int heightStickWIDth;	int heightStickLength;	voID* heightfIEldData;	PHY_ScalarType hdt;	btScalar heightScale;	btScalar minHeight;	btScalar maxHeight;	int upaxis;	bool usefloatData;	bool flipQuadEdges;	btVector3 localScaling;	HeightfIEldInfo(int wIDth,int length,voID* data,PHY_ScalarType type = PHY_SHORT,btScalar heiScale = 1.f,btScalar minHei = 0.f,btScalar maxHei = 1.f,const btVector3& scale = btVector3(1,1,1),int up = 1,bool usefloat = false,bool filpQuad = false) :		heightStickWIDth(wIDth),heightStickLength(length),heightfIEldData(data),heightScale(heiScale),minHeight(minHei),maxHeight(maxHei),localScaling(scale),upaxis(up),hdt(type),usefloatData(usefloat),flipQuadEdges(filpQuad)	{}};

PhysicsWorld3D创建高度地形图

btRigIDBody* PhysicsWorld3D::addHeightfIEldTerrain(const HeightfIEldInfo& fIEldInfo,const btVector3& position,const PhysicsMaterial3D& material){	CCAssert(material.mass == 0.f,"height fIEld's mass must be 0.");	btHeightfIEldTerrainShape* heightfIEldShape = new btHeightfIEldTerrainShape(		fIEldInfo.heightStickWIDth,fIEldInfo.heightStickLength,fIEldInfo.heightfIEldData,fIEldInfo.heightScale,fIEldInfo.minHeight,fIEldInfo.maxHeight,fIEldInfo.upaxis,fIEldInfo.hdt,fIEldInfo.flipQuadEdges);	heightfIEldShape->setUseDiamondSubdivision(true);	// 钻石细分矩形方格会出现对角线	heightfIEldShape->setLocalScaling(fIEldInfo.localScaling);	auto body = getbody(heightfIEldShape,position,material);	_world->addRigIDBody(body);	return body;}

下面来介绍btBvhTriangleMeshShape,通过载入三角网格,实现网格形状的物理模拟

http://bulletphysics.com/Bullet/BulletFull/classbtBvhTriangleMeshShape.html

看看效果


地形能够与模型完美的融合在一起,而且即使半径为0.1的球体也不会穿过地形

使用的shape就是btBvhTriangleMeshShape,构造方法有两个

btBvhTriangleMeshShape(

btStrIDingMeshInterface*meshInterface,//网格接口,存放网格数据

booluseQuantizedAabbCompression,//压缩?只有buildBvh为true才有效

constbtVector3&bvhAabbMin,

btVector3&bvhAabbMax,//mesh不可超过bvhaabb包围盒,只有buildBvh为true才有效

boolbuildBvh=true);//优化BVH


btBvhTriangleMeshShape(

true);

通过导入一个模型的原始三角形数据,就可以建立上图的地形

如何载入模型数据,官网类关系图


提供btTriangleIndexVertexArray,载入网格数据

btTriangleIndexVertexArray(

intnumTriangles,//三角个数

int*triangleIndexBase,//三角形索引数组首地址

inttriangleIndexStrIDe,//每个三角形索引大小=索引类型大小*3

intnumVertices,//顶点个数

btScalar*vertexBase,//顶点数组首地址

intvertexStrIDe); //每个顶点字节=顶点元素*3

既然索引类型为int,就用int

关于原始三角形数据如何得到,

1.可以利用cocos2dx的载入模型函数获取(有待实验)

2.利用Blender或者可以导出模型原始三角数据的软件,直接导出数据

关于Blender一款开源的3D建模软件,官网:http://www.blender.org/,自带游戏引擎,物理引擎就是Bullet

Blender raw 文件

导出三角形数据,Blender有个插件专门导出三角形数据文件后缀名为raw,它是文本格式的,

导出时首先要让模型旋转一定角度,坐标系不是opengl的坐标系,cocos2dx采用的就是opengl的坐标系

raw文件格式非常简单:n,每行9个浮点数据(描述一个三角形),每三个浮点为一个顶点

3.自定义格式

。。。。

来实现数据的载入吧

首先读取raw文件,实现一个简单的PhysicsHelper3D

#ifndef __PHYSICS_HELPER_3D_H__#define __PHYSICS_HELPER_3D_H__#include <cocos2d.h>USING_NS_CC;class PhysicsHelper3D{public:	static std::vector<float> loadRaw(const char* filename);	static bool loadRaw(const char* filename,std::vector<float>& verts);};#endif // !__PHYSICS_HELPER_3D_H__#include "PhysicsHelper3D.h"std::vector<float> PhysicsHelper3D::loadRaw(const char* filename){	std::vector<float> data;	if (loadRaw(filename,data))	{		return data;	}	return std::vector<float>(0);}bool PhysicsHelper3D::loadRaw(const char* filename,std::vector<float>& verts){	char line[1024];		float oneData;	auto rawData = fileUtils::getInstance()->getStringFromfile(filename);	// 利用cocos2dx载入文件	std::stringstream ss,ssline;	ss << rawData;				while (ss.getline(line,1024))	// 读取一行	{		ssline << line;		for (int i = 0; i < 9; i++)	// 获取9个浮点数		{			ssline >> oneData;			verts.push_back(oneData);		}	}	return true;}

并不是很难吧,载入文件办法不好,不过先将就着用吧

_indexVertexArrays = new btTriangleIndexVertexArray(_verts.size() / 9,&_verIndices[0],3 * sizeof(int),_verts.size() / 3,(btScalar*)&_verts[0],3 * sizeof(float));_meshShape = new btBvhTriangleMeshShape(_indexVertexArrays,true);_verts是vector<float> 三角形的个数 =_verts.size() / 9为了构建方便实现PhysicsMesh3D#ifndef __PHYSICS_MESH_3D_H__#define __PHYSICS_MESH_3D_H__#include "Bullet/btBulletDynamicsCommon.h"#include "cocos2d.h"USING_NS_CC;class PhysicsMesh3D{public:	static PhysicsMesh3D* constuct(const char* filename);		voID destroy();	bool initWithfile(const char* filename);private:	std::vector<float> _verts;		// 存放顶点	std::vector<int> _verIndices;	// 顶点索引	btTriangleIndexVertexArray* _indexVertexArrays;	// 三角形数据	CC_SYNTHESIZE_Readonly(btBvhTriangleMeshShape*,_meshShape,MeshShape);	// shape};#endifCC_SYNTHESIZE_Readonly 为cocos2dx提供的宏bool PhysicsMesh3D::initWithfile(const char* filename){	_indexVertexArrays = nullptr;	_verts.clear();	_verIndices.clear();	if (PhysicsHelper3D::loadRaw(filename,_verts))		// 载入数据	{		_verIndices.resize(_verts.size());			// 顶点的位置就是索引		for (int i=0; i < _verts.size(); ++i)		{			_verIndices[i] = i;		}		_indexVertexArrays = new btTriangleIndexVertexArray(_verts.size() / 9,// 三角形个数&_verIndices[0],// 三角数据数组首地址3 * sizeof(int),// 一个三角索引大小					_verts.size() / 3,// 顶点个数(btScalar*)&_verts[0],// 顶点数组首地址3 * sizeof(float));		// 一个顶点大小// 获取shape		_meshShape = new btBvhTriangleMeshShape(_indexVertexArrays,true);		return true;	}	return false;}

释放申请的内存

voID PhysicsMesh3D::destroy(){	_verts.clear();	_verIndices.clear();	delete _indexVertexArrays;	delete this;}

在PhysicsWorld3D建立一个添加Mesh的方法

btRigIDBody* addTriangleMesh(PhysicsMesh3D* mesh3D,const PhysicsMaterial3D& material = PHYSICS_MATERIAL3D_PLANE);btRigIDBody* PhysicsWorld3D::addTriangleMeshShape(PhysicsMesh3D* mesh3D,"body's mass must be 0.");	auto body = getbody(mesh3D->getMeshShape(),material);	_world->addRigIDBody(body);	return body;}

测试

HelloWorld添加变量

PhysicsMesh3D* _phyMesh3D;	// mesh shape
添加网格
_phyMesh3D = PhysicsMesh3D::constuct("heightmap.raw");_world->addTriangleMesh(_phyMesh3D,btVector3(0,0));// 载入plane模型auto spPlane = Sprite3D::create("model/heightmap.c3b"); this->addChild(spPlane);spPlane->setposition3D(Vec3(0,0));spPlane->setRotation3D(Vec3(0,180,0));

onExit()不要忘了

_phyMesh3D->destroy();


为了方便测试,实现了一个漫游摄像机,有空讲解一下。

完整源码及资源

github

总结

以上是内存溢出为你收集整理的Bullet(Cocos2dx)之创建地形全部内容,希望文章能够帮你解决Bullet(Cocos2dx)之创建地形所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1030034.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-23
下一篇 2022-05-23

发表评论

登录后才能评论

评论列表(0条)

保存