mirror of https://github.com/axmolengine/axmol.git
Merge pull request #276 from tangziwen/terrain
update Terrain, support skirt
This commit is contained in:
commit
45987b6a60
|
@ -8,14 +8,16 @@ USING_NS_CC;
|
|||
#include "renderer/CCRenderer.h"
|
||||
#include "renderer/CCGLProgramStateCache.h"
|
||||
#include "renderer/ccGLStateCache.h"
|
||||
#include "base/CCDirector.h"
|
||||
#include "2d/CCCamera.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
NS_CC_BEGIN
|
||||
Terrain * Terrain::create(TerrainData ¶meter)
|
||||
Terrain * Terrain::create(TerrainData ¶meter, CrackFixedType fixedType)
|
||||
{
|
||||
Terrain * terrain = new (std::nothrow)Terrain();
|
||||
terrain->_terrainData = parameter;
|
||||
terrain->_crackFixedType = fixedType;
|
||||
terrain->_isCameraViewChanged = true;
|
||||
terrain->_isTerrainModelMatrixChanged = true;
|
||||
//chunksize
|
||||
|
@ -28,7 +30,7 @@ Terrain * Terrain::create(TerrainData ¶meter)
|
|||
textImage->initWithImageFile(parameter.detailMaps[0].detailMapSrc);
|
||||
auto texture = new (std::nothrow)Texture2D();
|
||||
texture->initWithImage(textImage);
|
||||
terrain->textures.push_back(texture);
|
||||
terrain->_detailMapTextures[0] = texture;
|
||||
}else
|
||||
{
|
||||
//alpha map
|
||||
|
@ -42,8 +44,7 @@ Terrain * Terrain::create(TerrainData ¶meter)
|
|||
textImage->initWithImageFile(parameter.detailMaps[i].detailMapSrc);
|
||||
auto texture = new (std::nothrow)Texture2D();
|
||||
texture->initWithImage(textImage);
|
||||
terrain->textures.push_back(texture);
|
||||
terrain->detailSize[i] = parameter.detailMaps[i].detailMapSize;
|
||||
terrain->_detailMapTextures[i] = texture;
|
||||
}
|
||||
}
|
||||
terrain->init();
|
||||
|
@ -94,7 +95,7 @@ void Terrain::onDraw(const Mat4 &transform, uint32_t flags)
|
|||
if(!_alphaMap)
|
||||
{
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D,textures[0]->getName());
|
||||
glBindTexture(GL_TEXTURE_2D,_detailMapTextures[0]->getName());
|
||||
auto texture_location = glGetUniformLocation(glProgram->getProgram(),"u_texture0");
|
||||
glUniform1i(texture_location,0);
|
||||
auto alpha_location = glGetUniformLocation(glProgram->getProgram(),"u_has_alpha");
|
||||
|
@ -104,7 +105,7 @@ void Terrain::onDraw(const Mat4 &transform, uint32_t flags)
|
|||
for(int i =0;i<_maxDetailMapValue;i++)
|
||||
{
|
||||
glActiveTexture(GL_TEXTURE0+i);
|
||||
glBindTexture(GL_TEXTURE_2D,textures[i]->getName());
|
||||
glBindTexture(GL_TEXTURE_2D,_detailMapTextures[i]->getName());
|
||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
|
||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
|
||||
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
|
||||
|
@ -116,7 +117,7 @@ void Terrain::onDraw(const Mat4 &transform, uint32_t flags)
|
|||
|
||||
sprintf(str,"u_detailSize[%d]",i);
|
||||
auto detailSizeLocation = glGetUniformLocation(glProgram->getProgram(),str);
|
||||
glUniform1f(detailSizeLocation,detailSize[i]);
|
||||
glUniform1f(detailSizeLocation,_terrainData.detailMaps[i].detailMapSize);
|
||||
}
|
||||
|
||||
auto alpha_location = glGetUniformLocation(glProgram->getProgram(),"u_has_alpha");
|
||||
|
@ -145,7 +146,7 @@ void Terrain::onDraw(const Mat4 &transform, uint32_t flags)
|
|||
_oldTerrrainModelMatrix = terrainWorldTransform;
|
||||
}
|
||||
|
||||
quad->updateAABB(_oldTerrrainModelMatrix);
|
||||
_quadRoot->updateAABB(_oldTerrrainModelMatrix);
|
||||
|
||||
if(_isCameraViewChanged || _isTerrainModelMatrixChanged)
|
||||
{
|
||||
|
@ -157,11 +158,11 @@ void Terrain::onDraw(const Mat4 &transform, uint32_t flags)
|
|||
|
||||
if(_isCameraViewChanged || _isTerrainModelMatrixChanged)
|
||||
{
|
||||
quad->resetNeedDraw(true);//reset it
|
||||
_quadRoot->resetNeedDraw(true);//reset it
|
||||
//camera frustum culling
|
||||
quad->cullByCamera(camera,_oldTerrrainModelMatrix);
|
||||
_quadRoot->cullByCamera(camera,_oldTerrrainModelMatrix);
|
||||
}
|
||||
quad->draw();
|
||||
_quadRoot->draw();
|
||||
if(_isCameraViewChanged)
|
||||
{
|
||||
_isCameraViewChanged = false;
|
||||
|
@ -219,7 +220,7 @@ void Terrain::initHeightMap(const char * heightMap)
|
|||
if(m+1<chunk_amount_y) _chunkesArray[m][n]->front = _chunkesArray[m+1][n];
|
||||
}
|
||||
}
|
||||
quad = new QuadTree(0,0,imageWidth,imageHeight,this);
|
||||
_quadRoot = new QuadTree(0,0,imageWidth,imageHeight,this);
|
||||
}
|
||||
|
||||
Terrain::Terrain()
|
||||
|
@ -249,7 +250,7 @@ void Terrain::setChunksLOD(Vec3 cameraPos)
|
|||
}
|
||||
}
|
||||
|
||||
float Terrain::getHeight(float x,float z,Vec3 * normal)
|
||||
float Terrain::getHeight(float x, float z, Vec3 * normal)
|
||||
{
|
||||
Vec2 pos = Vec2(x,z);
|
||||
|
||||
|
@ -298,7 +299,7 @@ float Terrain::getHeight(float x,float z,Vec3 * normal)
|
|||
}
|
||||
}
|
||||
|
||||
float Terrain::getHeight(Vec2 pos,Vec3*Normal)
|
||||
float Terrain::getHeight(Vec2 pos, Vec3*Normal)
|
||||
{
|
||||
return getHeight(pos.x,pos.y,Normal);
|
||||
}
|
||||
|
@ -391,7 +392,7 @@ void Terrain::setDrawWire(bool bool_value)
|
|||
_isDrawWire = bool_value;
|
||||
}
|
||||
|
||||
void Terrain::setLODDistance(float lod_1,float lod_2,float lod_3)
|
||||
void Terrain::setLODDistance(float lod_1, float lod_2, float lod_3)
|
||||
{
|
||||
_lodDistance[0] = lod_1;
|
||||
_lodDistance[1] = lod_2;
|
||||
|
@ -418,7 +419,7 @@ Terrain::~Terrain()
|
|||
}
|
||||
}
|
||||
|
||||
cocos2d::Vec3 Terrain::getNormal(int pixel_x,int pixel_y)
|
||||
cocos2d::Vec3 Terrain::getNormal(int pixel_x, int pixel_y)
|
||||
{
|
||||
float a = getImageHeight(pixel_x,pixel_y)*getScaleY();
|
||||
float b = getImageHeight(pixel_x,pixel_y+1)*getScaleY();
|
||||
|
@ -511,7 +512,7 @@ void Terrain::resetHeightMap(const char * heightMap)
|
|||
}
|
||||
}
|
||||
}
|
||||
delete quad;
|
||||
delete _quadRoot;
|
||||
initHeightMap(heightMap);
|
||||
}
|
||||
|
||||
|
@ -527,7 +528,112 @@ float Terrain::getMaxHeight()
|
|||
|
||||
cocos2d::AABB Terrain::getAABB()
|
||||
{
|
||||
return quad->_worldSpaceAABB;
|
||||
return _quadRoot->_worldSpaceAABB;
|
||||
}
|
||||
|
||||
Terrain::QuadTree * Terrain::getQuadTree()
|
||||
{
|
||||
return _quadRoot;
|
||||
}
|
||||
|
||||
void Terrain::setAlphaMap(cocos2d::Texture2D * newAlphaMapTexture)
|
||||
{
|
||||
_alphaMap->release();
|
||||
_alphaMap = newAlphaMapTexture;
|
||||
}
|
||||
|
||||
void Terrain::setDetailMap(unsigned int index, DetailMap detailMap)
|
||||
{
|
||||
if(index>4)
|
||||
{
|
||||
CCLOG("invalid DetailMap index %d\n",index);
|
||||
}
|
||||
_terrainData.detailMaps[index] = detailMap;
|
||||
if(_detailMapTextures[index])
|
||||
{
|
||||
|
||||
_detailMapTextures[index]->release();
|
||||
}
|
||||
_detailMapTextures[index] = new (std::nothrow)Texture2D();
|
||||
auto textImage = new (std::nothrow)Image();
|
||||
textImage->initWithImageFile(detailMap.detailMapSrc);
|
||||
_detailMapTextures[index]->initWithImage(textImage);
|
||||
}
|
||||
|
||||
Terrain::ChunkIndices Terrain::lookForIndicesLOD(int neighborLod[4], int selfLod, bool * result)
|
||||
{
|
||||
(* result) =false;
|
||||
ChunkIndices tmp;
|
||||
tmp.indices = 0;
|
||||
tmp.size = 0;
|
||||
if(_chunkLodIndicesSet.empty())
|
||||
{
|
||||
(* result) =false;
|
||||
return tmp;
|
||||
}else
|
||||
{
|
||||
int test[5];
|
||||
memcpy(test,neighborLod,sizeof(int [4]));
|
||||
test[4] = selfLod;
|
||||
for(int i =0;i<_chunkLodIndicesSet.size();i++)
|
||||
{
|
||||
if(memcmp(test,_chunkLodIndicesSet[i].relativeLod,sizeof(test))==0)
|
||||
{
|
||||
(*result) = true;
|
||||
return _chunkLodIndicesSet[i]._chunkIndices;
|
||||
}
|
||||
}
|
||||
}
|
||||
(* result) =false;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
Terrain::ChunkIndices Terrain::insertIndicesLOD(int neighborLod[4], int selfLod, GLushort * indices,int size)
|
||||
{
|
||||
ChunkLODIndices lodIndices;
|
||||
memcpy(lodIndices.relativeLod,neighborLod,sizeof(int [4]));
|
||||
lodIndices.relativeLod[4] = selfLod;
|
||||
lodIndices._chunkIndices.size = size;
|
||||
glGenBuffers(1,&(lodIndices._chunkIndices.indices));
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, lodIndices._chunkIndices.indices);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(GLushort)*size,indices,GL_STATIC_DRAW);
|
||||
this->_chunkLodIndicesSet.push_back(lodIndices);
|
||||
return lodIndices._chunkIndices;
|
||||
}
|
||||
|
||||
Terrain::ChunkIndices Terrain::lookForIndicesLODSkrit(int selfLod, bool * result)
|
||||
{
|
||||
ChunkIndices badResult;
|
||||
badResult.indices = 0;
|
||||
badResult.size = 0;
|
||||
if(this->_chunkLodIndicesSkirtSet.empty())
|
||||
{
|
||||
(*result) = false;
|
||||
return badResult;
|
||||
}
|
||||
|
||||
for(int i =0;i<_chunkLodIndicesSkirtSet.size();i++)
|
||||
{
|
||||
if(_chunkLodIndicesSkirtSet[i].selfLod == selfLod)
|
||||
{
|
||||
(*result) = true;
|
||||
return _chunkLodIndicesSkirtSet[i]._chunkIndices;
|
||||
}
|
||||
}
|
||||
(*result) = false;
|
||||
return badResult;
|
||||
}
|
||||
|
||||
Terrain::ChunkIndices Terrain::insertIndicesLODSkirt(int selfLod, GLushort * indices, int size)
|
||||
{
|
||||
ChunkLODIndicesSkirt skirtIndices;
|
||||
skirtIndices.selfLod = selfLod;
|
||||
skirtIndices._chunkIndices.size = size;
|
||||
glGenBuffers(1,&(skirtIndices._chunkIndices.indices));
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, skirtIndices._chunkIndices.indices);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(GLushort)*size,indices,GL_STATIC_DRAW);
|
||||
this->_chunkLodIndicesSkirtSet.push_back(skirtIndices);
|
||||
return skirtIndices._chunkIndices;
|
||||
}
|
||||
|
||||
void Terrain::Chunk::finish()
|
||||
|
@ -568,10 +674,21 @@ void Terrain::Chunk::bindAndDraw()
|
|||
glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
|
||||
if(_terrain->_isCameraViewChanged)
|
||||
{
|
||||
updateVerticesForLOD();
|
||||
updateIndices();
|
||||
switch (_terrain->_crackFixedType)
|
||||
{
|
||||
case CrackFixedType::SKIRT:
|
||||
|
||||
updateIndicesLODSkirt();
|
||||
break;
|
||||
case CrackFixedType::INCREASE_LOWER:
|
||||
updateVerticesForLOD();
|
||||
updateIndicesLOD();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,vbo[1]);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,_chunkIndices.indices);
|
||||
GL::enableVertexAttribs(GL::VERTEX_ATTRIB_FLAG_POSITION | GL::VERTEX_ATTRIB_FLAG_TEX_COORD| GL::VERTEX_ATTRIB_FLAG_NORMAL);
|
||||
unsigned long offset = 0;
|
||||
//position
|
||||
|
@ -583,27 +700,65 @@ void Terrain::Chunk::bindAndDraw()
|
|||
glEnableVertexAttribArray(_terrain->_normalLocation);
|
||||
//normal
|
||||
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_NORMAL,3,GL_FLOAT,GL_FALSE,sizeof(TerrainVertexData),(GLvoid *)offset);
|
||||
glDrawElements(GL_TRIANGLES, (GLsizei)_lod[_currentLod].indices.size(), GL_UNSIGNED_SHORT, 0);
|
||||
|
||||
glDrawElements(GL_TRIANGLES, (GLsizei)_chunkIndices.size, GL_UNSIGNED_SHORT, 0);
|
||||
CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1, _chunkIndices.size);
|
||||
#if (CC_TARGET_PLATFORM == CC_PLATFORM_MAC) || (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32) || (CC_TARGET_PLATFORM == CC_PLATFORM_LINUX)
|
||||
glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Terrain::Chunk::generate(int imgWidth,int imageHei,int m,int n,const unsigned char * data)
|
||||
void Terrain::Chunk::generate(int imgWidth, int imageHei, int m, int n, const unsigned char * data)
|
||||
{
|
||||
pos_y = m;
|
||||
pos_x = n;
|
||||
for(int i=_size.height*m;i<=_size.height*(m+1);i++)
|
||||
switch (_terrain->_crackFixedType)
|
||||
{
|
||||
if(i>=imageHei) break;
|
||||
for(int j=_size.width*n;j<=_size.width*(n+1);j++)
|
||||
case CrackFixedType::SKIRT:
|
||||
{
|
||||
if(j>=imgWidth)break;
|
||||
auto v =_terrain->vertices[i*imgWidth + j];
|
||||
vertices.push_back (v);
|
||||
for(int i=_size.height*m;i<=_size.height*(m+1);i++)
|
||||
{
|
||||
if(i>=imageHei) break;
|
||||
for(int j=_size.width*n;j<=_size.width*(n+1);j++)
|
||||
{
|
||||
if(j>=imgWidth)break;
|
||||
auto v =_terrain->vertices[i*imgWidth + j];
|
||||
vertices.push_back (v);
|
||||
}
|
||||
}
|
||||
// add two skirt
|
||||
//#1
|
||||
for(int i =_size.height*m;i<=_size.height*(m+1);i++)
|
||||
{
|
||||
auto v = _terrain->vertices[i*imgWidth +_size.width*(n+1)];
|
||||
v.position.y = -5;
|
||||
vertices.push_back (v);
|
||||
}
|
||||
//#2
|
||||
for(int j =_size.width*n;j<=_size.width*(n+1);j++)
|
||||
{
|
||||
auto v = _terrain->vertices[_size.height*(m+1)*imgWidth + j];
|
||||
v.position.y = -5;
|
||||
vertices.push_back (v);
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
case CrackFixedType::INCREASE_LOWER:
|
||||
{
|
||||
for(int i=_size.height*m;i<=_size.height*(m+1);i++)
|
||||
{
|
||||
if(i>=imageHei) break;
|
||||
for(int j=_size.width*n;j<=_size.width*(n+1);j++)
|
||||
{
|
||||
if(j>=imgWidth)break;
|
||||
auto v =_terrain->vertices[i*imgWidth + j];
|
||||
vertices.push_back (v);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
calculateAABB();
|
||||
finish();
|
||||
}
|
||||
|
@ -622,7 +777,7 @@ Terrain::Chunk::Chunk()
|
|||
}
|
||||
}
|
||||
|
||||
void Terrain::Chunk::updateIndices()
|
||||
void Terrain::Chunk::updateIndicesLOD()
|
||||
{
|
||||
int currentNeighborLOD[4];
|
||||
if(left)
|
||||
|
@ -646,6 +801,12 @@ void Terrain::Chunk::updateIndices()
|
|||
{
|
||||
return;// no need to update
|
||||
}
|
||||
bool isOk;
|
||||
_chunkIndices = _terrain->lookForIndicesLOD(currentNeighborLOD,_currentLod,&isOk);
|
||||
if(isOk)
|
||||
{
|
||||
return;
|
||||
}
|
||||
memcpy(_neighborOldLOD,currentNeighborLOD,sizeof(currentNeighborLOD));
|
||||
_oldLod = _currentLod;
|
||||
int gridY = _size.height;
|
||||
|
@ -796,8 +957,8 @@ void Terrain::Chunk::updateIndices()
|
|||
_lod[_currentLod].indices.push_back(i+step);
|
||||
}
|
||||
}
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo[1]);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(GLushort)*_lod[_currentLod].indices.size(),&_lod[_currentLod].indices[0],GL_STATIC_DRAW);
|
||||
|
||||
_chunkIndices = _terrain->insertIndicesLOD(currentNeighborLOD,_currentLod,&_lod[_currentLod].indices[0],_lod[_currentLod].indices.size());
|
||||
}else{
|
||||
//No lod difference, use simple method
|
||||
_lod[_currentLod].indices.clear();
|
||||
|
@ -816,8 +977,7 @@ void Terrain::Chunk::updateIndices()
|
|||
_lod[_currentLod].indices.push_back (nLocIndex + step * (gridX+1) + step);
|
||||
}
|
||||
}
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,vbo[1]);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(GLushort)*_lod[_currentLod].indices.size(),&_lod[_currentLod].indices[0],GL_STATIC_DRAW);
|
||||
_chunkIndices = _terrain->insertIndicesLOD(currentNeighborLOD,_currentLod,&_lod[_currentLod].indices[0],_lod[_currentLod].indices.size());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -894,7 +1054,65 @@ Terrain::Chunk::~Chunk()
|
|||
// glDeleteBuffers(2,vbo);
|
||||
}
|
||||
|
||||
Terrain::QuadTree::QuadTree(int x,int y,int w,int h,Terrain * terrain)
|
||||
void Terrain::Chunk::updateIndicesLODSkirt()
|
||||
{
|
||||
if(_oldLod == _currentLod) return;
|
||||
_oldLod = _currentLod;
|
||||
bool isOk;
|
||||
_chunkIndices = _terrain->lookForIndicesLODSkrit(_currentLod,&isOk);
|
||||
if(isOk) return;
|
||||
|
||||
int gridY = _size.height;
|
||||
int gridX = _size.width;
|
||||
int step = int(powf(2.0f, float(_currentLod)));
|
||||
|
||||
|
||||
for(int i =0;i<gridY;i+=step)
|
||||
{
|
||||
for(int j = 0;j<gridX;j+=step)
|
||||
{
|
||||
int nLocIndex = i * (gridX+1) + j;
|
||||
_lod[_currentLod].indices.push_back (nLocIndex);
|
||||
_lod[_currentLod].indices.push_back (nLocIndex + step * (gridX+1));
|
||||
_lod[_currentLod].indices.push_back (nLocIndex + step);
|
||||
|
||||
_lod[_currentLod].indices.push_back (nLocIndex + step);
|
||||
_lod[_currentLod].indices.push_back (nLocIndex + step * (gridX+1));
|
||||
_lod[_currentLod].indices.push_back (nLocIndex + step * (gridX+1) + step);
|
||||
}
|
||||
}
|
||||
//add skirt
|
||||
//#1
|
||||
for(int i =0;i<gridY;i+=step)
|
||||
{
|
||||
int nLocIndex = i * (gridX+1) + gridX-step+1;
|
||||
_lod[_currentLod].indices.push_back (nLocIndex);
|
||||
_lod[_currentLod].indices.push_back (nLocIndex + step * (gridX+1));
|
||||
_lod[_currentLod].indices.push_back ((gridY+1) *(gridX+1)+i);
|
||||
|
||||
_lod[_currentLod].indices.push_back ((gridY+1) *(gridX+1)+i);
|
||||
_lod[_currentLod].indices.push_back (nLocIndex + step * (gridX+1));
|
||||
_lod[_currentLod].indices.push_back ((gridY+1) *(gridX+1)+i+step);
|
||||
}
|
||||
|
||||
//#2
|
||||
for(int j =0;j<gridX;j+=step)
|
||||
{
|
||||
int nLocIndex = (gridY-step+1)* (gridX+1) + j;
|
||||
_lod[_currentLod].indices.push_back (nLocIndex);
|
||||
_lod[_currentLod].indices.push_back ((gridX+1)*(gridY+1)+_size.height+1 +j);
|
||||
_lod[_currentLod].indices.push_back (nLocIndex + step);
|
||||
|
||||
_lod[_currentLod].indices.push_back (nLocIndex + step);
|
||||
_lod[_currentLod].indices.push_back ((gridX+1)*(gridY+1)+_size.height+1 +j);
|
||||
_lod[_currentLod].indices.push_back ((gridX+1)*(gridY+1)+_size.height+1 +j+step);
|
||||
}
|
||||
|
||||
|
||||
_chunkIndices = _terrain->insertIndicesLODSkirt(_currentLod,&_lod[_currentLod].indices[0],_lod[_currentLod].indices.size());
|
||||
}
|
||||
|
||||
Terrain::QuadTree::QuadTree(int x, int y, int w, int h, Terrain * terrain)
|
||||
{
|
||||
_terrain = terrain;
|
||||
_needDraw = true;
|
||||
|
@ -962,7 +1180,7 @@ void Terrain::QuadTree::resetNeedDraw(bool value)
|
|||
}
|
||||
}
|
||||
|
||||
void Terrain::QuadTree::cullByCamera(const Camera * camera,const Mat4 & worldTransform)
|
||||
void Terrain::QuadTree::cullByCamera(const Camera * camera, const Mat4 & worldTransform)
|
||||
{
|
||||
if(_terrain->_isTerrainModelMatrixChanged)
|
||||
{
|
||||
|
@ -998,7 +1216,7 @@ void Terrain::QuadTree::updateAABB(const Mat4 & worldTransform)
|
|||
}
|
||||
}
|
||||
|
||||
Terrain::TerrainData::TerrainData(const char * heightMapsrc ,const char * textureSrc,const Size & chunksize,float height,float scale)
|
||||
Terrain::TerrainData::TerrainData(const char * heightMapsrc , const char * textureSrc, const Size & chunksize, float height, float scale)
|
||||
{
|
||||
this->heightMapSrc = heightMapsrc;
|
||||
this->detailMaps[0].detailMapSrc = textureSrc;
|
||||
|
@ -1008,7 +1226,7 @@ Terrain::TerrainData::TerrainData(const char * heightMapsrc ,const char * textur
|
|||
this->mapScale = scale;
|
||||
}
|
||||
|
||||
Terrain::TerrainData::TerrainData(const char * heightMapsrc ,const char * alphamap,const DetailMap& detail1,const DetailMap& detail2,const DetailMap& detail3,const DetailMap& detail4,const Size & chunksize,float height,float scale)
|
||||
Terrain::TerrainData::TerrainData(const char * heightMapsrc, const char * alphamap, const DetailMap& detail1, const DetailMap& detail2, const DetailMap& detail3, const DetailMap& detail4, const Size & chunksize, float height, float scale)
|
||||
{
|
||||
this->heightMapSrc = heightMapsrc;
|
||||
this->alphaMapSrc = const_cast<char *>(alphamap);
|
||||
|
@ -1022,7 +1240,7 @@ Terrain::TerrainData::TerrainData(const char * heightMapsrc ,const char * alpham
|
|||
_detailMapAmount = 4;
|
||||
}
|
||||
|
||||
Terrain::TerrainData::TerrainData(const char* heightMapsrc ,const char * alphamap,const DetailMap& detail1,const DetailMap& detail2,const DetailMap& detail3,const Size & chunksize /*= Size(32,32)*/,float height /*= 2*/,float scale /*= 0.1*/)
|
||||
Terrain::TerrainData::TerrainData(const char* heightMapsrc, const char * alphamap, const DetailMap& detail1, const DetailMap& detail2, const DetailMap& detail3, const Size & chunksize /*= Size(32,32)*/, float height /*= 2*/, float scale /*= 0.1*/)
|
||||
{
|
||||
this->heightMapSrc = heightMapsrc;
|
||||
this->alphaMapSrc = const_cast<char *>(alphamap);
|
||||
|
@ -1041,7 +1259,7 @@ Terrain::TerrainData::TerrainData()
|
|||
|
||||
}
|
||||
|
||||
Terrain::DetailMap::DetailMap(const char * detailMapPath , float size /*= 35*/)
|
||||
Terrain::DetailMap::DetailMap(const char * detailMapPath, float size /*= 35*/)
|
||||
{
|
||||
this->detailMapSrc = detailMapPath;
|
||||
this->detailMapSize = size;
|
||||
|
|
|
@ -32,6 +32,12 @@ THE SOFTWARE.
|
|||
#include "3d/CCRay.h"
|
||||
#include <vector>
|
||||
NS_CC_BEGIN
|
||||
|
||||
/**
|
||||
* @addtogroup _3d
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*
|
||||
* the maximum amount of the chunkes
|
||||
**/
|
||||
|
@ -73,9 +79,15 @@ NS_CC_BEGIN
|
|||
* We can use ray-terrain intersection to pick a point of the terrain;
|
||||
* Also we can get an arbitrary point of the terrain's height and normal vector for convenience .
|
||||
**/
|
||||
class CC_DLL Terrain :public Node{
|
||||
class CC_DLL Terrain :public Node
|
||||
{
|
||||
public:
|
||||
|
||||
enum class CrackFixedType{
|
||||
SKIRT,
|
||||
INCREASE_LOWER,
|
||||
};
|
||||
|
||||
/*
|
||||
*DetailMap
|
||||
*this struct maintain a detail map data ,including source file ,detail size.
|
||||
|
@ -84,7 +96,7 @@ public:
|
|||
struct CC_DLL DetailMap{
|
||||
/*Constructors*/
|
||||
DetailMap();
|
||||
DetailMap(const char * detailMapSrc , float size = 35);
|
||||
DetailMap(const char * detailMapSrc, float size = 35);
|
||||
/*detail Image source file path*/
|
||||
std::string detailMapSrc;
|
||||
/*detailMapSize determine how many tiles that Terrain represent*/
|
||||
|
@ -99,9 +111,9 @@ public:
|
|||
{
|
||||
/*Constructors*/
|
||||
TerrainData();
|
||||
TerrainData(const char* heightMapsrc ,const char * textureSrc,const Size & chunksize = Size(32,32),float mapHeight = 2,float mapScale = 0.1);
|
||||
TerrainData(const char* heightMapsrc ,const char * alphamap,const DetailMap& detail1,const DetailMap& detail2,const DetailMap& detail3,const DetailMap& detail4,const Size & chunksize = Size(32,32),float mapHeight = 2,float mapScale = 0.1);
|
||||
TerrainData(const char* heightMapsrc ,const char * alphamap,const DetailMap& detail1,const DetailMap& detail2,const DetailMap& detail3,const Size & chunksize = Size(32,32),float mapHeight = 2,float mapScale = 0.1);
|
||||
TerrainData(const char* heightMapsrc, const char * textureSrc, const Size & chunksize = Size(32,32), float mapHeight = 2, float mapScale = 0.1);
|
||||
TerrainData(const char* heightMapsrc, const char * alphamap, const DetailMap& detail1,const DetailMap& detail2, const DetailMap& detail3, const DetailMap& detail4, const Size & chunksize = Size(32,32), float mapHeight = 2, float mapScale = 0.1);
|
||||
TerrainData(const char* heightMapsrc, const char * alphamap, const DetailMap& detail1,const DetailMap& detail2, const DetailMap& detail3, const Size & chunksize = Size(32,32), float mapHeight = 2, float mapScale = 0.1);
|
||||
/*
|
||||
*deterimine the chunk size,chunk is the minimal subdivision of the Terrain
|
||||
*/
|
||||
|
@ -120,6 +132,24 @@ public:
|
|||
};
|
||||
private:
|
||||
|
||||
struct ChunkIndices
|
||||
{
|
||||
GLuint indices;
|
||||
unsigned short size;
|
||||
};
|
||||
|
||||
struct ChunkLODIndices
|
||||
{
|
||||
int relativeLod[5];
|
||||
ChunkIndices _chunkIndices;
|
||||
};
|
||||
|
||||
|
||||
struct ChunkLODIndicesSkirt
|
||||
{
|
||||
int selfLod;
|
||||
ChunkIndices _chunkIndices;
|
||||
};
|
||||
/*
|
||||
*terrain vertices internal data format
|
||||
**/
|
||||
|
@ -127,7 +157,7 @@ private:
|
|||
{
|
||||
/*constructor*/
|
||||
TerrainVertexData(){};
|
||||
TerrainVertexData(Vec3 v1 ,Tex2F v2)
|
||||
TerrainVertexData(Vec3 v1, Tex2F v2)
|
||||
{
|
||||
position = v1;
|
||||
texcoord = v2;
|
||||
|
@ -154,12 +184,13 @@ private:
|
|||
std::vector<GLushort> indices;
|
||||
};
|
||||
GLuint vbo[2];
|
||||
ChunkIndices _chunkIndices;
|
||||
/*we now have four levels of detail*/
|
||||
LOD _lod[4];
|
||||
/*AABB in local space*/
|
||||
AABB _aabb;
|
||||
/*setup Chunk data*/
|
||||
void generate(int map_width,int map_height,int m,int n,const unsigned char * data);
|
||||
void generate(int map_width, int map_height, int m, int n, const unsigned char * data);
|
||||
/*calculateAABB*/
|
||||
void calculateAABB();
|
||||
/*internal use draw function*/
|
||||
|
@ -169,7 +200,9 @@ private:
|
|||
/*use linear-sample vertices for LOD mesh*/
|
||||
void updateVerticesForLOD();
|
||||
/*updateIndices for every frame*/
|
||||
void updateIndices();
|
||||
void updateIndicesLOD();
|
||||
|
||||
void updateIndicesLODSkirt();
|
||||
|
||||
void calculateSlope();
|
||||
/*current LOD of the chunk*/
|
||||
|
@ -204,10 +237,10 @@ private:
|
|||
**/
|
||||
struct QuadTree
|
||||
{
|
||||
QuadTree(int x,int y,int width,int height,Terrain * terrain);
|
||||
QuadTree(int x, int y, int width, int height, Terrain * terrain);
|
||||
void draw();
|
||||
void resetNeedDraw(bool value);
|
||||
void cullByCamera(const Camera * camera,const Mat4 & worldTransform);
|
||||
void cullByCamera(const Camera * camera, const Mat4 & worldTransform);
|
||||
void updateAABB(const Mat4 & worldTransform);
|
||||
QuadTree * tl;
|
||||
QuadTree * tr;
|
||||
|
@ -232,19 +265,25 @@ public:
|
|||
bool init();
|
||||
void initHeightMap(const char* heightMap);
|
||||
/*create entry*/
|
||||
static Terrain * create(TerrainData ¶meter);
|
||||
static Terrain * create(TerrainData ¶meter, CrackFixedType fixedType = CrackFixedType::INCREASE_LOWER);
|
||||
/*get specified position's height mapping to the terrain*/
|
||||
float getHeight(float x,float z,Vec3 * normal= nullptr);
|
||||
float getHeight(Vec2 pos,Vec3*Normal = nullptr);
|
||||
Vec3 getNormal(int pixel_x,int pixel_y);
|
||||
float getHeight(float x, float z, Vec3 * normal= nullptr);
|
||||
float getHeight(Vec2 pos, Vec3*Normal = nullptr);
|
||||
Vec3 getNormal(int pixel_x, int pixel_y);
|
||||
/*get height from the raw height map*/
|
||||
float getImageHeight(int pixel_x,int pixel_y);
|
||||
float getImageHeight(int pixel_x, int pixel_y);
|
||||
/*Debug Use only, show the wireline instead of the surface. only support desktop platform*/
|
||||
void setDrawWire(bool bool_value);
|
||||
/*Set threshold distance of each LOD level,must equal or gereater than the chunk size*/
|
||||
void setLODDistance(float lod_1,float lod_2,float lod_3);
|
||||
void setLODDistance(float lod_1, float lod_2, float lod_3);
|
||||
/*Switch frustumCulling Flag*/
|
||||
void setIsEnableFrustumCull(bool bool_value);
|
||||
|
||||
/** set the alpha map*/
|
||||
void setAlphaMap(cocos2d::Texture2D * newAlphaMapTexture);
|
||||
/**set the Detail Map */
|
||||
void setDetailMap(unsigned int index, DetailMap detailMap);
|
||||
|
||||
// Overrides, internal use only
|
||||
virtual void draw(cocos2d::Renderer* renderer, const cocos2d::Mat4 &transform, uint32_t flags) override;
|
||||
//Ray-Terrain intersection.
|
||||
|
@ -263,8 +302,19 @@ public:
|
|||
// get the terrain's maximum height.
|
||||
float getMaxHeight();
|
||||
|
||||
//get terrain's AABB
|
||||
//get terrain's AABB
|
||||
AABB getAABB();
|
||||
|
||||
//get the terrain's quad tree which is also the root node
|
||||
QuadTree * getQuadTree();
|
||||
|
||||
ChunkIndices lookForIndicesLODSkrit(int selfLod, bool * result);
|
||||
ChunkIndices lookForIndicesLOD(int neighborLod[4], int selfLod, bool * result);
|
||||
|
||||
ChunkIndices insertIndicesLOD(int neighborLod[4], int selfLod, GLushort * indices, int size);
|
||||
|
||||
ChunkIndices insertIndicesLODSkirt(int selfLod, GLushort * indices, int size);
|
||||
|
||||
protected:
|
||||
|
||||
Terrain();
|
||||
|
@ -277,21 +327,22 @@ protected:
|
|||
//calculate Normal Line for each Vertex
|
||||
void calculateNormal();
|
||||
protected:
|
||||
std::vector <ChunkLODIndices> _chunkLodIndicesSet;
|
||||
std::vector<ChunkLODIndicesSkirt> _chunkLodIndicesSkirtSet;
|
||||
Mat4 _CameraMatrix;
|
||||
bool _isCameraViewChanged;
|
||||
TerrainData _terrainData;
|
||||
bool _isDrawWire;
|
||||
unsigned char * _data;
|
||||
float _lodDistance[3];
|
||||
std::vector<Texture2D *>textures;
|
||||
Texture2D * _detailMapTextures[4];
|
||||
Texture2D * _alphaMap;
|
||||
CustomCommand _customCommand;
|
||||
GLuint vbo[2];
|
||||
QuadTree * quad;
|
||||
int detailSize[4];
|
||||
QuadTree * _quadRoot;
|
||||
Chunk * _chunkesArray[MAX_CHUNKES][MAX_CHUNKES];
|
||||
std::vector<TerrainVertexData> vertices;
|
||||
std::vector<GLushort > indices;
|
||||
std::vector<GLushort> indices;
|
||||
int imageWidth;
|
||||
int imageHeight;
|
||||
Size _chunkSize;
|
||||
|
@ -304,6 +355,11 @@ protected:
|
|||
GLuint _normalLocation;
|
||||
float m_maxHeight;
|
||||
float m_minHeight;
|
||||
CrackFixedType _crackFixedType;
|
||||
};
|
||||
|
||||
// end of actions group
|
||||
/// @}
|
||||
|
||||
NS_CC_END
|
||||
#endif
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
|
||||
|
||||
Vec3 camera_offset(0,45,60);
|
||||
Vec3 camera_offset(0, 45, 60);
|
||||
#define PLAYER_HEIGHT 0
|
||||
static std::function<Layer*()> createFunctions[] =
|
||||
{
|
||||
|
@ -48,10 +48,12 @@ TerrainSimple::TerrainSimple()
|
|||
_camera->setCameraFlag(CameraFlag::USER1);
|
||||
addChild(_camera);
|
||||
|
||||
Terrain::DetailMap r("TerrainTest/dirt.dds"),g("TerrainTest/Grass2.dds"),b("TerrainTest/road.dds"),a("TerrainTest/Grass1.dds");
|
||||
Terrain::DetailMap r("TerrainTest/dirt.dds"),g("TerrainTest/Grass2.dds"),b("TerrainTest/road.dds"),a("TerrainTest/GreenSkin.jpg");
|
||||
|
||||
Terrain::TerrainData data("TerrainTest/heightmap16.jpg","TerrainTest/alphamap.png",r,g,b,a);
|
||||
_terrain = Terrain::create(data);
|
||||
|
||||
_terrain = Terrain::create(data,Terrain::CrackFixedType::SKIRT);
|
||||
_terrain->setLODDistance(1000.2,6.4,9.6);
|
||||
_terrain->setMaxDetailMapAmount(4);
|
||||
addChild(_terrain);
|
||||
_terrain->setCameraMask(2);
|
||||
|
@ -63,7 +65,7 @@ TerrainSimple::TerrainSimple()
|
|||
|
||||
std::string TerrainSimple::title() const
|
||||
{
|
||||
return "Simple Terrain";
|
||||
return "Terrain with skirt";
|
||||
}
|
||||
|
||||
std::string TerrainSimple::subtitle() const
|
||||
|
@ -178,16 +180,15 @@ TerrainWalkThru::TerrainWalkThru()
|
|||
_camera->setCameraFlag(CameraFlag::USER1);
|
||||
addChild(_camera);
|
||||
|
||||
Terrain::DetailMap r("TerrainTest/dirt.dds"),g("TerrainTest/Grass2.dds",10),b("TerrainTest/road.dds"),a("TerrainTest/Grass1.dds",20);
|
||||
Terrain::DetailMap r("TerrainTest/dirt.dds"),g("TerrainTest/Grass2.dds",10),b("TerrainTest/road.dds"),a("TerrainTest/GreenSkin.jpg",20);
|
||||
|
||||
Terrain::TerrainData data("TerrainTest/heightmap16.jpg","TerrainTest/alphamap.png",r,g,b,a);
|
||||
Terrain::TerrainData data("TerrainTest/heightmap16.jpg","TerrainTest/alphamap.png",r,g,b,a,Size(32,32),40.0f,2);
|
||||
_terrain = Terrain::create(data);
|
||||
_terrain->setScale(20);
|
||||
_terrain->setMaxDetailMapAmount(4);
|
||||
_terrain->setCameraMask(2);
|
||||
_terrain->setDrawWire(false);
|
||||
|
||||
_terrain->setLODDistance(150,220,300);
|
||||
_terrain->setLODDistance(64,128,192);
|
||||
_player = Player::create("Sprite3DTest/girl.c3b",_camera,_terrain);
|
||||
_player->setCameraMask(2);
|
||||
_player->setScale(0.08);
|
||||
|
|
|
@ -51,7 +51,7 @@ protected:
|
|||
class Player : public Sprite3D
|
||||
{
|
||||
public:
|
||||
static Player * create(const char * file,Camera * cam,Terrain * terrain);
|
||||
static Player * create(const char * file, Camera * cam, Terrain * terrain);
|
||||
virtual bool isDone() const;
|
||||
virtual void update(float dt);
|
||||
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 8.0 KiB |
Loading…
Reference in New Issue