Bullet (COCOS2DX) Creation of terrain

Source: Internet
Author: User

Bullet provides several classes of btbvhtrianglemeshshape,btheightfieldterrainshape to create some grid graphics, first to understand Btheightfieldterrainshape, create a 3D terrain from the height graph data.

A static mesh that's optimised for and described by the surface of a height map.

Official website explanation:http://bulletphysics.com/Bullet/BulletFull/classbtHeightfieldTerrainShape.html# a90d823ba5f44871a0bcfce0174177223

Recommended first read the official website introduction

The first few


Based on the height map data. High topographic map generated by Raw

Parameter Settings heightfieldinfo info (_heightmapdata.getbytes (), Phy_uchar, 1.6f/udata, -1.f, 1.f, BtVector3 (25.f/uda Ta, 1.f, 25.f/udata));

(UData is the maximum value of _heightmapdata )


Custom data generation height topographic map (phy_float)

Parameter Settings heightfieldinfo info (mapData, phy_float, 1.f, -1.f, 1.f, BtVector3(1.f, 1.F, 1). f));

MapData custom data, random 0~1 data



Custom data generation height topographic map (phy_float)

Parameter Settings heightfieldinfo info (mapData, phy_short, 1.f, -1.f, 1.f, BtVector3(1.f, 1.F, 1). f));

MapData data for custom data 0,1


examples of Bullet 's own Demo


Btheightfieldterrainshape has two constructors, which analyze the more complex one

Btheightfieldterrainshape (

int heightstickwidth, total x axis width

int heightsticklength, z-axis total length

For example, width = x, length = 64, 128,z axis direction is 64

Const void* Heightfielddata, height data

Btscalar Heightscale, *heightscale per byte = actual height

Btscalar minheight, min. height

Btscalar maxheight, max height

Terrain origin = (MinHeight + maxheight) * 0.5

int Upaxis, Direction axis value 0=x, 1=y, 2=z, determines the orientation of the terrain, similar to the normal vector

Phy_scalartype heightdatatype, data Format 3 kinds, Phy_uchar, Phy_short, phy_float

BOOL Flipquadedges Square cropping

);


As an example,

50*50 data

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

{

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

{

HEIGHTMAP[I*50+J] = j% 2;

}

}

For Heightmap[i*50+j]

1. If 0, minheight = 0.f, maxheight = 6.F;

The lowest point is just -3.f.

2. If 0, minheight = 0.f, maxheight = 12.f;

The lowest point is just -6.f.

3. If 0, minheight = 0.f, maxheight = 3.F;

The lowest point is just -1.5f.

1. If 2, MinHeight = 0.f, maxheight = 6.F;

The lowest point is just -4.f.

2. If 2, MinHeight = 0.f, maxheight = 12.f;

The lowest point is just -7.f.

3. If 2, MinHeight = 0.f, maxheight = 3.F;

The lowest point is just -2.5f.

Terrain Offset offsety =-(MinHeight + maxheight);

Not recommended MinHeight + MaxHeight < 0, unstable

Heightscale * Value (Heightfielddata[i]) is the actual height

Height calculation:

For Phy_uchar

Lowest point y = OffsetY + min (heightfielddata); Miny = 0

The highest point y = OffsetY + max (heightfielddata) * Heightscale;

For Phy_short, Phy_float

The highest point y = OffsetY + max (heightfielddata) * Heightscale;

Lowest point y = OffsetY + min (heightfielddata) * Heightscale;

Attention:

The grid spacing should not be too large, passing through the Assembly of objects.

Custom data type simplified parameter passing

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 MinH ei = 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 creating a highly topographic map

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);//The Diagonal heightfieldshape->setlocalscaling (fieldinfo.localscaling) will appear in the Diamond subdivision rectangle square; Auto BODY = GetBody (heightfieldshape, position, material); _world->addrigidbody (body); return body;}

Here's a description Btbvhtrianglemeshshape , the physical simulation of grid shape is realized by loading triangular meshes .

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

Look at the effect


The terrain can be perfectly fused with the model , and even spheres with a radius of 0.1 will not cross the terrain

The shape used is btbvhtrianglemeshshape, and the construction method has two

Btbvhtrianglemeshshape (

btstridingmeshinterface* meshinterface, //grid interface, storing grid data

bool usequantizedaabbcompression,//compression? Only valid if BUILDBVH is True

Const BtVector3& Bvhaabbmin,

Const BtVector3& Bvhaabbmax, //mesh cannot exceed bvhaabb bounding box, only BUILDBVH is true

bool BUILDBVH = true); //optimize BVH


Btbvhtrianglemeshshape (

btstridingmeshinterface* meshinterface,

bool usequantizedaabbcompression,

bool BUILDBVH = true);

By importing the raw triangle data of a model, you can create a terrain

How to load model data, official website class diagram


Provide Bttriangleindexvertexarray, load grid data

Bttriangleindexvertexarray (

int numtriangles,//Triangle number

int* triangleindexbase,//Triangle index Array first address

int triangleindexstride,//index size per triangle = Index Type size * 3

int numvertices,//Vertex count

btscalar* vertexbase,//vertex array first address

int vertexstride); Bytes per vertex = vertex element * 3

Since the index type is int, use int

about how the raw triangle data is obtained,

1. Can be obtained using cocos2dx 's load model function ( pending Experiment )

2. directly export data using Blender or software that can export the original triangular data of the model

About Blender an open source 3D modeling software , official website :/http www.blender.org/ , with its own game engine, the physics engine is Bullet

Export triangle data,Blender has a plugin specifically exported triangle data file suffix named raw, it is text Format ,

When exporting, first let the model rotate a certain angle , the coordinate system is not the OpenGL coordinate system,cocos2dx uses OpenGL the coordinate system

The raw file format is simple:n rows of 9 Floating-point data per line ( describe a triangle ), each three floating point is a vertex

3. Custom formats

。。。。

To implement the data loading.

First read the raw file, implement a simple 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);//use COCOS2DX to load files Std::stringstream  SS, Ssline;ss << Rawdata;while (Ss.getline (line, 1024))//read a row {ssline << line;for (int i = 0; i < 9; i++)// Get 9 floating-point numbers {ssline >> onedata;verts.push_back (Onedata);}} return true;}

It's not hard, but it's not good to load the file, but let's use it.

_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 is the number of vector<float> triangles =_verts.size ()/9 in order to build a convenient implementation 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;//storage vertex std::vector<int> _verindices;// Vertex index bttriangleindexvertexarray* _indexvertexarrays;//triangle Data cc_synthesize_readonly (btbvhtrianglemeshshape*, _ Meshshape, Meshshape);//shape}; #endifCC_SYNTHESIZE_READONLY the macro bool Physicsmesh3d::initwithfile provided for COCOS2DX (const char* fileName) {_indexvertexarrays = Nullptr;_verts.clear (); _verindices.clear (); if (Physicshelper3d::loadraw ( FilenaMe, _verts)//Load Data {_verindices.resize (_verts.size ());//The position of vertex is index for (int i=0; i < _verts.size (); ++i) {_verindices[ I] = i;} _indexvertexarrays = new Bttriangleindexvertexarray (_verts.size ()/9,//number of triangles &_verindices[0],//Triangle data Array First address 3 * Sizeo f (int),//A triangular index size _verts.size ()/3,//Vertex count (btscalar*) &_verts[0],//vertex array first address 3 * sizeof (float));//a vertex size//Get Shape_m Eshshape = new Btbvhtrianglemeshshape (_indexvertexarrays, True); return true;} return false;}

Release the requested memory

void Physicsmesh3d::d Estroy () {_verts.clear (); _verindices.clear ();d elete _indexvertexarrays;delete this;}

Create a method for adding mesh in Physicsworld3d

btrigidbody* Addtrianglemeshshape (physicsmesh3d* mesh3d, const btvector3& position, const physicsmaterial3d& material = Physics_material3d_plane); btrigidbody* Physicsworld3d::addtrianglemeshshape (physicsmesh3d* Mesh3D, const btvector3& position, const physicsmaterial3d& material) {Ccassert (Material.mass = = 0.f, "body ' s mass must be 0."); Auto BODY = GetBody (Mesh3d->getmeshshape (), position, material); _world->addrigidbody (body); return body;}

Test

HelloWorld Adding variables

physicsmesh3d* _phymesh3d;//Mesh Shape
Add Mesh

_phymesh3d = Physicsmesh3d::constuct ("Heightmap.raw"); _world->addtrianglemeshshape (_phyMesh3D, BtVector3 (0, 0, 0 );//load plane model Auto Spplane = sprite3d::create ("model/heightmap.c3b"); This->addchild (Spplane); Spplane->setposition3d (Vec3 (0, 0, 0)); spplane->setrotation3d (VEC3 (0, 180, 0));

OnExit () Don't forget.

_phymesh3d->destroy ();


For the convenience of testing, a roaming camera has been implemented and is available for explanation.

Full Source and resources

GitHub

Bullet (COCOS2DX) Creation of terrain

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.