2015-04-03 13:49:07 +08:00
|
|
|
/****************************************************************************
|
2018-01-29 16:25:32 +08:00
|
|
|
Copyright (c) 2015-2016 Chukong Technologies Inc.
|
|
|
|
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
2015-04-03 13:49:07 +08:00
|
|
|
|
|
|
|
http://www.cocos2d-x.org
|
|
|
|
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
of this software and associated documentation files (the "Software"), to deal
|
|
|
|
in the Software without restriction, including without limitation the rights
|
|
|
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
|
copies of the Software, and to permit persons to whom the Software is
|
|
|
|
furnished to do so, subject to the following conditions:
|
|
|
|
|
|
|
|
The above copyright notice and this permission notice shall be included in
|
|
|
|
all copies or substantial portions of the Software.
|
|
|
|
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
|
|
THE SOFTWARE.
|
|
|
|
****************************************************************************/
|
|
|
|
|
2016-03-20 21:53:44 +08:00
|
|
|
#include "3d/CCTerrain.h"
|
2015-04-03 13:49:07 +08:00
|
|
|
|
2015-01-15 11:45:06 +08:00
|
|
|
USING_NS_CC;
|
2015-04-03 13:49:07 +08:00
|
|
|
#include <stdlib.h>
|
2015-06-24 15:49:09 +08:00
|
|
|
#include <float.h>
|
|
|
|
#include <set>
|
2015-01-15 11:45:06 +08:00
|
|
|
#include "renderer/CCRenderer.h"
|
2019-02-27 17:16:25 +08:00
|
|
|
#include "renderer/ccShaders.h"
|
|
|
|
#include "renderer/backend/Device.h"
|
|
|
|
#include "renderer/backend/Program.h"
|
|
|
|
#include "renderer/backend/Buffer.h"
|
2015-03-30 18:25:22 +08:00
|
|
|
#include "base/CCDirector.h"
|
2015-04-08 19:11:46 +08:00
|
|
|
#include "base/CCEventType.h"
|
2015-06-24 15:49:09 +08:00
|
|
|
#include "2d/CCCamera.h"
|
2016-03-21 21:04:06 +08:00
|
|
|
#include "platform/CCImage.h"
|
2019-02-27 17:16:25 +08:00
|
|
|
#include "3d/CC3DProgramInfo.h"
|
2015-01-23 18:09:54 +08:00
|
|
|
|
2015-01-20 10:34:30 +08:00
|
|
|
NS_CC_BEGIN
|
2015-04-03 13:49:07 +08:00
|
|
|
|
|
|
|
// check a number is power of two.
|
|
|
|
static bool isPOT(int number)
|
|
|
|
{
|
2016-03-21 21:04:06 +08:00
|
|
|
bool flag = false;
|
2019-02-27 17:16:25 +08:00
|
|
|
if ((number > 0) && (number&(number - 1)) == 0)
|
2016-03-21 21:04:06 +08:00
|
|
|
flag = true;
|
|
|
|
return flag;
|
2015-04-03 13:49:07 +08:00
|
|
|
}
|
|
|
|
|
2015-03-30 18:25:22 +08:00
|
|
|
Terrain * Terrain::create(TerrainData ¶meter, CrackFixedType fixedType)
|
2015-01-15 11:45:06 +08:00
|
|
|
{
|
2015-01-30 15:46:39 +08:00
|
|
|
Terrain * terrain = new (std::nothrow)Terrain();
|
2015-07-31 18:35:47 +08:00
|
|
|
if (terrain->initWithTerrainData(parameter, fixedType))
|
2015-07-30 17:17:57 +08:00
|
|
|
{
|
|
|
|
terrain->autorelease();
|
|
|
|
return terrain;
|
|
|
|
}
|
|
|
|
CC_SAFE_DELETE(terrain);
|
|
|
|
return terrain;
|
|
|
|
}
|
2015-07-31 18:35:47 +08:00
|
|
|
bool Terrain::initWithTerrainData(TerrainData ¶meter, CrackFixedType fixedType)
|
2015-07-30 17:17:57 +08:00
|
|
|
{
|
|
|
|
this->setSkirtHeightRatio(parameter._skirtHeightRatio);
|
|
|
|
this->_terrainData = parameter;
|
|
|
|
this->_crackFixedType = fixedType;
|
|
|
|
this->_isCameraViewChanged = true;
|
2015-01-15 11:45:06 +08:00
|
|
|
//chunksize
|
2015-07-30 17:17:57 +08:00
|
|
|
this->_chunkSize = parameter._chunkSize;
|
|
|
|
bool initResult = true;
|
2015-04-01 18:24:05 +08:00
|
|
|
|
2015-04-03 13:49:07 +08:00
|
|
|
//init heightmap
|
2016-02-03 23:12:37 +08:00
|
|
|
initResult &= this->initHeightMap(parameter._heightMapSrc);
|
2015-04-03 13:49:07 +08:00
|
|
|
//init textures alpha map,detail Maps
|
2015-07-30 17:17:57 +08:00
|
|
|
initResult &= this->initTextures();
|
|
|
|
initResult &= this->initProperties();
|
2016-03-21 21:04:06 +08:00
|
|
|
|
2015-07-30 17:17:57 +08:00
|
|
|
return initResult;
|
2015-01-15 11:45:06 +08:00
|
|
|
}
|
|
|
|
|
2015-07-29 14:32:36 +08:00
|
|
|
void cocos2d::Terrain::setLightMap(const std::string& fileName)
|
2015-07-29 13:24:12 +08:00
|
|
|
{
|
2015-08-03 10:27:57 +08:00
|
|
|
CC_SAFE_RELEASE(_lightMap);
|
2015-07-29 13:24:12 +08:00
|
|
|
auto image = new (std::nothrow)Image();
|
|
|
|
image->initWithImageFile(fileName);
|
|
|
|
_lightMap = new (std::nothrow)Texture2D();
|
|
|
|
_lightMap->initWithImage(image);
|
|
|
|
|
|
|
|
Texture2D::TexParams tRepeatParams;//set texture parameters
|
|
|
|
tRepeatParams.magFilter = tRepeatParams.minFilter = GL_LINEAR;
|
|
|
|
tRepeatParams.wrapS = GL_REPEAT;
|
|
|
|
tRepeatParams.wrapT = GL_REPEAT;
|
|
|
|
_lightMap->setTexParameters(tRepeatParams);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2015-07-29 14:32:36 +08:00
|
|
|
void cocos2d::Terrain::setLightDir(const Vec3& lightDir)
|
2015-07-29 13:24:12 +08:00
|
|
|
{
|
|
|
|
_lightDir = lightDir;
|
|
|
|
}
|
|
|
|
|
2015-04-03 13:49:07 +08:00
|
|
|
bool Terrain::initProperties()
|
2015-01-15 11:45:06 +08:00
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
_programState = new backend::ProgramState(CC3D_terrain_vert, CC3D_terrain_frag);
|
2015-04-07 18:47:19 +08:00
|
|
|
|
2019-02-27 17:16:25 +08:00
|
|
|
_stateBlock.depthWrite = true;
|
|
|
|
_stateBlock.depthTest = true;
|
|
|
|
_stateBlock.cullFace = backend::CullMode::FRONT;
|
2015-05-20 08:18:44 +08:00
|
|
|
|
2019-02-27 17:16:25 +08:00
|
|
|
_beforeDraw.func = CC_CALLBACK_0(Terrain::onBeforeDraw, this);
|
|
|
|
_afterDraw.func = CC_CALLBACK_0(Terrain::onAfterDraw, this);
|
2015-05-20 08:18:44 +08:00
|
|
|
|
2015-01-15 11:45:06 +08:00
|
|
|
setDrawWire(false);
|
|
|
|
setIsEnableFrustumCull(true);
|
2019-02-27 17:16:25 +08:00
|
|
|
setAnchorPoint(Vec2(0, 0));
|
2015-01-15 11:45:06 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-01-20 10:34:30 +08:00
|
|
|
void Terrain::draw(cocos2d::Renderer *renderer, const cocos2d::Mat4 &transform, uint32_t flags)
|
2015-01-15 11:45:06 +08:00
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
_beforeDraw.init(-1); //to ensure callbackcommand run before others
|
|
|
|
_afterDraw.init(100000.0);
|
|
|
|
|
|
|
|
renderer->addCommand(&_beforeDraw);
|
2019-02-15 14:30:10 +08:00
|
|
|
|
2015-05-26 17:51:26 +08:00
|
|
|
auto modelMatrix = getNodeToWorldTransform();
|
2019-02-27 17:16:25 +08:00
|
|
|
if (memcmp(&modelMatrix, &_terrainModelMatrix, sizeof(Mat4)) != 0)
|
2015-05-26 17:51:26 +08:00
|
|
|
{
|
|
|
|
_terrainModelMatrix = modelMatrix;
|
|
|
|
_quadRoot->preCalculateAABB(_terrainModelMatrix);
|
|
|
|
}
|
2016-03-21 21:04:06 +08:00
|
|
|
|
2019-02-27 17:16:25 +08:00
|
|
|
//TODO arnold
|
|
|
|
//#if (CC_TARGET_PLATFORM == CC_PLATFORM_MAC) || (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32) || (CC_TARGET_PLATFORM == CC_PLATFORM_LINUX)
|
|
|
|
// if(_isDrawWire)
|
|
|
|
// {
|
|
|
|
// glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
|
|
|
|
// }else
|
|
|
|
// {
|
|
|
|
// glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
|
|
|
|
//
|
|
|
|
// }
|
|
|
|
//#endif
|
|
|
|
|
2019-03-06 17:03:16 +08:00
|
|
|
auto &projectionMatrix = Director::getInstance()->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);
|
|
|
|
auto finalMatrix = projectionMatrix * transform;
|
2019-02-27 17:16:25 +08:00
|
|
|
_programState->setUniform(_mvpMatrixLocation, &finalMatrix.m, sizeof(finalMatrix.m));
|
|
|
|
|
|
|
|
_programState->setUniform(_lightDirLocation, &_lightDir, sizeof(_lightDir));
|
|
|
|
if (!_alphaMap)
|
|
|
|
{
|
|
|
|
_programState->setTexture(_detailMapLocation[0], 0, _detailMapTextures[0]->getBackendTexture());
|
|
|
|
int hasAlphaMap = 0;
|
|
|
|
_programState->setUniform(_alphaIsHasAlphaMapLocation, &hasAlphaMap, sizeof(hasAlphaMap));
|
2018-09-11 14:39:30 +08:00
|
|
|
}
|
|
|
|
else
|
2015-01-15 11:45:06 +08:00
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
float detailMapSize[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
|
|
|
|
for (int i = 0; i < _maxDetailMapValue; ++i)
|
2015-01-15 11:45:06 +08:00
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
_programState->setTexture(_detailMapLocation[i], i, _detailMapTextures[i]->getBackendTexture());
|
|
|
|
detailMapSize[i] = _terrainData._detailMaps[i]._detailMapSize;
|
2015-01-15 11:45:06 +08:00
|
|
|
}
|
2019-02-27 17:16:25 +08:00
|
|
|
_programState->setUniform(_detailMapSizeLocation, detailMapSize, sizeof(detailMapSize));
|
2015-01-30 15:46:39 +08:00
|
|
|
|
2019-02-27 17:16:25 +08:00
|
|
|
int hasAlphaMap = 1;
|
|
|
|
_programState->setUniform(_alphaIsHasAlphaMapLocation, &hasAlphaMap, sizeof(hasAlphaMap));
|
|
|
|
_programState->setTexture(_alphaMapLocation, 4, _alphaMap->getBackendTexture());
|
2015-01-15 11:45:06 +08:00
|
|
|
}
|
2015-07-29 13:24:12 +08:00
|
|
|
if (_lightMap)
|
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
int hasLightMap = 1;
|
|
|
|
_programState->setUniform(_lightMapCheckLocation, &hasLightMap, sizeof(hasLightMap));
|
|
|
|
_programState->setTexture(_lightMapLocation, 5, _lightMap->getBackendTexture());
|
|
|
|
}
|
|
|
|
else
|
2015-07-29 13:24:12 +08:00
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
int hasLightMap = 0;
|
|
|
|
_programState->setUniform(_lightMapCheckLocation, &hasLightMap, sizeof(hasLightMap));
|
2015-07-29 13:24:12 +08:00
|
|
|
}
|
2015-01-15 11:45:06 +08:00
|
|
|
auto camera = Camera::getVisitingCamera();
|
2015-03-03 14:14:50 +08:00
|
|
|
|
2019-02-27 17:16:25 +08:00
|
|
|
if (memcmp(&_CameraMatrix, &camera->getViewMatrix(), sizeof(Mat4)) != 0)
|
2015-03-03 14:14:50 +08:00
|
|
|
{
|
|
|
|
_isCameraViewChanged = true;
|
|
|
|
_CameraMatrix = camera->getViewMatrix();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-02-27 17:16:25 +08:00
|
|
|
if (_isCameraViewChanged)
|
2015-03-03 14:14:50 +08:00
|
|
|
{
|
2015-06-17 15:58:17 +08:00
|
|
|
auto m = camera->getNodeToWorldTransform();
|
2015-03-03 14:14:50 +08:00
|
|
|
//set lod
|
2015-06-16 17:46:21 +08:00
|
|
|
setChunksLOD(Vec3(m.m[12], m.m[13], m.m[14]));
|
2015-03-03 14:14:50 +08:00
|
|
|
}
|
|
|
|
|
2019-02-27 17:16:25 +08:00
|
|
|
if (_isCameraViewChanged)
|
2015-03-03 14:14:50 +08:00
|
|
|
{
|
2016-03-21 21:04:06 +08:00
|
|
|
_quadRoot->resetNeedDraw(true);//reset it
|
2015-03-03 14:14:50 +08:00
|
|
|
//camera frustum culling
|
2015-07-29 13:24:12 +08:00
|
|
|
if (_isEnableFrustumCull)
|
|
|
|
{
|
|
|
|
_quadRoot->cullByCamera(camera, _terrainModelMatrix);
|
|
|
|
}
|
2015-03-03 14:14:50 +08:00
|
|
|
}
|
2015-03-27 13:43:09 +08:00
|
|
|
_quadRoot->draw();
|
2019-02-27 17:16:25 +08:00
|
|
|
if (_isCameraViewChanged)
|
2015-03-03 14:14:50 +08:00
|
|
|
{
|
|
|
|
_isCameraViewChanged = false;
|
|
|
|
}
|
2015-05-20 08:18:44 +08:00
|
|
|
|
2019-02-27 17:16:25 +08:00
|
|
|
|
|
|
|
//TODO arnold
|
|
|
|
//glActiveTexture(GL_TEXTURE0); //
|
|
|
|
//#if (CC_TARGET_PLATFORM == CC_PLATFORM_MAC) || (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32) || (CC_TARGET_PLATFORM == CC_PLATFORM_LINUX)
|
|
|
|
// if (_isDrawWire)//reset state.
|
|
|
|
// {
|
|
|
|
// glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
|
|
|
// }
|
|
|
|
//#endif
|
|
|
|
|
|
|
|
|
|
|
|
renderer->addCommand(&_afterDraw);
|
2015-01-30 15:46:39 +08:00
|
|
|
}
|
2015-01-15 11:45:06 +08:00
|
|
|
|
2015-11-12 18:08:29 +08:00
|
|
|
bool Terrain::initHeightMap(const std::string& heightMap)
|
2015-01-15 11:45:06 +08:00
|
|
|
{
|
2015-12-16 14:02:55 +08:00
|
|
|
_heightMapImage = new (std::nothrow) Image();
|
2015-01-23 18:09:54 +08:00
|
|
|
_heightMapImage->initWithImageFile(heightMap);
|
|
|
|
_data = _heightMapImage->getData();
|
2019-02-27 17:16:25 +08:00
|
|
|
_imageWidth = _heightMapImage->getWidth();
|
|
|
|
_imageHeight = _heightMapImage->getHeight();
|
2015-03-27 10:12:24 +08:00
|
|
|
|
2015-04-03 13:49:07 +08:00
|
|
|
//only the image size is the Powers Of Two(POT) or POT+1
|
2019-02-27 17:16:25 +08:00
|
|
|
if ((isPOT(_imageWidth) && isPOT(_imageHeight)) || (isPOT(_imageWidth - 1) && isPOT(_imageHeight - 1)))
|
2015-01-15 11:45:06 +08:00
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
int chunk_amount_y = _imageHeight / _chunkSize.height;
|
|
|
|
int chunk_amount_x = _imageWidth / _chunkSize.width;
|
2015-04-03 13:49:07 +08:00
|
|
|
loadVertices();
|
|
|
|
calculateNormal();
|
|
|
|
memset(_chunkesArray, 0, sizeof(_chunkesArray));
|
|
|
|
|
2019-02-27 17:16:25 +08:00
|
|
|
for (int m = 0; m < chunk_amount_y; m++)
|
2015-01-15 11:45:06 +08:00
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
for (int n = 0; n < chunk_amount_x; n++)
|
2015-04-03 13:49:07 +08:00
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
_chunkesArray[m][n] = new (std::nothrow) Chunk(this);
|
2015-04-03 13:49:07 +08:00
|
|
|
_chunkesArray[m][n]->_size = _chunkSize;
|
2019-02-27 17:16:25 +08:00
|
|
|
_chunkesArray[m][n]->generate(_imageWidth, _imageHeight, m, n, _data);
|
2015-04-03 13:49:07 +08:00
|
|
|
}
|
2015-01-15 11:45:06 +08:00
|
|
|
}
|
2015-03-27 10:12:24 +08:00
|
|
|
|
2015-04-03 13:49:07 +08:00
|
|
|
//calculate the neighbor
|
2019-02-27 17:16:25 +08:00
|
|
|
for (int m = 0; m < chunk_amount_y; m++)
|
2015-01-15 11:45:06 +08:00
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
for (int n = 0; n < chunk_amount_x; n++)
|
2015-04-03 13:49:07 +08:00
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
if (n - 1 >= 0) _chunkesArray[m][n]->_left = _chunkesArray[m][n - 1];
|
|
|
|
if (n + 1 < chunk_amount_x) _chunkesArray[m][n]->_right = _chunkesArray[m][n + 1];
|
|
|
|
if (m - 1 >= 0) _chunkesArray[m][n]->_back = _chunkesArray[m - 1][n];
|
|
|
|
if (m + 1 < chunk_amount_y) _chunkesArray[m][n]->_front = _chunkesArray[m + 1][n];
|
2015-04-03 13:49:07 +08:00
|
|
|
}
|
2015-01-15 11:45:06 +08:00
|
|
|
}
|
2019-02-27 17:16:25 +08:00
|
|
|
_quadRoot = new (std::nothrow) QuadTree(0, 0, _imageWidth, _imageHeight, this);
|
|
|
|
setLODDistance(_chunkSize.width, 2 * _chunkSize.width, 3 * _chunkSize.width);
|
2015-04-03 13:49:07 +08:00
|
|
|
return true;
|
2019-02-27 17:16:25 +08:00
|
|
|
}
|
|
|
|
else
|
2015-04-03 13:49:07 +08:00
|
|
|
{
|
|
|
|
CCLOG("warning: the height map size is not POT or POT + 1");
|
|
|
|
return false;
|
2015-01-15 11:45:06 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-20 10:34:30 +08:00
|
|
|
Terrain::Terrain()
|
2019-02-27 17:16:25 +08:00
|
|
|
: _alphaMap(nullptr)
|
|
|
|
, _lightMap(nullptr)
|
|
|
|
, _lightDir(-1.f, -1.f, 0.f)
|
2018-09-10 15:04:35 +08:00
|
|
|
#if CC_ENABLE_CACHE_TEXTURE_DATA
|
2019-02-27 17:16:25 +08:00
|
|
|
, _backToForegroundListener(nullptr)
|
2018-09-10 15:04:35 +08:00
|
|
|
#endif
|
2015-01-15 11:45:06 +08:00
|
|
|
{
|
2018-09-10 15:04:35 +08:00
|
|
|
#if CC_ENABLE_CACHE_TEXTURE_DATA
|
|
|
|
_backToForegroundListener = EventListenerCustom::create(EVENT_RENDERER_RECREATED,
|
2015-04-08 19:11:46 +08:00
|
|
|
[this](EventCustom*)
|
|
|
|
{
|
|
|
|
reload();
|
|
|
|
}
|
|
|
|
);
|
2015-04-10 14:22:07 +08:00
|
|
|
Director::getInstance()->getEventDispatcher()->addEventListenerWithFixedPriority(_backToForegroundListener, 1);
|
|
|
|
#endif
|
2015-01-15 11:45:06 +08:00
|
|
|
}
|
|
|
|
|
2016-05-17 12:17:56 +08:00
|
|
|
void Terrain::setChunksLOD(const Vec3& cameraPos)
|
2015-01-15 11:45:06 +08:00
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
int chunk_amount_y = _imageHeight / _chunkSize.height;
|
|
|
|
int chunk_amount_x = _imageWidth / _chunkSize.width;
|
|
|
|
for (int m = 0; m < chunk_amount_y; m++)
|
|
|
|
for (int n = 0; n < chunk_amount_x; n++)
|
2015-01-15 11:45:06 +08:00
|
|
|
{
|
2015-03-03 14:14:50 +08:00
|
|
|
AABB aabb = _chunkesArray[m][n]->_parent->_worldSpaceAABB;
|
2015-01-15 11:45:06 +08:00
|
|
|
auto center = aabb.getCenter();
|
2015-06-16 17:46:21 +08:00
|
|
|
float dist = Vec2(center.x, center.z).distance(Vec2(cameraPos.x, cameraPos.z));
|
2015-01-15 11:45:06 +08:00
|
|
|
_chunkesArray[m][n]->_currentLod = 3;
|
2019-02-27 17:16:25 +08:00
|
|
|
for (int i = 0; i < 3; ++i)
|
2015-01-15 11:45:06 +08:00
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
if (dist <= _lodDistance[i])
|
2015-01-23 18:09:54 +08:00
|
|
|
{
|
2015-01-15 11:45:06 +08:00
|
|
|
_chunkesArray[m][n]->_currentLod = i;
|
|
|
|
break;
|
2015-01-23 18:09:54 +08:00
|
|
|
}
|
2015-01-15 11:45:06 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-27 18:19:44 +08:00
|
|
|
float Terrain::getHeight(float x, float z, Vec3 * normal) const
|
2015-01-15 11:45:06 +08:00
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
Vec2 pos(x, z);
|
2015-01-15 11:45:06 +08:00
|
|
|
|
|
|
|
//top-left
|
2019-02-27 17:16:25 +08:00
|
|
|
Vec2 tl(-1 * _terrainData._mapScale*_imageWidth / 2, -1 * _terrainData._mapScale*_imageHeight / 2);
|
2017-02-09 10:55:24 +08:00
|
|
|
auto mulResult = getNodeToWorldTransform() * Vec4(tl.x, 0.0f, tl.y, 1.0f);
|
|
|
|
tl.set(mulResult.x, mulResult.z);
|
2015-01-15 11:45:06 +08:00
|
|
|
|
|
|
|
Vec2 to_tl = pos - tl;
|
|
|
|
|
|
|
|
//real size
|
2019-02-27 17:16:25 +08:00
|
|
|
Vec2 size(_imageWidth*_terrainData._mapScale, _imageHeight*_terrainData._mapScale);
|
2017-02-09 10:55:24 +08:00
|
|
|
mulResult = getNodeToWorldTransform() * Vec4(size.x, 0.0f, size.y, 0.0f);
|
|
|
|
size.set(mulResult.x, mulResult.z);
|
2015-01-15 11:45:06 +08:00
|
|
|
|
2019-02-27 17:16:25 +08:00
|
|
|
float width_ratio = to_tl.x / size.x;
|
|
|
|
float height_ratio = to_tl.y / size.y;
|
2015-01-15 11:45:06 +08:00
|
|
|
|
2015-04-02 14:04:31 +08:00
|
|
|
float image_x = width_ratio * _imageWidth;
|
|
|
|
float image_y = height_ratio * _imageHeight;
|
2019-02-27 17:16:25 +08:00
|
|
|
float u = image_x - (int)image_x;
|
|
|
|
float v = image_y - (int)image_y;
|
2015-01-15 11:45:06 +08:00
|
|
|
float i = (int)image_x;
|
|
|
|
float j = (int)image_y;
|
2015-01-27 15:18:59 +08:00
|
|
|
|
|
|
|
|
2019-02-27 17:16:25 +08:00
|
|
|
if (image_x >= _imageWidth - 1 || image_y >= _imageHeight - 1 || image_x < 0 || image_y < 0)
|
2015-01-15 11:45:06 +08:00
|
|
|
{
|
2015-05-22 09:07:57 +08:00
|
|
|
if (normal)
|
|
|
|
{
|
|
|
|
normal->setZero();
|
|
|
|
}
|
2015-01-30 15:46:39 +08:00
|
|
|
return 0;
|
2019-02-27 17:16:25 +08:00
|
|
|
}
|
|
|
|
else
|
2015-01-15 11:45:06 +08:00
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
float a = getImageHeight(i, j)*getScaleY();
|
|
|
|
float b = getImageHeight(i, j + 1)*getScaleY();
|
|
|
|
float c = getImageHeight(i + 1, j)*getScaleY();
|
|
|
|
float d = getImageHeight(i + 1, j + 1)*getScaleY();
|
|
|
|
if (normal)
|
2015-01-27 15:18:59 +08:00
|
|
|
{
|
|
|
|
normal->x = c - b;
|
|
|
|
normal->y = 2;
|
|
|
|
normal->z = d - a;
|
|
|
|
normal->normalize();
|
|
|
|
//(*normal) = (1-u)*(1-v)*getNormal(i,j)+ (1-u)*v*getNormal(i,j+1) + u*(1-v)*getNormal(i+1,j)+ u*v*getNormal(i+1,j+1);
|
|
|
|
}
|
2019-02-27 17:16:25 +08:00
|
|
|
float result = (1 - u)*(1 - v)*getImageHeight(i, j)*getScaleY() + (1 - u)*v*getImageHeight(i, j + 1)*getScaleY() + u * (1 - v)*getImageHeight(i + 1, j)*getScaleY() + u * v*getImageHeight(i + 1, j + 1)*getScaleY();
|
2016-10-20 18:17:37 +08:00
|
|
|
return result;
|
2015-01-15 11:45:06 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-17 12:17:56 +08:00
|
|
|
float Terrain::getHeight(const Vec2& pos, Vec3* normal) const
|
2015-01-15 11:45:06 +08:00
|
|
|
{
|
2016-05-17 12:17:56 +08:00
|
|
|
return getHeight(pos.x, pos.y, normal);
|
2015-01-15 11:45:06 +08:00
|
|
|
}
|
|
|
|
|
2019-02-27 17:16:25 +08:00
|
|
|
float Terrain::getImageHeight(int pixel_x, int pixel_y) const
|
2015-01-15 11:45:06 +08:00
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
int byte_stride = 1;
|
2019-01-30 09:35:17 +08:00
|
|
|
switch (_heightMapImage->getPixelFormat())
|
2015-01-23 18:09:54 +08:00
|
|
|
{
|
|
|
|
case Texture2D::PixelFormat::BGRA8888:
|
|
|
|
byte_stride = 4;
|
|
|
|
break;
|
|
|
|
case Texture2D::PixelFormat::RGB888:
|
2019-02-27 17:16:25 +08:00
|
|
|
byte_stride = 3;
|
2015-01-23 18:09:54 +08:00
|
|
|
break;
|
|
|
|
case Texture2D::PixelFormat::I8:
|
2019-02-27 17:16:25 +08:00
|
|
|
byte_stride = 1;
|
2015-01-23 18:09:54 +08:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2019-02-27 17:16:25 +08:00
|
|
|
return _data[(pixel_y*_imageWidth + pixel_x)*byte_stride] * 1.0 / 255 * _terrainData._mapHeight - 0.5*_terrainData._mapHeight;
|
2015-01-15 11:45:06 +08:00
|
|
|
}
|
|
|
|
|
2015-01-20 10:34:30 +08:00
|
|
|
void Terrain::loadVertices()
|
2015-01-15 11:45:06 +08:00
|
|
|
{
|
2015-04-02 14:04:31 +08:00
|
|
|
_maxHeight = -99999;
|
|
|
|
_minHeight = 99999;
|
2019-02-27 17:16:25 +08:00
|
|
|
for (int i = 0; i < _imageHeight; ++i)
|
2015-01-15 11:45:06 +08:00
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
for (int j = 0; j < _imageWidth; j++)
|
2015-01-15 11:45:06 +08:00
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
float height = getImageHeight(j, i);
|
2015-01-15 11:45:06 +08:00
|
|
|
TerrainVertexData v;
|
2019-02-27 17:16:25 +08:00
|
|
|
v._position = Vec3(j*_terrainData._mapScale - _imageWidth / 2 * _terrainData._mapScale, //x
|
2015-03-27 11:46:02 +08:00
|
|
|
height, //y
|
2019-02-27 17:16:25 +08:00
|
|
|
i*_terrainData._mapScale - _imageHeight / 2 * _terrainData._mapScale);//z
|
|
|
|
v._texcoord = Tex2F(j*1.0 / _imageWidth, i*1.0 / _imageHeight);
|
|
|
|
_vertices.push_back(v);
|
2015-03-27 11:46:02 +08:00
|
|
|
|
|
|
|
//update the min & max height;
|
2019-02-27 17:16:25 +08:00
|
|
|
if (height > _maxHeight) _maxHeight = height;
|
|
|
|
if (height < _minHeight) _minHeight = height;
|
2015-01-15 11:45:06 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-20 10:34:30 +08:00
|
|
|
void Terrain::calculateNormal()
|
2015-01-15 11:45:06 +08:00
|
|
|
{
|
2015-04-02 14:04:31 +08:00
|
|
|
_indices.clear();
|
2015-01-15 11:45:06 +08:00
|
|
|
//we generate whole terrain indices(global indices) for correct normal calculate
|
2019-02-27 17:16:25 +08:00
|
|
|
for (int i = 0; i < _imageHeight - 1; i += 1)
|
2015-01-15 11:45:06 +08:00
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
for (int j = 0; j < _imageWidth - 1; j += 1)
|
2016-03-21 21:04:06 +08:00
|
|
|
{
|
2015-01-15 11:45:06 +08:00
|
|
|
|
2015-04-02 14:04:31 +08:00
|
|
|
int nLocIndex = i * _imageWidth + j;
|
2019-02-27 17:16:25 +08:00
|
|
|
_indices.push_back(nLocIndex);
|
|
|
|
_indices.push_back(nLocIndex + _imageWidth);
|
|
|
|
_indices.push_back(nLocIndex + 1);
|
2015-01-15 11:45:06 +08:00
|
|
|
|
2019-02-27 17:16:25 +08:00
|
|
|
_indices.push_back(nLocIndex + 1);
|
|
|
|
_indices.push_back(nLocIndex + _imageWidth);
|
|
|
|
_indices.push_back(nLocIndex + _imageWidth + 1);
|
2015-01-15 11:45:06 +08:00
|
|
|
}
|
|
|
|
}
|
2017-01-19 09:41:57 +08:00
|
|
|
for (size_t i = 0, size = _indices.size(); i < size; i += 3) {
|
2015-04-02 14:04:31 +08:00
|
|
|
unsigned int Index0 = _indices[i];
|
|
|
|
unsigned int Index1 = _indices[i + 1];
|
|
|
|
unsigned int Index2 = _indices[i + 2];
|
2015-04-08 15:17:05 +08:00
|
|
|
Vec3 v1 = _vertices[Index1]._position - _vertices[Index0]._position;
|
|
|
|
Vec3 v2 = _vertices[Index2]._position - _vertices[Index0]._position;
|
2015-01-15 11:45:06 +08:00
|
|
|
Vec3 Normal;
|
2019-02-27 17:16:25 +08:00
|
|
|
Vec3::cross(v1, v2, &Normal);
|
2015-01-15 11:45:06 +08:00
|
|
|
Normal.normalize();
|
2015-04-08 15:17:05 +08:00
|
|
|
_vertices[Index0]._normal += Normal;
|
|
|
|
_vertices[Index1]._normal += Normal;
|
|
|
|
_vertices[Index2]._normal += Normal;
|
2015-01-15 11:45:06 +08:00
|
|
|
}
|
|
|
|
|
2017-01-19 09:41:57 +08:00
|
|
|
for (auto &vertex : _vertices) {
|
|
|
|
vertex._normal.normalize();
|
2015-01-15 11:45:06 +08:00
|
|
|
}
|
|
|
|
//global indices no need at all
|
2015-04-02 14:04:31 +08:00
|
|
|
_indices.clear();
|
2015-01-15 11:45:06 +08:00
|
|
|
}
|
|
|
|
|
2015-01-20 10:34:30 +08:00
|
|
|
void Terrain::setDrawWire(bool bool_value)
|
2015-01-15 11:45:06 +08:00
|
|
|
{
|
|
|
|
_isDrawWire = bool_value;
|
|
|
|
}
|
|
|
|
|
2015-03-30 18:25:22 +08:00
|
|
|
void Terrain::setLODDistance(float lod_1, float lod_2, float lod_3)
|
2015-01-15 11:45:06 +08:00
|
|
|
{
|
|
|
|
_lodDistance[0] = lod_1;
|
|
|
|
_lodDistance[1] = lod_2;
|
|
|
|
_lodDistance[2] = lod_3;
|
|
|
|
}
|
|
|
|
|
2015-01-20 10:34:30 +08:00
|
|
|
void Terrain::setIsEnableFrustumCull(bool bool_value)
|
2015-01-15 11:45:06 +08:00
|
|
|
{
|
|
|
|
_isEnableFrustumCull = bool_value;
|
|
|
|
}
|
|
|
|
|
2015-01-23 18:09:54 +08:00
|
|
|
Terrain::~Terrain()
|
|
|
|
{
|
2015-08-03 10:27:57 +08:00
|
|
|
CC_SAFE_RELEASE(_alphaMap);
|
|
|
|
CC_SAFE_RELEASE(_lightMap);
|
|
|
|
CC_SAFE_RELEASE(_heightMapImage);
|
2019-02-27 17:16:25 +08:00
|
|
|
CC_SAFE_RELEASE_NULL(_programState);
|
2015-04-01 18:24:05 +08:00
|
|
|
delete _quadRoot;
|
2019-02-27 17:16:25 +08:00
|
|
|
for (int i = 0; i < 4; ++i)
|
2015-04-01 18:24:05 +08:00
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
if (_detailMapTextures[i])
|
2015-04-01 18:24:05 +08:00
|
|
|
{
|
|
|
|
_detailMapTextures[i]->release();
|
|
|
|
}
|
|
|
|
}
|
2019-02-27 17:16:25 +08:00
|
|
|
for (int i = 0; i < MAX_CHUNKES; ++i)
|
2015-01-23 18:14:44 +08:00
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
for (int j = 0; j < MAX_CHUNKES; j++)
|
2015-01-23 18:14:44 +08:00
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
if (_chunkesArray[i][j])
|
2015-01-30 15:46:39 +08:00
|
|
|
{
|
|
|
|
delete _chunkesArray[i][j];
|
|
|
|
}
|
2015-01-23 18:14:44 +08:00
|
|
|
}
|
|
|
|
}
|
2015-04-01 18:24:05 +08:00
|
|
|
|
2018-09-10 15:04:35 +08:00
|
|
|
#if CC_ENABLE_CACHE_TEXTURE_DATA
|
2015-04-08 19:11:46 +08:00
|
|
|
Director::getInstance()->getEventDispatcher()->removeEventListener(_backToForegroundListener);
|
|
|
|
#endif
|
2015-01-23 18:09:54 +08:00
|
|
|
}
|
|
|
|
|
2015-05-27 18:19:44 +08:00
|
|
|
cocos2d::Vec3 Terrain::getNormal(int pixel_x, int pixel_y) const
|
2015-01-27 15:18:59 +08:00
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
float a = getImageHeight(pixel_x, pixel_y)*getScaleY();
|
|
|
|
float b = getImageHeight(pixel_x, pixel_y + 1)*getScaleY();
|
|
|
|
float c = getImageHeight(pixel_x + 1, pixel_y)*getScaleY();
|
|
|
|
float d = getImageHeight(pixel_x + 1, pixel_y + 1)*getScaleY();
|
2015-01-27 15:18:59 +08:00
|
|
|
Vec3 normal;
|
|
|
|
normal.x = c - b;
|
|
|
|
normal.y = 2;
|
|
|
|
normal.z = d - a;
|
|
|
|
normal.normalize();
|
|
|
|
return normal;
|
|
|
|
}
|
|
|
|
|
2015-05-27 18:19:44 +08:00
|
|
|
cocos2d::Vec3 Terrain::getIntersectionPoint(const Ray & ray) const
|
2015-01-29 18:06:00 +08:00
|
|
|
{
|
2015-06-23 14:27:19 +08:00
|
|
|
Vec3 collisionPoint;
|
|
|
|
if (getIntersectionPoint(ray, collisionPoint))
|
|
|
|
{
|
|
|
|
return collisionPoint;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
return Vec3(0, 0, 0);
|
2015-06-23 14:27:19 +08:00
|
|
|
}
|
2015-01-29 18:06:00 +08:00
|
|
|
}
|
|
|
|
|
2015-08-07 17:36:35 +08:00
|
|
|
bool Terrain::getIntersectionPoint(const Ray & ray_, Vec3 & intersectionPoint) const
|
2015-05-22 09:07:57 +08:00
|
|
|
{
|
2016-10-27 15:10:24 +08:00
|
|
|
// convert ray from world space to local space
|
2015-08-07 17:36:35 +08:00
|
|
|
Ray ray(ray_);
|
|
|
|
getWorldToNodeTransform().transformPoint(&(ray._origin));
|
|
|
|
|
2015-06-23 14:27:19 +08:00
|
|
|
std::set<Chunk *> closeList;
|
2019-02-27 17:16:25 +08:00
|
|
|
Vec2 start = Vec2(ray_._origin.x, ray_._origin.z);
|
|
|
|
Vec2 dir = Vec2(ray._direction.x, ray._direction.z);
|
2015-06-23 14:27:19 +08:00
|
|
|
start = convertToTerrainSpace(start);
|
2019-02-27 17:16:25 +08:00
|
|
|
start.x /= (_terrainData._chunkSize.width + 1);
|
|
|
|
start.y /= (_terrainData._chunkSize.height + 1);
|
2015-06-23 14:27:19 +08:00
|
|
|
Vec2 delta = dir.getNormalized();
|
2015-06-23 16:11:00 +08:00
|
|
|
auto width = float(_imageWidth) / (_terrainData._chunkSize.width + 1);
|
|
|
|
auto height = float(_imageHeight) / (_terrainData._chunkSize.height + 1);
|
2015-06-24 15:49:09 +08:00
|
|
|
bool hasIntersect = false;
|
|
|
|
float intersectionDist = FLT_MAX;
|
|
|
|
Vec3 tmpIntersectionPoint;
|
2019-02-27 17:16:25 +08:00
|
|
|
for (;;)
|
2015-06-23 14:27:19 +08:00
|
|
|
{
|
2015-06-24 10:49:18 +08:00
|
|
|
int x1 = floorf(start.x);
|
|
|
|
int x2 = ceilf(start.x);
|
|
|
|
int y1 = floorf(start.y);
|
|
|
|
int y2 = ceilf(start.y);
|
|
|
|
for (int x = x1; x <= x2; x++) {
|
|
|
|
for (int y = y1; y <= y2; y++) {
|
|
|
|
auto chunk = getChunkByIndex(x, y);
|
|
|
|
if (chunk)
|
2015-06-23 14:27:19 +08:00
|
|
|
{
|
2015-06-24 10:49:18 +08:00
|
|
|
if (closeList.find(chunk) == closeList.end())
|
2015-06-23 14:27:19 +08:00
|
|
|
{
|
2017-01-16 11:20:07 +08:00
|
|
|
if (chunk->getIntersectPointWithRay(ray, tmpIntersectionPoint))
|
2015-06-24 10:49:18 +08:00
|
|
|
{
|
2015-06-24 15:49:09 +08:00
|
|
|
float dist = (ray._origin - tmpIntersectionPoint).length();
|
|
|
|
if (intersectionDist > dist)
|
|
|
|
{
|
|
|
|
hasIntersect = true;
|
|
|
|
intersectionDist = dist;
|
|
|
|
intersectionPoint = tmpIntersectionPoint;
|
|
|
|
}
|
2015-06-24 10:49:18 +08:00
|
|
|
}
|
|
|
|
closeList.insert(chunk);
|
2015-06-23 14:27:19 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-02-27 17:16:25 +08:00
|
|
|
if ((delta.x > 0 && start.x > width) || (delta.x < 0 && start.x < 0))
|
2015-06-23 16:11:00 +08:00
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if ((delta.y > 0 && start.y > height) || (delta.y < 0 && start.y < 0))
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
2015-06-24 10:49:18 +08:00
|
|
|
start.x += delta.x;
|
|
|
|
start.y += delta.y;
|
2015-05-22 09:07:57 +08:00
|
|
|
}
|
2015-06-24 15:49:09 +08:00
|
|
|
return hasIntersect;
|
2015-05-22 09:07:57 +08:00
|
|
|
}
|
|
|
|
|
2015-01-30 15:46:39 +08:00
|
|
|
void Terrain::setMaxDetailMapAmount(int max_value)
|
|
|
|
{
|
|
|
|
_maxDetailMapValue = max_value;
|
|
|
|
}
|
|
|
|
|
2016-05-17 12:17:56 +08:00
|
|
|
cocos2d::Vec2 Terrain::convertToTerrainSpace(const Vec2& worldSpaceXZ) const
|
2015-03-27 10:12:24 +08:00
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
Vec2 pos(worldSpaceXZ.x, worldSpaceXZ.y);
|
2015-03-27 10:12:24 +08:00
|
|
|
|
|
|
|
//top-left
|
2019-02-27 17:16:25 +08:00
|
|
|
Vec2 tl(-1 * _terrainData._mapScale*_imageWidth / 2, -1 * _terrainData._mapScale*_imageHeight / 2);
|
|
|
|
auto result = getNodeToWorldTransform()*Vec4(tl.x, 0.0f, tl.y, 1.0f);
|
2015-04-20 01:40:52 +08:00
|
|
|
tl.set(result.x, result.z);
|
2015-03-27 10:12:24 +08:00
|
|
|
|
|
|
|
Vec2 to_tl = pos - tl;
|
|
|
|
|
|
|
|
//real size
|
2019-02-27 17:16:25 +08:00
|
|
|
Vec2 size(_imageWidth*_terrainData._mapScale, _imageHeight*_terrainData._mapScale);
|
|
|
|
result = getNodeToWorldTransform()*Vec4(size.x, 0.0f, size.y, 0.0f);
|
2015-04-20 01:40:52 +08:00
|
|
|
size.set(result.x, result.z);
|
2015-03-27 10:12:24 +08:00
|
|
|
|
2019-02-27 17:16:25 +08:00
|
|
|
float width_ratio = to_tl.x / size.x;
|
|
|
|
float height_ratio = to_tl.y / size.y;
|
2015-03-27 10:12:24 +08:00
|
|
|
|
2015-04-02 14:04:31 +08:00
|
|
|
float image_x = width_ratio * _imageWidth;
|
|
|
|
float image_y = height_ratio * _imageHeight;
|
2019-02-27 17:16:25 +08:00
|
|
|
return Vec2(image_x, image_y);
|
2015-03-27 10:12:24 +08:00
|
|
|
}
|
|
|
|
|
2015-11-12 18:08:29 +08:00
|
|
|
void Terrain::resetHeightMap(const std::string& heightMap)
|
2015-03-27 10:12:24 +08:00
|
|
|
{
|
|
|
|
_heightMapImage->release();
|
2015-04-02 14:04:31 +08:00
|
|
|
_vertices.clear();
|
2015-03-27 10:12:24 +08:00
|
|
|
free(_data);
|
2019-02-27 17:16:25 +08:00
|
|
|
for (int i = 0; i < MAX_CHUNKES; ++i)
|
2015-03-27 10:12:24 +08:00
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
for (int j = 0; j < MAX_CHUNKES; j++)
|
2015-03-27 10:12:24 +08:00
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
if (_chunkesArray[i][j])
|
2015-03-27 10:12:24 +08:00
|
|
|
{
|
|
|
|
delete _chunkesArray[i][j];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-03-27 13:43:09 +08:00
|
|
|
delete _quadRoot;
|
2015-03-27 10:12:24 +08:00
|
|
|
initHeightMap(heightMap);
|
|
|
|
}
|
|
|
|
|
2015-03-27 11:46:02 +08:00
|
|
|
float Terrain::getMinHeight()
|
|
|
|
{
|
2015-04-02 14:04:31 +08:00
|
|
|
return _minHeight;
|
2015-03-27 11:46:02 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
float Terrain::getMaxHeight()
|
|
|
|
{
|
2015-04-02 14:04:31 +08:00
|
|
|
return _maxHeight;
|
2015-03-27 11:46:02 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
cocos2d::AABB Terrain::getAABB()
|
|
|
|
{
|
2015-03-27 13:43:09 +08:00
|
|
|
return _quadRoot->_worldSpaceAABB;
|
|
|
|
}
|
|
|
|
|
|
|
|
Terrain::QuadTree * Terrain::getQuadTree()
|
|
|
|
{
|
|
|
|
return _quadRoot;
|
2015-03-27 11:46:02 +08:00
|
|
|
}
|
|
|
|
|
2015-05-08 15:49:33 +08:00
|
|
|
|
|
|
|
std::vector<float> Terrain::getHeightData() const
|
|
|
|
{
|
|
|
|
std::vector<float> data;
|
|
|
|
data.resize(_imageWidth * _imageHeight);
|
2016-10-27 15:10:24 +08:00
|
|
|
for (int i = 0; i < _imageHeight; ++i) {
|
2015-05-08 15:49:33 +08:00
|
|
|
for (int j = 0; j < _imageWidth; j++) {
|
|
|
|
int idx = i * _imageWidth + j;
|
|
|
|
data[idx] = (_vertices[idx]._position.y);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return data;
|
|
|
|
}
|
|
|
|
|
2015-06-23 14:27:19 +08:00
|
|
|
Terrain::Chunk * cocos2d::Terrain::getChunkByIndex(int x, int y) const
|
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
if (x < 0 || y < 0 || x >= MAX_CHUNKES || y >= MAX_CHUNKES) return nullptr;
|
2015-06-23 14:27:19 +08:00
|
|
|
return _chunkesArray[y][x];
|
|
|
|
}
|
|
|
|
|
2015-03-30 18:25:22 +08:00
|
|
|
void Terrain::setAlphaMap(cocos2d::Texture2D * newAlphaMapTexture)
|
|
|
|
{
|
2015-08-03 10:27:57 +08:00
|
|
|
CC_SAFE_RETAIN(newAlphaMapTexture);
|
|
|
|
CC_SAFE_RELEASE(_alphaMap);
|
2015-03-30 18:25:22 +08:00
|
|
|
_alphaMap = newAlphaMapTexture;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Terrain::setDetailMap(unsigned int index, DetailMap detailMap)
|
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
if (index > 4)
|
2015-03-30 18:25:22 +08:00
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
CCLOG("invalid DetailMap index %d\n", index);
|
2015-03-30 18:25:22 +08:00
|
|
|
}
|
2015-04-08 15:17:05 +08:00
|
|
|
_terrainData._detailMaps[index] = detailMap;
|
2019-02-27 17:16:25 +08:00
|
|
|
if (_detailMapTextures[index])
|
2015-03-30 18:25:22 +08:00
|
|
|
{
|
|
|
|
|
|
|
|
_detailMapTextures[index]->release();
|
|
|
|
}
|
|
|
|
_detailMapTextures[index] = new (std::nothrow)Texture2D();
|
|
|
|
auto textImage = new (std::nothrow)Image();
|
2015-04-08 15:17:05 +08:00
|
|
|
textImage->initWithImageFile(detailMap._detailMapSrc);
|
2015-03-30 18:25:22 +08:00
|
|
|
_detailMapTextures[index]->initWithImage(textImage);
|
2015-04-07 18:47:19 +08:00
|
|
|
delete textImage;
|
2015-03-30 18:25:22 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
Terrain::ChunkIndices Terrain::lookForIndicesLOD(int neighborLod[4], int selfLod, bool * result)
|
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
(*result) = false;
|
2015-03-30 18:25:22 +08:00
|
|
|
ChunkIndices tmp;
|
2019-02-27 17:16:25 +08:00
|
|
|
tmp._indexBuffer = nullptr;
|
2015-04-08 15:17:05 +08:00
|
|
|
tmp._size = 0;
|
2019-02-27 17:16:25 +08:00
|
|
|
if (_chunkLodIndicesSet.empty())
|
2015-03-30 18:25:22 +08:00
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
(*result) = false;
|
2015-03-30 18:25:22 +08:00
|
|
|
return tmp;
|
2019-02-27 17:16:25 +08:00
|
|
|
}
|
|
|
|
else
|
2015-03-30 18:25:22 +08:00
|
|
|
{
|
|
|
|
int test[5];
|
2019-02-27 17:16:25 +08:00
|
|
|
memcpy(test, neighborLod, sizeof(int[4]));
|
2015-03-30 18:25:22 +08:00
|
|
|
test[4] = selfLod;
|
2019-02-27 17:16:25 +08:00
|
|
|
for (size_t i = 0, size = _chunkLodIndicesSet.size(); i < size; ++i)
|
2015-03-30 18:25:22 +08:00
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
if (memcmp(test, _chunkLodIndicesSet[i]._relativeLod, sizeof(test)) == 0)
|
2015-03-30 18:25:22 +08:00
|
|
|
{
|
|
|
|
(*result) = true;
|
|
|
|
return _chunkLodIndicesSet[i]._chunkIndices;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-02-27 17:16:25 +08:00
|
|
|
(*result) = false;
|
2015-03-30 18:25:22 +08:00
|
|
|
return tmp;
|
|
|
|
}
|
|
|
|
|
2019-02-27 17:16:25 +08:00
|
|
|
Terrain::ChunkIndices Terrain::insertIndicesLOD(int neighborLod[4], int selfLod, GLushort * indices, int size)
|
2015-03-30 18:25:22 +08:00
|
|
|
{
|
|
|
|
ChunkLODIndices lodIndices;
|
2019-02-27 17:16:25 +08:00
|
|
|
memcpy(lodIndices._relativeLod, neighborLod, sizeof(int[4]));
|
2015-04-08 15:17:05 +08:00
|
|
|
lodIndices._relativeLod[4] = selfLod;
|
|
|
|
lodIndices._chunkIndices._size = size;
|
2019-02-27 17:16:25 +08:00
|
|
|
|
|
|
|
auto buffer = backend::Device::getInstance()->newBuffer(sizeof(uint16_t) * size, backend::BufferType::INDEX, backend::BufferUsage::STATIC);
|
|
|
|
buffer->updateData(indices, sizeof(uint16_t) * size);
|
|
|
|
|
|
|
|
CC_SAFE_RELEASE_NULL(lodIndices._chunkIndices._indexBuffer);
|
|
|
|
lodIndices._chunkIndices._indexBuffer = buffer;
|
2015-03-30 18:25:22 +08:00
|
|
|
this->_chunkLodIndicesSet.push_back(lodIndices);
|
|
|
|
return lodIndices._chunkIndices;
|
|
|
|
}
|
|
|
|
|
|
|
|
Terrain::ChunkIndices Terrain::lookForIndicesLODSkrit(int selfLod, bool * result)
|
|
|
|
{
|
|
|
|
ChunkIndices badResult;
|
2019-02-27 17:16:25 +08:00
|
|
|
badResult._indexBuffer = nullptr;
|
2015-04-08 15:17:05 +08:00
|
|
|
badResult._size = 0;
|
2019-02-27 17:16:25 +08:00
|
|
|
if (this->_chunkLodIndicesSkirtSet.empty())
|
2015-03-30 18:25:22 +08:00
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
(*result) = false;
|
|
|
|
return badResult;
|
2015-03-30 18:25:22 +08:00
|
|
|
}
|
2019-02-27 17:16:25 +08:00
|
|
|
for (size_t i = 0, size = _chunkLodIndicesSkirtSet.size(); i < size; ++i)
|
2015-03-30 18:25:22 +08:00
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
if (_chunkLodIndicesSkirtSet[i]._selfLod == selfLod)
|
2015-03-30 18:25:22 +08:00
|
|
|
{
|
|
|
|
(*result) = true;
|
|
|
|
return _chunkLodIndicesSkirtSet[i]._chunkIndices;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
(*result) = false;
|
|
|
|
return badResult;
|
|
|
|
}
|
|
|
|
|
|
|
|
Terrain::ChunkIndices Terrain::insertIndicesLODSkirt(int selfLod, GLushort * indices, int size)
|
|
|
|
{
|
|
|
|
ChunkLODIndicesSkirt skirtIndices;
|
2015-04-08 15:17:05 +08:00
|
|
|
skirtIndices._selfLod = selfLod;
|
|
|
|
skirtIndices._chunkIndices._size = size;
|
2019-02-27 17:16:25 +08:00
|
|
|
|
|
|
|
auto buffer = backend::Device::getInstance()->newBuffer(sizeof(uint16_t) * size, backend::BufferType::INDEX, backend::BufferUsage::STATIC);
|
|
|
|
buffer->updateData(indices, sizeof(GLushort)*size);
|
|
|
|
|
|
|
|
CC_SAFE_RELEASE_NULL(skirtIndices._chunkIndices._indexBuffer);
|
|
|
|
skirtIndices._chunkIndices._indexBuffer = buffer;
|
2015-03-30 18:25:22 +08:00
|
|
|
this->_chunkLodIndicesSkirtSet.push_back(skirtIndices);
|
|
|
|
return skirtIndices._chunkIndices;
|
2015-03-27 11:46:02 +08:00
|
|
|
}
|
|
|
|
|
2015-04-01 18:24:05 +08:00
|
|
|
void Terrain::setSkirtHeightRatio(float ratio)
|
|
|
|
{
|
|
|
|
_skirtRatio = ratio;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Terrain::onEnter()
|
|
|
|
{
|
2015-07-28 16:07:14 +08:00
|
|
|
#if CC_ENABLE_SCRIPT_BINDING
|
|
|
|
if (_scriptType == kScriptTypeJavascript)
|
|
|
|
{
|
2015-07-28 18:24:03 +08:00
|
|
|
if (ScriptEngineManager::sendNodeEventToJSExtended(this, kNodeOnEnter))
|
2015-07-28 16:07:14 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif
|
2016-03-21 21:04:06 +08:00
|
|
|
|
2015-04-01 18:24:05 +08:00
|
|
|
Node::onEnter();
|
|
|
|
_terrainModelMatrix = getNodeToWorldTransform();
|
|
|
|
_quadRoot->preCalculateAABB(_terrainModelMatrix);
|
2015-04-08 10:10:05 +08:00
|
|
|
cacheUniformAttribLocation();
|
2015-04-01 18:24:05 +08:00
|
|
|
}
|
|
|
|
|
2015-04-08 10:10:05 +08:00
|
|
|
void Terrain::cacheUniformAttribLocation()
|
2015-04-01 18:24:05 +08:00
|
|
|
{
|
2015-04-07 18:47:19 +08:00
|
|
|
|
2019-02-27 17:16:25 +08:00
|
|
|
_vertexLayout.setAtrribute("a_position", 0, backend::VertexFormat::FLOAT3, 0, false);
|
|
|
|
_vertexLayout.setAtrribute("a_texCoord", 1, backend::VertexFormat::FLOAT2, offsetof(TerrainVertexData, _texcoord), false);
|
|
|
|
_vertexLayout.setAtrribute("a_normal", 2, backend::VertexFormat::FLOAT3, offsetof(TerrainVertexData, _normal), false);
|
|
|
|
_vertexLayout.setLayout(sizeof(TerrainVertexData), backend::VertexStepMode::VERTEX);
|
|
|
|
|
|
|
|
_alphaMapLocation.reset();
|
|
|
|
for (int i = 0; i < 4; ++i)
|
2015-04-03 13:49:07 +08:00
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
_detailMapLocation[i].reset();
|
2015-04-03 13:49:07 +08:00
|
|
|
}
|
2019-02-27 17:16:25 +08:00
|
|
|
_detailMapSizeLocation.reset();
|
|
|
|
|
|
|
|
_alphaIsHasAlphaMapLocation = _programState->getUniformLocation("u_has_alpha");
|
|
|
|
_lightMapCheckLocation = _programState->getUniformLocation("u_has_light_map");
|
|
|
|
if (!_alphaMap)
|
2015-04-01 18:24:05 +08:00
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
_detailMapLocation[0] = _programState->getUniformLocation("u_texture0");
|
|
|
|
}
|
|
|
|
else
|
2015-04-01 18:24:05 +08:00
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
for (int i = 0; i < _maxDetailMapValue; ++i)
|
2015-04-01 18:24:05 +08:00
|
|
|
{
|
|
|
|
char str[20];
|
2019-02-27 17:16:25 +08:00
|
|
|
sprintf(str, "u_texture%d", i);
|
|
|
|
_detailMapLocation[i] = _programState->getUniformLocation(str);
|
2015-04-01 18:24:05 +08:00
|
|
|
}
|
2019-02-27 17:16:25 +08:00
|
|
|
|
|
|
|
_detailMapSizeLocation = _programState->getUniformLocation("u_detailSize"); //float[4]
|
|
|
|
|
|
|
|
_alphaMapLocation = _programState->getUniformLocation("u_alphaMap");
|
2015-04-01 18:24:05 +08:00
|
|
|
}
|
2019-02-27 17:16:25 +08:00
|
|
|
_lightMapLocation = _programState->getUniformLocation("u_lightMap");
|
|
|
|
_lightDirLocation = _programState->getUniformLocation("u_lightDir");
|
|
|
|
_mvpMatrixLocation = _programState->getUniformLocation("u_MVPMatrix");
|
2015-04-01 18:24:05 +08:00
|
|
|
}
|
|
|
|
|
2015-04-03 13:49:07 +08:00
|
|
|
bool Terrain::initTextures()
|
|
|
|
{
|
2016-10-27 15:10:24 +08:00
|
|
|
for (int i = 0; i < 4; ++i)
|
2015-07-29 13:24:12 +08:00
|
|
|
{
|
|
|
|
_detailMapTextures[i] = nullptr;
|
|
|
|
}
|
|
|
|
|
2015-04-03 13:49:07 +08:00
|
|
|
Texture2D::TexParams texParam;
|
|
|
|
texParam.wrapS = GL_REPEAT;
|
|
|
|
texParam.wrapT = GL_REPEAT;
|
2019-02-27 17:16:25 +08:00
|
|
|
if (_terrainData._alphaMapSrc.empty())
|
2015-04-03 13:49:07 +08:00
|
|
|
{
|
|
|
|
auto textImage = new (std::nothrow)Image();
|
2015-04-08 15:17:05 +08:00
|
|
|
textImage->initWithImageFile(_terrainData._detailMaps[0]._detailMapSrc);
|
2015-04-03 13:49:07 +08:00
|
|
|
auto texture = new (std::nothrow)Texture2D();
|
|
|
|
texture->initWithImage(textImage);
|
|
|
|
texture->generateMipmap();
|
|
|
|
_detailMapTextures[0] = texture;
|
|
|
|
texParam.minFilter = GL_LINEAR_MIPMAP_LINEAR;
|
|
|
|
texParam.magFilter = GL_LINEAR;
|
|
|
|
texture->setTexParameters(texParam);
|
|
|
|
delete textImage;
|
2019-02-27 17:16:25 +08:00
|
|
|
}
|
|
|
|
else
|
2015-04-03 13:49:07 +08:00
|
|
|
{
|
|
|
|
//alpha map
|
2016-03-21 21:04:06 +08:00
|
|
|
auto image = new (std::nothrow)Image();
|
2015-04-08 15:17:05 +08:00
|
|
|
image->initWithImageFile(_terrainData._alphaMapSrc);
|
2015-04-03 13:49:07 +08:00
|
|
|
_alphaMap = new (std::nothrow)Texture2D();
|
|
|
|
_alphaMap->initWithImage(image);
|
|
|
|
texParam.wrapS = GL_CLAMP_TO_EDGE;
|
|
|
|
texParam.wrapT = GL_CLAMP_TO_EDGE;
|
|
|
|
texParam.minFilter = GL_LINEAR;
|
|
|
|
texParam.magFilter = GL_LINEAR;
|
|
|
|
_alphaMap->setTexParameters(texParam);
|
|
|
|
delete image;
|
|
|
|
|
2019-02-27 17:16:25 +08:00
|
|
|
for (int i = 0; i < _terrainData._detailMapAmount; ++i)
|
2015-04-03 13:49:07 +08:00
|
|
|
{
|
|
|
|
auto textImage = new (std::nothrow)Image();
|
2015-04-08 15:17:05 +08:00
|
|
|
textImage->initWithImageFile(_terrainData._detailMaps[i]._detailMapSrc);
|
2015-04-03 13:49:07 +08:00
|
|
|
auto texture = new (std::nothrow)Texture2D();
|
|
|
|
texture->initWithImage(textImage);
|
|
|
|
delete textImage;
|
|
|
|
texture->generateMipmap();
|
|
|
|
_detailMapTextures[i] = texture;
|
|
|
|
|
|
|
|
texParam.wrapS = GL_REPEAT;
|
|
|
|
texParam.wrapT = GL_REPEAT;
|
|
|
|
texParam.minFilter = GL_LINEAR_MIPMAP_LINEAR;
|
|
|
|
texParam.magFilter = GL_LINEAR;
|
|
|
|
texture->setTexParameters(texParam);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
setMaxDetailMapAmount(_terrainData._detailMapAmount);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-04-08 19:11:46 +08:00
|
|
|
void Terrain::reload()
|
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
int chunk_amount_y = _imageHeight / _chunkSize.height;
|
|
|
|
int chunk_amount_x = _imageWidth / _chunkSize.width;
|
2015-04-10 14:22:07 +08:00
|
|
|
|
2019-02-27 17:16:25 +08:00
|
|
|
for (int m = 0; m < chunk_amount_y; m++)
|
2015-04-10 14:22:07 +08:00
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
for (int n = 0; n < chunk_amount_x; n++)
|
2015-04-10 14:22:07 +08:00
|
|
|
{
|
|
|
|
_chunkesArray[m][n]->finish();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-08 19:11:46 +08:00
|
|
|
initTextures();
|
|
|
|
_chunkLodIndicesSet.clear();
|
|
|
|
_chunkLodIndicesSkirtSet.clear();
|
|
|
|
}
|
|
|
|
|
2015-01-20 10:34:30 +08:00
|
|
|
void Terrain::Chunk::finish()
|
2015-01-15 11:45:06 +08:00
|
|
|
{
|
2015-09-09 11:37:41 +08:00
|
|
|
//generate two VBO ,the first for vertices, we just setup datas once ,won't changed at all
|
2016-03-21 21:04:06 +08:00
|
|
|
//the second vbo for the indices, because we use level of detail technique to each chunk, so we will modified frequently
|
2015-01-15 11:45:06 +08:00
|
|
|
|
2019-02-27 17:16:25 +08:00
|
|
|
CC_SAFE_RELEASE_NULL(_buffer);
|
|
|
|
_buffer = backend::Device::getInstance()->newBuffer(sizeof(TerrainVertexData) * _originalVertices.size(), backend::BufferType::VERTEX, backend::BufferUsage::DYNAMIC);
|
2015-01-15 11:45:06 +08:00
|
|
|
|
2019-02-27 17:16:25 +08:00
|
|
|
_buffer->updateData(&_originalVertices[0], sizeof(TerrainVertexData)*_originalVertices.size());
|
2015-01-15 11:45:06 +08:00
|
|
|
|
|
|
|
calculateSlope();
|
2015-01-15 15:54:12 +08:00
|
|
|
|
2019-02-27 17:16:25 +08:00
|
|
|
for (int i = 0; i < 4; ++i)
|
2015-01-15 15:54:12 +08:00
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
int step = 1 << _currentLod;
|
2016-03-21 21:04:06 +08:00
|
|
|
//reserve the indices size, the first part is the core part of the chunk, the second part & third part is for fix crack
|
2019-02-27 17:16:25 +08:00
|
|
|
int indicesAmount = (_terrain->_chunkSize.width / step + 1)*(_terrain->_chunkSize.height / step + 1) * 6 + (_terrain->_chunkSize.height / step) * 6
|
|
|
|
+ (_terrain->_chunkSize.width / step) * 6;
|
2015-04-08 15:17:05 +08:00
|
|
|
_lod[i]._indices.reserve(indicesAmount);
|
2015-01-15 15:54:12 +08:00
|
|
|
}
|
2015-04-10 14:22:07 +08:00
|
|
|
_oldLod = -1;
|
2015-01-15 11:45:06 +08:00
|
|
|
}
|
|
|
|
|
2015-01-20 10:34:30 +08:00
|
|
|
void Terrain::Chunk::bindAndDraw()
|
2015-01-15 11:45:06 +08:00
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
if (_terrain->_isCameraViewChanged || _oldLod < 0)
|
2015-03-03 14:14:50 +08:00
|
|
|
{
|
2015-03-30 18:25:22 +08:00
|
|
|
switch (_terrain->_crackFixedType)
|
|
|
|
{
|
|
|
|
case CrackFixedType::SKIRT:
|
|
|
|
|
|
|
|
updateIndicesLODSkirt();
|
|
|
|
break;
|
|
|
|
case CrackFixedType::INCREASE_LOWER:
|
|
|
|
updateVerticesForLOD();
|
|
|
|
updateIndicesLOD();
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2019-02-27 17:16:25 +08:00
|
|
|
|
2015-03-03 14:14:50 +08:00
|
|
|
}
|
2019-02-27 17:16:25 +08:00
|
|
|
|
|
|
|
auto *renderer = Director::getInstance()->getRenderer();
|
|
|
|
CCASSERT(_buffer && _chunkIndices._indexBuffer, "buffer should not be nullptr");
|
|
|
|
_command.setIndexBuffer(_chunkIndices._indexBuffer, backend::IndexFormat::U_SHORT);
|
|
|
|
_command.setVertexBuffer(_buffer);
|
|
|
|
_command.getPipelineDescriptor().vertexLayout = _terrain->_vertexLayout;
|
|
|
|
_command.getPipelineDescriptor().programState = _terrain->_programState;
|
|
|
|
_command.setIndexDrawInfo(0, _chunkIndices._size);
|
|
|
|
renderer->addCommand(&_command);
|
2015-04-08 15:17:05 +08:00
|
|
|
CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1, _chunkIndices._size);
|
2015-01-15 11:45:06 +08:00
|
|
|
}
|
|
|
|
|
2016-11-16 09:48:37 +08:00
|
|
|
void Terrain::Chunk::generate(int imgWidth, int imageHei, int m, int n, const unsigned char * /*data*/)
|
2015-01-15 11:45:06 +08:00
|
|
|
{
|
2015-04-08 15:17:05 +08:00
|
|
|
_posY = m;
|
|
|
|
_posX = n;
|
2015-03-30 18:25:22 +08:00
|
|
|
switch (_terrain->_crackFixedType)
|
2015-01-15 11:45:06 +08:00
|
|
|
{
|
2015-03-30 18:25:22 +08:00
|
|
|
case CrackFixedType::SKIRT:
|
2019-02-27 17:16:25 +08:00
|
|
|
{
|
|
|
|
for (int i = _size.height*m; i <= _size.height*(m + 1); ++i)
|
2015-01-15 11:45:06 +08:00
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
if (i >= imageHei) break;
|
|
|
|
for (int j = _size.width*n; j <= _size.width*(n + 1); j++)
|
2015-03-30 18:25:22 +08:00
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
if (j >= imgWidth)break;
|
|
|
|
auto v = _terrain->_vertices[i*imgWidth + j];
|
|
|
|
_originalVertices.push_back(v);
|
2015-03-30 18:25:22 +08:00
|
|
|
}
|
2019-02-27 17:16:25 +08:00
|
|
|
}
|
|
|
|
// add four skirts
|
2016-03-21 21:04:06 +08:00
|
|
|
|
2019-02-27 17:16:25 +08:00
|
|
|
float skirtHeight = _terrain->_skirtRatio *_terrain->_terrainData._mapScale * 8;
|
|
|
|
//#1
|
|
|
|
_terrain->_skirtVerticesOffset[0] = (int)_originalVertices.size();
|
|
|
|
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 -= skirtHeight;
|
|
|
|
_originalVertices.push_back(v);
|
|
|
|
}
|
2015-04-01 18:24:05 +08:00
|
|
|
|
2019-02-27 17:16:25 +08:00
|
|
|
//#2
|
|
|
|
_terrain->_skirtVerticesOffset[1] = (int)_originalVertices.size();
|
|
|
|
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 -= skirtHeight;
|
|
|
|
_originalVertices.push_back(v);
|
|
|
|
}
|
2015-04-01 18:24:05 +08:00
|
|
|
|
2019-02-27 17:16:25 +08:00
|
|
|
//#3
|
|
|
|
_terrain->_skirtVerticesOffset[2] = (int)_originalVertices.size();
|
|
|
|
for (int i = _size.height*m; i <= _size.height*(m + 1); ++i)
|
|
|
|
{
|
|
|
|
auto v = _terrain->_vertices[i*imgWidth + _size.width*n];
|
|
|
|
v._position.y -= skirtHeight;
|
|
|
|
_originalVertices.push_back(v);
|
|
|
|
}
|
2015-03-30 18:25:22 +08:00
|
|
|
|
2019-02-27 17:16:25 +08:00
|
|
|
//#4
|
|
|
|
_terrain->_skirtVerticesOffset[3] = (int)_originalVertices.size();
|
|
|
|
for (int j = _size.width*n; j <= _size.width*(n + 1); j++)
|
|
|
|
{
|
|
|
|
auto v = _terrain->_vertices[_size.height*m*imgWidth + j];
|
|
|
|
v._position.y -= skirtHeight;
|
|
|
|
//v.position.y = -5;
|
|
|
|
_originalVertices.push_back(v);
|
2015-01-15 11:45:06 +08:00
|
|
|
}
|
2019-02-27 17:16:25 +08:00
|
|
|
}
|
|
|
|
break;
|
2015-03-30 18:25:22 +08:00
|
|
|
case CrackFixedType::INCREASE_LOWER:
|
2019-02-27 17:16:25 +08:00
|
|
|
{
|
|
|
|
for (int i = _size.height*m; i <= _size.height*(m + 1); ++i)
|
2015-03-30 18:25:22 +08:00
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
if (i >= imageHei) break;
|
|
|
|
for (int j = _size.width*n; j <= _size.width*(n + 1); j++)
|
2015-03-30 18:25:22 +08:00
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
if (j >= imgWidth)break;
|
|
|
|
auto v = _terrain->_vertices[i*imgWidth + j];
|
|
|
|
_originalVertices.push_back(v);
|
2015-03-30 18:25:22 +08:00
|
|
|
}
|
|
|
|
}
|
2019-02-27 17:16:25 +08:00
|
|
|
}
|
|
|
|
break;
|
2015-01-15 11:45:06 +08:00
|
|
|
}
|
2015-06-23 14:27:19 +08:00
|
|
|
//store triangle:
|
2016-10-27 15:10:24 +08:00
|
|
|
for (int i = 0; i < _size.height; ++i)
|
2015-06-23 14:27:19 +08:00
|
|
|
{
|
|
|
|
for (int j = 0; j < _size.width; j++)
|
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
int nLocIndex = i * (_size.width + 1) + j;
|
|
|
|
Triangle a(_originalVertices[nLocIndex]._position, _originalVertices[nLocIndex + 1 * (_size.width + 1)]._position, _originalVertices[nLocIndex + 1]._position);
|
|
|
|
Triangle b(_originalVertices[nLocIndex + 1]._position, _originalVertices[nLocIndex + 1 * (_size.width + 1)]._position, _originalVertices[nLocIndex + 1 * (_size.width + 1) + 1]._position);
|
2015-06-23 14:27:19 +08:00
|
|
|
|
|
|
|
_trianglesList.push_back(a);
|
|
|
|
_trianglesList.push_back(b);
|
|
|
|
}
|
|
|
|
}
|
2015-03-30 18:25:22 +08:00
|
|
|
|
2015-01-15 11:45:06 +08:00
|
|
|
calculateAABB();
|
|
|
|
finish();
|
|
|
|
}
|
|
|
|
|
2019-02-27 17:16:25 +08:00
|
|
|
Terrain::Chunk::Chunk(Terrain *terrain)
|
2015-01-15 11:45:06 +08:00
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
_terrain = terrain;
|
2015-01-15 11:45:06 +08:00
|
|
|
_currentLod = 0;
|
2015-04-03 13:49:07 +08:00
|
|
|
_left = nullptr;
|
|
|
|
_right = nullptr;
|
|
|
|
_back = nullptr;
|
|
|
|
_front = nullptr;
|
2015-03-03 14:14:50 +08:00
|
|
|
_oldLod = -1;
|
2019-02-27 17:16:25 +08:00
|
|
|
for (int i = 0; i < 4; ++i)
|
2015-03-03 14:14:50 +08:00
|
|
|
{
|
|
|
|
_neighborOldLOD[i] = -1;
|
|
|
|
}
|
2019-02-27 17:16:25 +08:00
|
|
|
_command.init(_terrain->_globalZOrder);
|
|
|
|
_command.setTransparent(false);
|
|
|
|
_command.set3D(true);
|
2019-03-07 17:30:11 +08:00
|
|
|
_command.setPrimitiveType(MeshCommand::PrimitiveType::TRIANGLE);
|
|
|
|
_command.setDrawType(MeshCommand::DrawType::ELEMENT);
|
2019-02-27 17:16:25 +08:00
|
|
|
auto &pipelineDescriptor = _command.getPipelineDescriptor();
|
|
|
|
pipelineDescriptor.blendDescriptor.blendEnabled = false;
|
2015-01-15 11:45:06 +08:00
|
|
|
}
|
|
|
|
|
2015-03-30 18:25:22 +08:00
|
|
|
void Terrain::Chunk::updateIndicesLOD()
|
2015-01-15 11:45:06 +08:00
|
|
|
{
|
2015-03-03 14:14:50 +08:00
|
|
|
int currentNeighborLOD[4];
|
2019-02-27 17:16:25 +08:00
|
|
|
if (_left)
|
2015-03-03 14:14:50 +08:00
|
|
|
{
|
2015-04-03 13:49:07 +08:00
|
|
|
currentNeighborLOD[0] = _left->_currentLod;
|
2019-02-27 17:16:25 +08:00
|
|
|
}
|
|
|
|
else { currentNeighborLOD[0] = -1; }
|
|
|
|
if (_right)
|
2015-03-03 14:14:50 +08:00
|
|
|
{
|
2015-04-03 13:49:07 +08:00
|
|
|
currentNeighborLOD[1] = _right->_currentLod;
|
2019-02-27 17:16:25 +08:00
|
|
|
}
|
|
|
|
else { currentNeighborLOD[1] = -1; }
|
|
|
|
if (_back)
|
2015-03-03 14:14:50 +08:00
|
|
|
{
|
2015-04-03 13:49:07 +08:00
|
|
|
currentNeighborLOD[2] = _back->_currentLod;
|
2019-02-27 17:16:25 +08:00
|
|
|
}
|
|
|
|
else { currentNeighborLOD[2] = -1; }
|
|
|
|
if (_front)
|
2015-03-03 14:14:50 +08:00
|
|
|
{
|
2015-04-03 13:49:07 +08:00
|
|
|
currentNeighborLOD[3] = _front->_currentLod;
|
2019-02-27 17:16:25 +08:00
|
|
|
}
|
|
|
|
else { currentNeighborLOD[3] = -1; }
|
2015-03-03 14:14:50 +08:00
|
|
|
|
2019-02-27 17:16:25 +08:00
|
|
|
if (_oldLod == _currentLod && (memcmp(currentNeighborLOD, _neighborOldLOD, sizeof(currentNeighborLOD)) == 0))
|
2015-03-03 14:14:50 +08:00
|
|
|
{
|
|
|
|
return;// no need to update
|
|
|
|
}
|
2015-03-30 18:25:22 +08:00
|
|
|
bool isOk;
|
2019-02-27 17:16:25 +08:00
|
|
|
_chunkIndices = _terrain->lookForIndicesLOD(currentNeighborLOD, _currentLod, &isOk);
|
|
|
|
if (isOk)
|
2015-03-30 18:25:22 +08:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2019-02-27 17:16:25 +08:00
|
|
|
memcpy(_neighborOldLOD, currentNeighborLOD, sizeof(currentNeighborLOD));
|
2015-03-03 14:14:50 +08:00
|
|
|
_oldLod = _currentLod;
|
2015-01-15 11:45:06 +08:00
|
|
|
int gridY = _size.height;
|
|
|
|
int gridX = _size.width;
|
|
|
|
|
2019-02-27 17:16:25 +08:00
|
|
|
int step = 1 << _currentLod;
|
|
|
|
if ((_left&&_left->_currentLod > _currentLod) || (_right&&_right->_currentLod > _currentLod)
|
|
|
|
|| (_back&&_back->_currentLod > _currentLod) || (_front && _front->_currentLod > _currentLod))
|
2015-01-23 18:09:54 +08:00
|
|
|
//need update indices.
|
|
|
|
{
|
2016-03-21 21:04:06 +08:00
|
|
|
//t-junction inner
|
2015-04-08 15:17:05 +08:00
|
|
|
_lod[_currentLod]._indices.clear();
|
2019-02-27 17:16:25 +08:00
|
|
|
for (int i = step; i < gridY - step; i += step)
|
2015-01-15 11:45:06 +08:00
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
for (int j = step; j < gridX - step; j += step)
|
2016-03-21 21:04:06 +08:00
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
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);
|
2015-01-15 11:45:06 +08:00
|
|
|
}
|
2015-01-23 18:09:54 +08:00
|
|
|
}
|
|
|
|
//fix T-crack
|
2019-02-27 17:16:25 +08:00
|
|
|
int next_step = 1 << (_currentLod + 1);
|
|
|
|
if (_left&&_left->_currentLod > _currentLod)//left
|
2015-01-23 18:09:54 +08:00
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
for (int i = 0; i < gridY; i += next_step)
|
2015-01-15 11:45:06 +08:00
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
_lod[_currentLod]._indices.push_back(i*(gridX + 1) + step);
|
|
|
|
_lod[_currentLod]._indices.push_back(i*(gridX + 1));
|
|
|
|
_lod[_currentLod]._indices.push_back((i + next_step)*(gridX + 1));
|
2015-01-15 11:45:06 +08:00
|
|
|
|
2019-02-27 17:16:25 +08:00
|
|
|
_lod[_currentLod]._indices.push_back(i*(gridX + 1) + step);
|
|
|
|
_lod[_currentLod]._indices.push_back((i + next_step)*(gridX + 1));
|
|
|
|
_lod[_currentLod]._indices.push_back((i + step)*(gridX + 1) + step);
|
2015-01-15 11:45:06 +08:00
|
|
|
|
2019-02-27 17:16:25 +08:00
|
|
|
_lod[_currentLod]._indices.push_back((i + step)*(gridX + 1) + step);
|
|
|
|
_lod[_currentLod]._indices.push_back((i + next_step)*(gridX + 1));
|
|
|
|
_lod[_currentLod]._indices.push_back((i + next_step)*(gridX + 1) + step);
|
2015-01-23 18:09:54 +08:00
|
|
|
}
|
2019-02-27 17:16:25 +08:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
int start = 0;
|
|
|
|
int end = gridY;
|
|
|
|
if (_front&&_front->_currentLod > _currentLod) end -= step;
|
|
|
|
if (_back&&_back->_currentLod > _currentLod) start += step;
|
|
|
|
for (int i = start; i < end; i += step)
|
2015-01-23 18:09:54 +08:00
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
_lod[_currentLod]._indices.push_back(i*(gridX + 1) + step);
|
|
|
|
_lod[_currentLod]._indices.push_back(i*(gridX + 1));
|
|
|
|
_lod[_currentLod]._indices.push_back((i + step)*(gridX + 1));
|
2015-01-15 11:45:06 +08:00
|
|
|
|
2019-02-27 17:16:25 +08:00
|
|
|
_lod[_currentLod]._indices.push_back(i*(gridX + 1) + step);
|
|
|
|
_lod[_currentLod]._indices.push_back((i + step)*(gridX + 1));
|
|
|
|
_lod[_currentLod]._indices.push_back((i + step)*(gridX + 1) + step);
|
2015-01-23 18:09:54 +08:00
|
|
|
}
|
|
|
|
}
|
2015-01-15 11:45:06 +08:00
|
|
|
|
2019-02-27 17:16:25 +08:00
|
|
|
if (_right&&_right->_currentLod > _currentLod)//LEFT
|
2015-01-23 18:09:54 +08:00
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
for (int i = 0; i < gridY; i += next_step)
|
2015-01-15 11:45:06 +08:00
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
_lod[_currentLod]._indices.push_back(i*(gridX + 1) + gridX);
|
|
|
|
_lod[_currentLod]._indices.push_back(i*(gridX + 1) + gridX - step);
|
|
|
|
_lod[_currentLod]._indices.push_back((i + step)*(gridX + 1) + gridX - step);
|
2015-01-15 11:45:06 +08:00
|
|
|
|
2019-02-27 17:16:25 +08:00
|
|
|
_lod[_currentLod]._indices.push_back(i*(gridX + 1) + gridX);
|
|
|
|
_lod[_currentLod]._indices.push_back((i + step)*(gridX + 1) + gridX - step);
|
|
|
|
_lod[_currentLod]._indices.push_back((i + next_step)*(gridX + 1) + gridX - step);
|
2015-01-15 11:45:06 +08:00
|
|
|
|
2019-02-27 17:16:25 +08:00
|
|
|
_lod[_currentLod]._indices.push_back(i*(gridX + 1) + gridX);
|
|
|
|
_lod[_currentLod]._indices.push_back((i + next_step)*(gridX + 1) + gridX - step);
|
|
|
|
_lod[_currentLod]._indices.push_back((i + next_step)*(gridX + 1) + gridX);
|
2015-01-23 18:09:54 +08:00
|
|
|
}
|
2019-02-27 17:16:25 +08:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
int start = 0;
|
|
|
|
int end = gridY;
|
|
|
|
if (_front&&_front->_currentLod > _currentLod) end -= step;
|
|
|
|
if (_back&&_back->_currentLod > _currentLod) start += step;
|
|
|
|
for (int i = start; i < end; i += step)
|
2015-01-23 18:09:54 +08:00
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
_lod[_currentLod]._indices.push_back(i*(gridX + 1) + gridX);
|
|
|
|
_lod[_currentLod]._indices.push_back(i*(gridX + 1) + gridX - step);
|
|
|
|
_lod[_currentLod]._indices.push_back((i + step)*(gridX + 1) + gridX - step);
|
2015-01-15 11:45:06 +08:00
|
|
|
|
2019-02-27 17:16:25 +08:00
|
|
|
_lod[_currentLod]._indices.push_back(i*(gridX + 1) + gridX);
|
|
|
|
_lod[_currentLod]._indices.push_back((i + step)*(gridX + 1) + gridX - step);
|
|
|
|
_lod[_currentLod]._indices.push_back((i + step)*(gridX + 1) + gridX);
|
2015-01-23 18:09:54 +08:00
|
|
|
}
|
2015-01-15 11:45:06 +08:00
|
|
|
}
|
2019-02-27 17:16:25 +08:00
|
|
|
if (_front&&_front->_currentLod > _currentLod)//front
|
2015-01-23 18:09:54 +08:00
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
for (int i = 0; i < gridX; i += next_step)
|
2015-01-15 11:45:06 +08:00
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
_lod[_currentLod]._indices.push_back((gridY - step)*(gridX + 1) + i);
|
|
|
|
_lod[_currentLod]._indices.push_back(gridY*(gridX + 1) + i);
|
|
|
|
_lod[_currentLod]._indices.push_back((gridY - step)*(gridX + 1) + i + step);
|
2015-01-15 11:45:06 +08:00
|
|
|
|
2019-02-27 17:16:25 +08:00
|
|
|
_lod[_currentLod]._indices.push_back((gridY - step)*(gridX + 1) + i + step);
|
|
|
|
_lod[_currentLod]._indices.push_back(gridY*(gridX + 1) + i);
|
|
|
|
_lod[_currentLod]._indices.push_back(gridY*(gridX + 1) + i + next_step);
|
2015-01-15 11:45:06 +08:00
|
|
|
|
2019-02-27 17:16:25 +08:00
|
|
|
_lod[_currentLod]._indices.push_back((gridY - step)*(gridX + 1) + i + step);
|
|
|
|
_lod[_currentLod]._indices.push_back(gridY*(gridX + 1) + i + next_step);
|
|
|
|
_lod[_currentLod]._indices.push_back((gridY - step)*(gridX + 1) + i + next_step);
|
2015-01-23 18:09:54 +08:00
|
|
|
}
|
2019-02-27 17:16:25 +08:00
|
|
|
}
|
|
|
|
else
|
2015-01-23 18:09:54 +08:00
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
for (int i = step; i < gridX - step; i += step)
|
2015-01-15 11:45:06 +08:00
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
_lod[_currentLod]._indices.push_back((gridY - step)*(gridX + 1) + i);
|
|
|
|
_lod[_currentLod]._indices.push_back(gridY*(gridX + 1) + i);
|
|
|
|
_lod[_currentLod]._indices.push_back((gridY - step)*(gridX + 1) + i + step);
|
2015-01-15 11:45:06 +08:00
|
|
|
|
2019-02-27 17:16:25 +08:00
|
|
|
_lod[_currentLod]._indices.push_back((gridY - step)*(gridX + 1) + i + step);
|
|
|
|
_lod[_currentLod]._indices.push_back(gridY*(gridX + 1) + i);
|
|
|
|
_lod[_currentLod]._indices.push_back(gridY*(gridX + 1) + i + step);
|
2015-01-15 11:45:06 +08:00
|
|
|
}
|
2015-01-23 18:09:54 +08:00
|
|
|
}
|
2019-02-27 17:16:25 +08:00
|
|
|
if (_back&&_back->_currentLod > _currentLod)//back
|
2015-01-23 18:09:54 +08:00
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
for (int i = 0; i < gridX; i += next_step)
|
2015-01-15 11:45:06 +08:00
|
|
|
{
|
2015-04-08 15:17:05 +08:00
|
|
|
_lod[_currentLod]._indices.push_back(i);
|
2019-02-27 17:16:25 +08:00
|
|
|
_lod[_currentLod]._indices.push_back(step*(gridX + 1) + i);
|
|
|
|
_lod[_currentLod]._indices.push_back(step*(gridX + 1) + i + step);
|
2015-01-15 11:45:06 +08:00
|
|
|
|
2015-04-08 15:17:05 +08:00
|
|
|
_lod[_currentLod]._indices.push_back(i);
|
2019-02-27 17:16:25 +08:00
|
|
|
_lod[_currentLod]._indices.push_back(step*(gridX + 1) + i + step);
|
|
|
|
_lod[_currentLod]._indices.push_back(i + next_step);
|
2015-01-15 11:45:06 +08:00
|
|
|
|
2019-02-27 17:16:25 +08:00
|
|
|
_lod[_currentLod]._indices.push_back(i + next_step);
|
|
|
|
_lod[_currentLod]._indices.push_back(step*(gridX + 1) + i + step);
|
|
|
|
_lod[_currentLod]._indices.push_back(step*(gridX + 1) + i + next_step);
|
2015-01-15 11:45:06 +08:00
|
|
|
}
|
2019-02-27 17:16:25 +08:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
for (int i = step; i < gridX - step; i += step)
|
2015-01-15 11:45:06 +08:00
|
|
|
{
|
2015-04-08 15:17:05 +08:00
|
|
|
_lod[_currentLod]._indices.push_back(i);
|
2019-02-27 17:16:25 +08:00
|
|
|
_lod[_currentLod]._indices.push_back(step*(gridX + 1) + i);
|
|
|
|
_lod[_currentLod]._indices.push_back(step*(gridX + 1) + i + step);
|
2015-01-15 11:45:06 +08:00
|
|
|
|
2015-04-08 15:17:05 +08:00
|
|
|
_lod[_currentLod]._indices.push_back(i);
|
2019-02-27 17:16:25 +08:00
|
|
|
_lod[_currentLod]._indices.push_back(step*(gridX + 1) + i + step);
|
|
|
|
_lod[_currentLod]._indices.push_back(i + step);
|
2015-01-23 18:09:54 +08:00
|
|
|
}
|
|
|
|
}
|
2015-03-30 18:25:22 +08:00
|
|
|
|
2019-02-27 17:16:25 +08:00
|
|
|
_chunkIndices = _terrain->insertIndicesLOD(currentNeighborLOD, _currentLod, &_lod[_currentLod]._indices[0], (int)_lod[_currentLod]._indices.size());
|
|
|
|
}
|
|
|
|
else {
|
2015-01-23 18:09:54 +08:00
|
|
|
//No lod difference, use simple method
|
2015-04-08 15:17:05 +08:00
|
|
|
_lod[_currentLod]._indices.clear();
|
2019-02-27 17:16:25 +08:00
|
|
|
for (int i = 0; i < gridY; i += step)
|
2015-01-23 18:09:54 +08:00
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
for (int j = 0; j < gridX; j += step)
|
2016-03-21 21:04:06 +08:00
|
|
|
{
|
2015-01-15 11:45:06 +08:00
|
|
|
|
2019-02-27 17:16:25 +08:00
|
|
|
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);
|
2015-01-23 18:09:54 +08:00
|
|
|
|
2019-02-27 17:16:25 +08:00
|
|
|
_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);
|
2015-01-15 11:45:06 +08:00
|
|
|
}
|
|
|
|
}
|
2019-02-27 17:16:25 +08:00
|
|
|
_chunkIndices = _terrain->insertIndicesLOD(currentNeighborLOD, _currentLod, &_lod[_currentLod]._indices[0], (int)_lod[_currentLod]._indices.size());
|
2015-01-23 18:09:54 +08:00
|
|
|
}
|
2015-01-15 11:45:06 +08:00
|
|
|
}
|
|
|
|
|
2015-01-20 10:34:30 +08:00
|
|
|
void Terrain::Chunk::calculateAABB()
|
2015-01-15 11:45:06 +08:00
|
|
|
{
|
|
|
|
std::vector<Vec3>pos;
|
2019-02-27 17:16:25 +08:00
|
|
|
for (size_t i = 0, size = _originalVertices.size(); i < size; ++i)
|
2015-01-15 11:45:06 +08:00
|
|
|
{
|
2015-06-16 17:46:21 +08:00
|
|
|
pos.push_back(_originalVertices[i]._position);
|
2015-01-15 11:45:06 +08:00
|
|
|
}
|
2019-02-27 17:16:25 +08:00
|
|
|
_aabb.updateMinMax(&pos[0], pos.size());
|
2015-01-15 11:45:06 +08:00
|
|
|
}
|
|
|
|
|
2015-01-20 10:34:30 +08:00
|
|
|
void Terrain::Chunk::calculateSlope()
|
2015-01-15 11:45:06 +08:00
|
|
|
{
|
|
|
|
//find max slope
|
2015-04-08 15:17:05 +08:00
|
|
|
auto lowest = _originalVertices[0]._position;
|
2019-02-27 17:16:25 +08:00
|
|
|
for (size_t i = 0, size = _originalVertices.size(); i < size; ++i)
|
2015-01-15 11:45:06 +08:00
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
if (_originalVertices[i]._position.y < lowest.y)
|
2015-01-15 11:45:06 +08:00
|
|
|
{
|
2015-04-08 15:17:05 +08:00
|
|
|
lowest = _originalVertices[i]._position;
|
2015-01-15 11:45:06 +08:00
|
|
|
}
|
|
|
|
}
|
2015-04-08 15:17:05 +08:00
|
|
|
auto highest = _originalVertices[0]._position;
|
2019-02-27 17:16:25 +08:00
|
|
|
for (size_t i = 0, size = _originalVertices.size(); i < size; ++i)
|
2015-01-15 11:45:06 +08:00
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
if (_originalVertices[i]._position.y > highest.y)
|
2015-01-15 11:45:06 +08:00
|
|
|
{
|
2015-04-08 15:17:05 +08:00
|
|
|
highest = _originalVertices[i]._position;
|
2015-01-15 11:45:06 +08:00
|
|
|
}
|
|
|
|
}
|
2019-02-27 17:16:25 +08:00
|
|
|
Vec2 a(lowest.x, lowest.z);
|
|
|
|
Vec2 b(highest.x, highest.z);
|
2015-01-23 18:09:54 +08:00
|
|
|
float dist = a.distance(b);
|
2019-02-27 17:16:25 +08:00
|
|
|
_slope = (highest.y - lowest.y) / dist;
|
2015-01-15 11:45:06 +08:00
|
|
|
}
|
|
|
|
|
2017-01-16 11:20:07 +08:00
|
|
|
bool Terrain::Chunk::getIntersectPointWithRay(const Ray& ray, Vec3& intersectPoint)
|
2015-06-23 14:27:19 +08:00
|
|
|
{
|
2015-06-24 10:49:18 +08:00
|
|
|
if (!ray.intersects(_aabb))
|
|
|
|
return false;
|
2016-03-21 21:04:06 +08:00
|
|
|
|
2015-06-24 15:49:09 +08:00
|
|
|
float minDist = FLT_MAX;
|
2015-06-23 14:27:19 +08:00
|
|
|
bool isFind = false;
|
|
|
|
for (auto triangle : _trianglesList)
|
|
|
|
{
|
|
|
|
Vec3 p;
|
2017-01-16 11:20:07 +08:00
|
|
|
if (triangle.getIntersectPoint(ray, p))
|
2015-06-23 14:27:19 +08:00
|
|
|
{
|
|
|
|
float dist = ray._origin.distance(p);
|
2019-02-27 17:16:25 +08:00
|
|
|
if (dist < minDist)
|
2015-06-23 14:27:19 +08:00
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
intersectPoint = p;
|
|
|
|
minDist = dist;
|
2015-06-23 14:27:19 +08:00
|
|
|
}
|
2019-02-27 17:16:25 +08:00
|
|
|
isFind = true;
|
2015-06-23 14:27:19 +08:00
|
|
|
}
|
|
|
|
}
|
2016-03-21 21:04:06 +08:00
|
|
|
|
2015-06-24 14:10:38 +08:00
|
|
|
return isFind;
|
2015-06-23 14:27:19 +08:00
|
|
|
}
|
|
|
|
|
2015-01-20 10:34:30 +08:00
|
|
|
void Terrain::Chunk::updateVerticesForLOD()
|
2015-01-15 11:45:06 +08:00
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
if (_oldLod == _currentLod) { return; } // no need to update vertices
|
2015-04-08 15:17:05 +08:00
|
|
|
_currentVertices = _originalVertices;
|
2015-01-23 18:09:54 +08:00
|
|
|
int gridY = _size.height;
|
|
|
|
int gridX = _size.width;
|
|
|
|
|
2016-07-04 22:12:45 +08:00
|
|
|
if (_currentLod >= 2 && std::abs(_slope) > 1.2f)
|
2015-01-23 18:09:54 +08:00
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
int step = 1 << _currentLod;
|
|
|
|
for (int i = step; i < gridY - step; i += step)
|
|
|
|
for (int j = step; j < gridX - step; j += step)
|
2015-01-15 11:45:06 +08:00
|
|
|
{
|
2015-01-23 18:09:54 +08:00
|
|
|
// use linear-sample adjust vertices height
|
|
|
|
float height = 0;
|
|
|
|
float count = 0;
|
2019-02-27 17:16:25 +08:00
|
|
|
for (int n = i - step / 2; n < i + step / 2; n++)
|
2015-01-15 11:45:06 +08:00
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
for (int m = j - step / 2; m < j + step / 2; m++)
|
2015-01-23 18:09:54 +08:00
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
float weight = (step / 2 - std::abs(n - i))*(step / 2 - std::abs(m - j));
|
|
|
|
height += _originalVertices[m*(gridX + 1) + n]._position.y;
|
2015-01-23 18:09:54 +08:00
|
|
|
count += weight;
|
|
|
|
}
|
2015-01-15 11:45:06 +08:00
|
|
|
}
|
2019-02-27 17:16:25 +08:00
|
|
|
_currentVertices[i*(gridX + 1) + j]._position.y = height / count;
|
2015-01-15 11:45:06 +08:00
|
|
|
}
|
2015-01-23 18:09:54 +08:00
|
|
|
}
|
2015-01-15 11:45:06 +08:00
|
|
|
|
2015-04-08 15:17:05 +08:00
|
|
|
glBufferData(GL_ARRAY_BUFFER, sizeof(TerrainVertexData)*_currentVertices.size(), &_currentVertices[0], GL_STREAM_DRAW);
|
2015-11-05 15:18:46 +08:00
|
|
|
_oldLod = _currentLod;
|
2015-01-15 11:45:06 +08:00
|
|
|
}
|
|
|
|
|
2015-01-23 18:14:44 +08:00
|
|
|
Terrain::Chunk::~Chunk()
|
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
CC_SAFE_RELEASE_NULL(_buffer);
|
2015-01-23 18:14:44 +08:00
|
|
|
}
|
|
|
|
|
2015-03-30 18:25:22 +08:00
|
|
|
void Terrain::Chunk::updateIndicesLODSkirt()
|
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
if (_oldLod == _currentLod) return;
|
2015-03-30 18:25:22 +08:00
|
|
|
_oldLod = _currentLod;
|
|
|
|
bool isOk;
|
2019-02-27 17:16:25 +08:00
|
|
|
_chunkIndices = _terrain->lookForIndicesLODSkrit(_currentLod, &isOk);
|
|
|
|
if (isOk) return;
|
2015-03-30 18:25:22 +08:00
|
|
|
|
|
|
|
int gridY = _size.height;
|
|
|
|
int gridX = _size.width;
|
2019-02-27 17:16:25 +08:00
|
|
|
int step = 1 << _currentLod;
|
|
|
|
int k = 0;
|
|
|
|
for (int i = 0; i < gridY; i += step, k += step)
|
2015-03-30 18:25:22 +08:00
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
for (int j = 0; j < gridX; j += step)
|
2016-03-21 21:04:06 +08:00
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
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);
|
2015-03-30 18:25:22 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
//add skirt
|
|
|
|
//#1
|
2019-02-27 17:16:25 +08:00
|
|
|
for (int i = 0; i < gridY; i += step)
|
2015-03-30 18:25:22 +08:00
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
int nLocIndex = i * (gridX + 1) + gridX;
|
|
|
|
_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);
|
2015-03-30 18:25:22 +08:00
|
|
|
|
2019-02-27 17:16:25 +08:00
|
|
|
_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);
|
2015-03-30 18:25:22 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
//#2
|
2019-02-27 17:16:25 +08:00
|
|
|
for (int j = 0; j < gridX; j += step)
|
2015-03-30 18:25:22 +08:00
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
int nLocIndex = (gridY)* (gridX + 1) + j;
|
|
|
|
_lod[_currentLod]._indices.push_back(nLocIndex);
|
|
|
|
_lod[_currentLod]._indices.push_back(_terrain->_skirtVerticesOffset[1] + j);
|
|
|
|
_lod[_currentLod]._indices.push_back(nLocIndex + step);
|
2015-03-30 18:25:22 +08:00
|
|
|
|
2019-02-27 17:16:25 +08:00
|
|
|
_lod[_currentLod]._indices.push_back(nLocIndex + step);
|
|
|
|
_lod[_currentLod]._indices.push_back(_terrain->_skirtVerticesOffset[1] + j);
|
|
|
|
_lod[_currentLod]._indices.push_back(_terrain->_skirtVerticesOffset[1] + j + step);
|
2015-04-01 18:24:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
//#3
|
2019-02-27 17:16:25 +08:00
|
|
|
for (int i = 0; i < gridY; i += step)
|
2015-04-01 18:24:05 +08:00
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
int nLocIndex = i * (gridX + 1);
|
|
|
|
_lod[_currentLod]._indices.push_back(nLocIndex);
|
|
|
|
_lod[_currentLod]._indices.push_back(_terrain->_skirtVerticesOffset[2] + i);
|
|
|
|
_lod[_currentLod]._indices.push_back((i + step)*(gridX + 1));
|
2015-04-01 18:24:05 +08:00
|
|
|
|
2019-02-27 17:16:25 +08:00
|
|
|
_lod[_currentLod]._indices.push_back((i + step)*(gridX + 1));
|
|
|
|
_lod[_currentLod]._indices.push_back(_terrain->_skirtVerticesOffset[2] + i);
|
|
|
|
_lod[_currentLod]._indices.push_back(_terrain->_skirtVerticesOffset[2] + i + step);
|
2015-03-30 18:25:22 +08:00
|
|
|
}
|
|
|
|
|
2015-04-01 18:24:05 +08:00
|
|
|
//#4
|
2019-02-27 17:16:25 +08:00
|
|
|
for (int j = 0; j < gridX; j += step)
|
2015-04-01 18:24:05 +08:00
|
|
|
{
|
|
|
|
int nLocIndex = j;
|
2019-02-27 17:16:25 +08:00
|
|
|
_lod[_currentLod]._indices.push_back(nLocIndex + step);
|
|
|
|
_lod[_currentLod]._indices.push_back(_terrain->_skirtVerticesOffset[3] + j);
|
|
|
|
_lod[_currentLod]._indices.push_back(nLocIndex);
|
2015-04-01 18:24:05 +08:00
|
|
|
|
|
|
|
|
2019-02-27 17:16:25 +08:00
|
|
|
_lod[_currentLod]._indices.push_back(_terrain->_skirtVerticesOffset[3] + j + step);
|
|
|
|
_lod[_currentLod]._indices.push_back(_terrain->_skirtVerticesOffset[3] + j);
|
|
|
|
_lod[_currentLod]._indices.push_back(nLocIndex + step);
|
2015-04-01 18:24:05 +08:00
|
|
|
}
|
2015-03-30 18:25:22 +08:00
|
|
|
|
2019-02-27 17:16:25 +08:00
|
|
|
_chunkIndices = _terrain->insertIndicesLODSkirt(_currentLod, &_lod[_currentLod]._indices[0], (int)_lod[_currentLod]._indices.size());
|
2015-03-30 18:25:22 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
Terrain::QuadTree::QuadTree(int x, int y, int w, int h, Terrain * terrain)
|
2015-01-15 11:45:06 +08:00
|
|
|
{
|
2015-03-03 14:14:50 +08:00
|
|
|
_terrain = terrain;
|
2015-01-23 18:09:54 +08:00
|
|
|
_needDraw = true;
|
2015-04-03 13:49:07 +08:00
|
|
|
_parent = nullptr;
|
2019-02-27 17:16:25 +08:00
|
|
|
_tl = nullptr;
|
|
|
|
_tr = nullptr;
|
|
|
|
_bl = nullptr;
|
|
|
|
_br = nullptr;
|
2015-04-03 13:49:07 +08:00
|
|
|
_posX = x;
|
|
|
|
_posY = y;
|
|
|
|
this->_height = h;
|
|
|
|
this->_width = w;
|
2019-02-27 17:16:25 +08:00
|
|
|
if (_width > terrain->_chunkSize.width &&_height > terrain->_chunkSize.height) //subdivision
|
2015-01-23 18:09:54 +08:00
|
|
|
{
|
2015-01-20 10:34:30 +08:00
|
|
|
_isTerminal = false;
|
2019-02-27 17:16:25 +08:00
|
|
|
this->_tl = new (std::nothrow) QuadTree(x, y, _width / 2, _height / 2, terrain);
|
2015-04-03 13:49:07 +08:00
|
|
|
this->_tl->_parent = this;
|
2019-02-27 17:16:25 +08:00
|
|
|
this->_tr = new (std::nothrow) QuadTree(x + _width / 2, y, _width / 2, _height / 2, terrain);
|
2015-04-03 13:49:07 +08:00
|
|
|
this->_tr->_parent = this;
|
2019-02-27 17:16:25 +08:00
|
|
|
this->_bl = new (std::nothrow) QuadTree(x, y + _height / 2, _width / 2, _height / 2, terrain);
|
2015-04-03 13:49:07 +08:00
|
|
|
this->_bl->_parent = this;
|
2019-02-27 17:16:25 +08:00
|
|
|
this->_br = new (std::nothrow) QuadTree(x + _width / 2, y + _height / 2, _width / 2, _height / 2, terrain);
|
2015-04-03 13:49:07 +08:00
|
|
|
this->_br->_parent = this;
|
|
|
|
|
2015-04-08 15:17:05 +08:00
|
|
|
_localAABB.merge(_tl->_localAABB);
|
|
|
|
_localAABB.merge(_tr->_localAABB);
|
|
|
|
_localAABB.merge(_bl->_localAABB);
|
|
|
|
_localAABB.merge(_br->_localAABB);
|
2019-02-27 17:16:25 +08:00
|
|
|
}
|
|
|
|
else // is terminal Node
|
2015-01-15 11:45:06 +08:00
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
int m = _posY / terrain->_chunkSize.height;
|
|
|
|
int n = _posX / terrain->_chunkSize.width;
|
2015-01-20 10:34:30 +08:00
|
|
|
_chunk = terrain->_chunkesArray[m][n];
|
|
|
|
_isTerminal = true;
|
2015-04-08 15:17:05 +08:00
|
|
|
_localAABB = _chunk->_aabb;
|
2015-03-03 14:14:50 +08:00
|
|
|
_chunk->_parent = this;
|
2015-06-23 14:27:19 +08:00
|
|
|
|
|
|
|
for (auto & triangle : _chunk->_trianglesList)
|
|
|
|
{
|
|
|
|
triangle.transform(_terrain->getNodeToWorldTransform());
|
|
|
|
}
|
2015-01-15 11:45:06 +08:00
|
|
|
}
|
2015-04-08 15:17:05 +08:00
|
|
|
_worldSpaceAABB = _localAABB;
|
2015-03-03 14:14:50 +08:00
|
|
|
_worldSpaceAABB.transform(_terrain->getNodeToWorldTransform());
|
2015-01-15 11:45:06 +08:00
|
|
|
}
|
|
|
|
|
2015-01-20 10:34:30 +08:00
|
|
|
void Terrain::QuadTree::draw()
|
2015-01-15 11:45:06 +08:00
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
if (!_needDraw)return;
|
|
|
|
if (_isTerminal) {
|
2015-01-15 11:45:06 +08:00
|
|
|
this->_chunk->bindAndDraw();
|
2019-02-27 17:16:25 +08:00
|
|
|
}
|
|
|
|
else
|
2015-01-15 11:45:06 +08:00
|
|
|
{
|
2015-04-03 13:49:07 +08:00
|
|
|
this->_tl->draw();
|
|
|
|
this->_tr->draw();
|
|
|
|
this->_br->draw();
|
|
|
|
this->_bl->draw();
|
2015-01-15 11:45:06 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-20 10:34:30 +08:00
|
|
|
void Terrain::QuadTree::resetNeedDraw(bool value)
|
2015-01-15 11:45:06 +08:00
|
|
|
{
|
|
|
|
this->_needDraw = value;
|
2019-02-27 17:16:25 +08:00
|
|
|
if (!_isTerminal)
|
2015-01-15 11:45:06 +08:00
|
|
|
{
|
2015-04-03 13:49:07 +08:00
|
|
|
_tl->resetNeedDraw(value);
|
|
|
|
_tr->resetNeedDraw(value);
|
|
|
|
_bl->resetNeedDraw(value);
|
|
|
|
_br->resetNeedDraw(value);
|
2015-01-15 11:45:06 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-30 18:25:22 +08:00
|
|
|
void Terrain::QuadTree::cullByCamera(const Camera * camera, const Mat4 & worldTransform)
|
2015-01-15 11:45:06 +08:00
|
|
|
{
|
metal support for cocos2d-x (#19305)
* remove deprecated files
* remove some deprecated codes
* remove more deprecated codes
* remove ui deprecated codes
* remove more deprecated codes
* remove deprecated codes in ccmenuitem
* remove more deprecated codes in ui
* remove more deprecated codes in ui
* remove more deprecated codes in ui
* remove more deprecated codes
* remove more deprecated codes
* remove more deprecated codes
* remove vr related codes and ignore some modules
* remove allocator
* remove some config
* 【Feature】add back-end project file
* [Feature] add back-end file
* add pipeline descriptor and shader cache
* [Feature] support sprite for backend
* [Feature] remove unneeded code
* [Feature] according to es2.0 spec, you must use clamp-to-edge as texture wrap mode, and no mipmapping for non-power-of-two texture
* [Feature] set texture wrap mode to clamp-to-edge, and no mipmapping for non-power-of-two texture
* [Feature] remove macro define to .cpp file
* [Feature] add log info
* [Feature] add PipelineDescriptor for TriangleCommand
* [Feature] add PipelineDescriptor object as member of TriangleCommand
* [Feature] add getPipelineDescriptor method
* add renderbackend
* complete pipeline descriptor
* [Feature] add viewport in RenderCommand
* set viewport when rendrering
* [Feature] occur error when using RendererBackend, to be fixed.
* a workaround to fix black screen on macOS 10.14 (#19090)
* add rendererbackend init function
* fix typo
* [Feature] modify testFile
* [BugFix] modify shader path
* [Feature] set default viewport
* fix projection
* [Feature] modify log info
* [BugFix] change viewport data type to int
* [BugFix] add BindGroup to PipelienDescriptor
* [BugFix] change a_position to vec3 in sprite.vert
* [BugFix] set vertexLayout according to V3F_C4B_T2F structure
* [Feature] revert a_position to vec4
* [Feature] renderer should not use gl codes directly
* [Feature] it's better not use default value parameter
* fix depth test setting
* rendererbackend -> renderer
* clear color and depth at begin
* add metal backend
* metal support normalized attribute
* simplify codes
* update external
* add render pass desctriptor in pipeline descriptor
* fix warnings
* fix crash and memeory leak
* refactor Texture2D
* put pipeline descriptor into render command
* simplify codes
* [Feature] update Sprite
* fix crash when closing app
* [Feature] update SpriteBatchNode and TextureAtlas
* support render texture(not finish)
* [Feature] remove unused code
* make tests work on mac
* fix download-deps path error
* make tests work on iOS
* [Feature] support ttf under normal label effect
* refactor triangle command processing
* let renderer handle more common commands
* refactor backend
* make render texture work
* [Feature] refactor backend for GL
* [Feature]Renaming to make it easy to understand
* [Feature] change warp mode to CLAMP_TO_EDGE
* fix ghost
* simplify visit render queue logic
* support progress timer without rial mode
* support partcile system
* Feature/update label (#149)
* [BugFix] fix compile error
* [Feature] support outline effect in ios
* [Feature] add shader file
* [BugFix] fix begin and end RenderPass
* [Feature] update CustomCommand
* [Feature] revert project.pbxproj
* [Feature] simplify codes
* [BugFix] pack AI88 to RGBA8888 only when outline enable
* [Feature] support shadow effect in Label
* [Feature] support BMFont
* [Feature] support glow effect
* [Feature] simplify shader files
* LabelAtlas work
* handle blend function correctly
* support tile map
* don't share buffer in metal
* alloc buffer size as needed
* support more tilemap
* Merge branch 'minggo/metal-support' into feature/updateLabel
* minggo/metal-support:
support tile map
handle blend function correctly
LabelAtlas work
Feature/update label (#149)
support partcile system
# Conflicts:
# cocos/2d/CCLabel.cpp
# cocos/2d/CCSprite.cpp
# cocos/2d/CCSpriteBatchNode.cpp
# cocos/renderer/CCQuadCommand.cpp
# cocos/renderer/CCQuadCommand.h
* render texture work without saving file
* use global viewport
* grid3d works
* remove grabber
* tiled3d works
* [BugFix] fix label bug
* [Feature] add updateSubData for buffer
* [Feature] remove setVertexCount
* support depth test
* add callback command
* [Feature] add UITest
* [Feature] update UITest
* [Feature] remove unneeded codes
* fix custom command issue
* fix layer color blend issue
* [BugFix] fix iOS compile error
* [Feature] remove unneeded codes
* [Feature] fix updateVertexBuffer
* layerradial works
* add draw test back
* fix batch issue
* fix compiling error
* [BugFix] support ETC1
* [BugFix] get the correct pipelineDescriptor
* [BugFix] skip draw when backendTexture nullptr
* clipping node support
* [Feature] add shader files
* fix stencil issue in metal
* [Feature] update UILayoutTest
* [BugFix] skip drawing when vertexCount is zero
* refactor renderer
* add set global z order for stencil manager commands
* fix warnings caused by type
* remove viewport in render command
* [Feature] fix warnings caused by type
* [BugFix] clear vertexCount and indexCount for CustomComand when needed
* [Feature] update clear for CustomCommand
* ios use metal
* fix viewport issue
* fix LayerColorGradient crash
* [cmake] transport to android and windows (#160)
* save point 1
* compile on windows
* run on android
* revert useless change
* android set CC_ENABLE_CACHE_TEXTURE_DATA to 1
* add initGlew
* fix android crash
* add TODO new-renderer
* review update
* revert onGLFWWindowPosCallback
* fix android compiling error
* Impl progress radial (#162)
* progresstimer add radial impl
* default drawType to element
* dec invoke times of createVertexBuffer (#163)
* support depth/stencil format for gl backend
* simplify progress timer codes
* support motionstreak, effect is wrong
* fix motionstreak issue
* [Feature] update Scissor Test (#161)
* [Feature] update Scissor Test
* [Feature] update ScissorTest
* [Feature] rename function
* [Feature] get constant reference if needed
* [Feature] show render status (#164)
* improve performance
* fix depth state
* fill error that triangle vertex/index number bigger than buffer
* fix compiline error in release mode
* fix buffer conflict between CPU and GPU on iOS/macOS
* Renderer refactor (#165)
* use one vertes/index buffer with opengl
* fix error on windows
* custom command support index format config
* CCLayer: compact vertex data structure
* update comment
* fix doc
* support fast tilemap
* pass index format instead
* fix some wrong effect
* fix render texture error
* fix texture per-element size
* fix texture format error
* BlendFunc type refactor, GLenum -> backend::BlendFactor (#167)
* BlendFunc use backend::BlendFactor as inner field
* update comments
* use int to replace GLenum
* update xcode project fiel
* rename to GLBlendConst
* add ccConstants.h
* update xcode project file
* update copyright
* remove primitive command
* remove CCPrimitive.cpp/.h
* remove deprecated files
* remove unneeded files
* remove multiple view support
* remove multiple view support
* remove the usage of frame buffer in camera
* director don't use frame buffer
* remove FrameBuffer
* remove BatchCommand
* add some api reference
* add physics2d back
* fix crash when close app on mac
* improve render texture
* fix rendertexture issue
* fix rendertexture issue
* simplify codes
* CMake support for mac & ios (#169)
* update cmake
* fix compile error
* update 3rd libs version
* remove CCThread.h/.cpp
* remove ccthread
* use audio engine to implement simple audio engine
* remove unneeded codes
* remove deprecated codes
* remove winrt macro
* remove CC_USE_WIC
* set partcile blend function in more elegant way
* remove unneeded codes
* remove unneeded codes
* cmake works on windows
* update project setting
* improve performance
* GLFloat -> float
* sync v3 cmake improvements into metal-support (#172)
* pick: modern cmake, compile definitions improvement (#19139)
* modern cmake, use target_compile_definitions partly
* simplify macro define, remove USE_*
* modern cmake, macro define
* add physics 2d macro define into ccConfig.h
* remove USE_CHIPMUNK macro in build.gradle
* remove CocosSelectModule.cmake
* shrink useless define
* simplify compile options config, re-add if necessary
* update external for tmp CI test
* un-quote target_compile_options value
* add "-g" parameter only when debug mode
* keep single build type when generator Xcode & VS projecy
* update external for tmp CI tes
* add static_cast<char>(-1), fix -Wc++11-narrowing
* simplify win32 compile define
* not modify code, only improve compile options
# Conflicts:
# .gitignore
# cmake/Modules/CocosConfigDepend.cmake
# cocos/CMakeLists.txt
# external/config.json
# tests/cpp-tests/CMakeLists.txt
* modern cmake, improve cmake_compiler_flags (#19145)
* cmake_compiler_flags
* Fix typo
* Fix typo2
* Remove chanages from Android.mk
* correct lua template cmake build (#19149)
* don't add -Wno-deprecated into jsb target
* correct lua template cmake build
* fix win32 lua template compile error
* prevent cmake in-source-build friendly (#19151)
* pick: Copy resources to "Resources/" on win32 like in linux configuration
* add "/Z7" for cpp-tests on windows
* [cmake] fix iOS xcode property setting failed (#19208)
* fix iOS xcode property setting failed
* use search_depend_libs_recursive at dlls collect
* fix typo
* [cmake] add find_host_library into iOS toolchain file (#19230)
* pick: [lua android] use luajit & template cmake update (#19239)
* increase cmake stability , remove tests/CMakeLists.txt (#19261)
* cmake win32 Precompiled header (#19273)
* Precompiled header
* Fix
* Precompiled header for cocos
* Precompiled header jscocos2d
* Fix for COCOS2D_DEBUG is always 1 on Android (#19291)
Related #19289
* little build fix, tests cpp-tests works on mac
* sync v3 build related codes into metal-support (#173)
* strict initialization for std::array
* remove proj.win32 project configs
* modern cmake, cmake_cleanup_remove_unused_variables (#19146)
* Switch travis CI to xenial (#19207)
* Switch travis CI to xenial
* Remove language: android
* Set language: cpp
* Fix java problem
* Update sdkmanager
* Fix sdkmanger
* next sdkmanager fix
* Remove xenial from android
* revert to sdk-tools-{system}-3859397
* Remove linux cmake install
* Update before-install.sh
* Update .travis.yml
* Simplify install-deps-linux.sh, tested on Ubuntu 16.04 (#19212)
* Simplify install-deps-linux.sh
* Cleanup
* pick: install ninja
* update cocos2d-console submodule
* for metal-support alpha release, we only test cpp
* add HelloCpp into project(Cocos2d-x) for tmp test
* update extenal metal-support-4
* update uniform setting
* [Feature] update BindGroup
* [Feature] empty-test
* [Feature] cpp-test
* [Feature] fix GL compiler error
* [Feature] fix GL crash
* [Feature] empty-test
* [Feature] cpp-tests
* [feature] improve frameRate
* [feature] fix opengl compile error
* [feature] fix opengl compile error
* [BugFix] fix compute maxLocation error
* [Feature] update setting unifrom
* [Feature] fix namespace
* [Feature] remove unneeded code
* [Bugfix] fix project file
* [Feature] update review
* [texture2d] impl texture format support (#175)
* texture update
* update
* update texture
* commit
* compile on windows
* ddd
* rename
* rename methods
* no crash
* save gl
* save
* save
* rename
* move out pixel format convert functions
* metal crash
* update
* update android
* support gles compressed texture format
* support more compress format
* add more conversion methods
* ss
* save
* update conversion methods
* add PVRTC format support
* reformat
* add marco linux
* fix GL marcro
* pvrtc supported only by ios 8.0+
* remove unused cmake
* revert change
* refactor Texture2D::initWithData
* fix conversion log
* refactor Texture2D::initWithData
* remove some OpenGL constants for PVRTC
* add todo
* fix typo
* AutoTest works on mac/iOS by disable part cases, sync v3 bug fix (#174)
* review cpp-tests, and fix part issues on start auto test
* sync png format fix: Node:Particle3D abnormal texture effects #19204
* fix cpp-tests SpritePolygon crash, wrong png format (#19170)
* fix wrong png convert format from sRGB to Gray
* erase plist index if all frames was erased
* test_A8.png have I8 format, fix it
* [CCSpriteCache] allow re-add plist & add testcase (#19175)
* allow re-add plist & add testcase
* remove comments/rename method/update testcase
* fix isSpriteFramesWithFileLoaded & add testcase
* remove used variable
* remove unused variable
* fix double free issues when js/lua-tests exit on iOS (#19236)
* disable part cases, AutoTest works without crash on mac
* update cocos2dx files json, to test cocos new next
* fix spritecache plist parsing issue (#19269)
* [linux] Fix FileUtils::getContents with folder (#19157)
* fix FileUtils::getContents on linux/mac
* use stat.st_mode
* simplify
* [CCFileUtils] win32 getFileSize (#19176)
* win32 getFileSize
* fix stat
* [cpp test-Android]20:FileUtils/2 change title (#19197)
* sync #19200
* sync #19231
* [android lua] improve performance of lua loader (#19234)
* [lua] improve performance of lua loader
* remove cache fix
* Revert "fix spritecache plist parsing issue (#19269)"
This reverts commit f3a85ece4307a7b90816c34489d1ed2c8fd11baf.
* remove win32 project files ref in template.json
* add metal framework lnk ref into cpp template
* test on iOS, and disable part cases
* alBufferData instead of alBufferDataStatic for small audio file on Apple (#19227)
* changes AudioCache to use alBufferData instead of alBufferDataStatic
(also makes test 19 faster to trigger openal bugs faster)
The original problem: CrashIfClientProvidedBogusAudioBufferList
https://github.com/cocos2d/cocos2d-x/issues/18948
is not happening anymore, but there's still a not very frequent issue
that makes OpenAL crash with a call stack like this.
AudioCache::readDataTask > alBufferData > CleanUpDeadBufferList
It happes more frequently when the device is "cold", which means after
half an hour of not using the device (locked).
I could not find the actual source code for iOS OpenAL, so I used the
macOS versions:
https://opensource.apple.com/source/OpenAL/OpenAL-48.7/Source/OpenAL/oalImp.cpp.auto.html
They seem to use CAGuard.h to make sure the dead buffer list
has no threading issues. I'm worried because the CAGuard code I found
has macos and win32 define but no iOS, so I'm not sure. I guess the
iOS version is different and has the guard.
I could not find a place in the code that's unprotected by the locks
except the InitializeBufferMap() which should not be called more than
once from cocos, and there's a workaround in AudioEngine-impl for it.
I reduced the occurence of the CleanUpDeadBufferList crash by moving
the guard in ~AudioCache to cover the alDeleteBuffers call.
* remove hack method "setTimeout" on audio
* AutoTest works on iOS
* support set ios deployment target for root project
* enable all texture2d cases, since Jiang have fixed
* add CCTextureUtils to xcode project file (#176)
* add leak cases for SpriteFrameCache (#177)
* re-add SpriteFrameCache cases
* update template file json
* Update SpriteFrameCacheTest.cpp
* fix compiling error
2019-01-18 15:08:25 +08:00
|
|
|
//TODO new-renderer: interface isVisibleInFrustum removal
|
2019-02-27 17:16:25 +08:00
|
|
|
if(!camera->isVisibleInFrustum(&_worldSpaceAABB))
|
|
|
|
{
|
2015-01-15 11:45:06 +08:00
|
|
|
this->resetNeedDraw(false);
|
2019-02-27 17:16:25 +08:00
|
|
|
}
|
|
|
|
else if (!_isTerminal) {
|
|
|
|
_tl->cullByCamera(camera, worldTransform);
|
|
|
|
_tr->cullByCamera(camera, worldTransform);
|
|
|
|
_bl->cullByCamera(camera, worldTransform);
|
|
|
|
_br->cullByCamera(camera, worldTransform);
|
|
|
|
}
|
|
|
|
// }
|
2015-01-15 11:45:06 +08:00
|
|
|
}
|
|
|
|
|
2015-04-01 18:24:05 +08:00
|
|
|
void Terrain::QuadTree::preCalculateAABB(const Mat4 & worldTransform)
|
2015-03-03 14:14:50 +08:00
|
|
|
{
|
2015-04-01 18:24:05 +08:00
|
|
|
|
2015-04-08 15:17:05 +08:00
|
|
|
_worldSpaceAABB = _localAABB;
|
2015-04-03 13:49:07 +08:00
|
|
|
_worldSpaceAABB.transform(worldTransform);
|
2019-02-27 17:16:25 +08:00
|
|
|
if (!_isTerminal) {
|
2015-04-03 13:49:07 +08:00
|
|
|
_tl->preCalculateAABB(worldTransform);
|
|
|
|
_tr->preCalculateAABB(worldTransform);
|
|
|
|
_bl->preCalculateAABB(worldTransform);
|
|
|
|
_br->preCalculateAABB(worldTransform);
|
2015-03-03 14:14:50 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-01 18:24:05 +08:00
|
|
|
Terrain::QuadTree::~QuadTree()
|
|
|
|
{
|
2019-02-27 17:16:25 +08:00
|
|
|
if (_tl) delete _tl;
|
|
|
|
if (_tr) delete _tr;
|
|
|
|
if (_bl) delete _bl;
|
|
|
|
if (_br) delete _br;
|
2015-04-01 18:24:05 +08:00
|
|
|
}
|
|
|
|
|
2019-02-27 17:16:25 +08:00
|
|
|
Terrain::TerrainData::TerrainData(const std::string& heightMapsrc, const std::string& textureSrc, const Size & chunksize, float height, float scale)
|
2016-03-21 21:04:06 +08:00
|
|
|
{
|
2015-04-08 15:17:05 +08:00
|
|
|
this->_heightMapSrc = heightMapsrc;
|
|
|
|
this->_detailMaps[0]._detailMapSrc = textureSrc;
|
2015-11-12 18:08:29 +08:00
|
|
|
this->_alphaMapSrc = "";
|
2015-04-08 15:17:05 +08:00
|
|
|
this->_chunkSize = chunksize;
|
|
|
|
this->_mapHeight = height;
|
2016-03-21 21:04:06 +08:00
|
|
|
this->_mapScale = scale;
|
2015-04-08 15:17:05 +08:00
|
|
|
_skirtHeightRatio = 1;
|
2015-01-15 11:45:06 +08:00
|
|
|
}
|
|
|
|
|
2015-11-12 18:08:29 +08:00
|
|
|
Terrain::TerrainData::TerrainData(const std::string& heightMapsrc, const std::string& alphamap, const DetailMap& detail1, const DetailMap& detail2, const DetailMap& detail3, const DetailMap& detail4, const Size & chunksize, float height, float scale)
|
2015-01-15 11:45:06 +08:00
|
|
|
{
|
2015-04-08 15:17:05 +08:00
|
|
|
this->_heightMapSrc = heightMapsrc;
|
2015-11-12 18:08:29 +08:00
|
|
|
this->_alphaMapSrc = alphamap;
|
2015-04-08 15:17:05 +08:00
|
|
|
this->_detailMaps[0] = detail1;
|
|
|
|
this->_detailMaps[1] = detail2;
|
|
|
|
this->_detailMaps[2] = detail3;
|
|
|
|
this->_detailMaps[3] = detail4;
|
|
|
|
this->_chunkSize = chunksize;
|
|
|
|
this->_mapHeight = height;
|
|
|
|
this->_mapScale = scale;
|
2015-01-23 18:09:54 +08:00
|
|
|
_detailMapAmount = 4;
|
2015-04-08 15:17:05 +08:00
|
|
|
_skirtHeightRatio = 1;
|
2015-01-23 18:09:54 +08:00
|
|
|
}
|
|
|
|
|
2015-11-12 18:08:29 +08:00
|
|
|
Terrain::TerrainData::TerrainData(const std::string& heightMapsrc, const std::string& alphamap, const DetailMap& detail1, const DetailMap& detail2, const DetailMap& detail3, const Size & chunksize /*= Size(32,32)*/, float height /*= 2*/, float scale /*= 0.1*/)
|
2015-01-23 18:09:54 +08:00
|
|
|
{
|
2015-04-08 15:17:05 +08:00
|
|
|
this->_heightMapSrc = heightMapsrc;
|
2015-11-12 18:08:29 +08:00
|
|
|
this->_alphaMapSrc = alphamap;
|
2015-04-08 15:17:05 +08:00
|
|
|
this->_detailMaps[0] = detail1;
|
|
|
|
this->_detailMaps[1] = detail2;
|
|
|
|
this->_detailMaps[2] = detail3;
|
|
|
|
this->_chunkSize = chunksize;
|
|
|
|
this->_mapHeight = height;
|
|
|
|
this->_mapScale = scale;
|
2015-01-23 18:09:54 +08:00
|
|
|
_detailMapAmount = 3;
|
2015-04-08 15:17:05 +08:00
|
|
|
_skirtHeightRatio = 1;
|
2015-01-15 11:45:06 +08:00
|
|
|
}
|
|
|
|
|
2015-01-20 10:34:30 +08:00
|
|
|
Terrain::TerrainData::TerrainData()
|
2015-01-15 11:45:06 +08:00
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2019-02-27 17:16:25 +08:00
|
|
|
Terrain::ChunkIndices::ChunkIndices(const Terrain::ChunkIndices &other)
|
|
|
|
{
|
|
|
|
_indexBuffer = other._indexBuffer;
|
|
|
|
CC_SAFE_RETAIN(_indexBuffer);
|
|
|
|
_size = other._size;
|
|
|
|
}
|
|
|
|
|
|
|
|
Terrain::ChunkIndices& Terrain::ChunkIndices::operator=(const Terrain::ChunkIndices &other)
|
|
|
|
{
|
|
|
|
if(other._indexBuffer != _indexBuffer)
|
|
|
|
{
|
|
|
|
CC_SAFE_RELEASE_NULL(_indexBuffer);
|
|
|
|
_indexBuffer = other._indexBuffer;
|
|
|
|
CC_SAFE_RETAIN(_indexBuffer);
|
|
|
|
}
|
|
|
|
_size = other._size;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
Terrain::ChunkIndices::~ChunkIndices()
|
|
|
|
{
|
|
|
|
CC_SAFE_RELEASE_NULL(_indexBuffer);
|
|
|
|
}
|
|
|
|
|
2015-11-12 18:08:29 +08:00
|
|
|
Terrain::DetailMap::DetailMap(const std::string& detailMapPath, float size /*= 35*/)
|
2015-01-15 11:45:06 +08:00
|
|
|
{
|
2015-04-08 15:17:05 +08:00
|
|
|
this->_detailMapSrc = detailMapPath;
|
|
|
|
this->_detailMapSize = size;
|
2015-01-15 11:45:06 +08:00
|
|
|
}
|
|
|
|
|
2015-01-20 10:34:30 +08:00
|
|
|
Terrain::DetailMap::DetailMap()
|
2015-01-15 11:45:06 +08:00
|
|
|
{
|
2016-03-21 21:04:06 +08:00
|
|
|
_detailMapSrc = "";
|
2015-04-08 15:17:05 +08:00
|
|
|
_detailMapSize = 35;
|
2015-01-15 11:45:06 +08:00
|
|
|
}
|
2015-05-08 15:49:33 +08:00
|
|
|
|
2016-05-17 12:17:56 +08:00
|
|
|
Terrain::Triangle::Triangle(const Vec3& p1, const Vec3& p2, const Vec3& p3)
|
2015-06-23 14:27:19 +08:00
|
|
|
{
|
|
|
|
_p1 = p1;
|
|
|
|
_p2 = p2;
|
|
|
|
_p3 = p3;
|
|
|
|
}
|
|
|
|
|
2016-05-17 12:17:56 +08:00
|
|
|
void Terrain::Triangle::transform(const cocos2d::Mat4& matrix)
|
2015-06-23 14:27:19 +08:00
|
|
|
{
|
|
|
|
matrix.transformPoint(&_p1);
|
|
|
|
matrix.transformPoint(&_p2);
|
|
|
|
matrix.transformPoint(&_p3);
|
|
|
|
}
|
|
|
|
|
2015-06-24 15:49:09 +08:00
|
|
|
//Please refer to 3D Math Primer for Graphics and Game Development
|
2017-01-16 11:20:07 +08:00
|
|
|
bool Terrain::Triangle::getIntersectPoint(const Ray& ray, Vec3& intersectPoint) const
|
2015-06-23 14:27:19 +08:00
|
|
|
{
|
|
|
|
// E1
|
|
|
|
Vec3 E1 = _p2 - _p1;
|
|
|
|
|
|
|
|
// E2
|
|
|
|
Vec3 E2 = _p3 - _p1;
|
|
|
|
|
|
|
|
// P
|
|
|
|
Vec3 P;
|
2019-02-27 17:16:25 +08:00
|
|
|
Vec3::cross(ray._direction, E2, &P);
|
2015-06-23 14:27:19 +08:00
|
|
|
|
|
|
|
// determinant
|
2019-02-27 17:16:25 +08:00
|
|
|
float det = E1.dot(P);
|
2015-06-23 14:27:19 +08:00
|
|
|
|
|
|
|
// keep det > 0, modify T accordingly
|
|
|
|
Vec3 T;
|
|
|
|
if (det > 0)
|
|
|
|
{
|
|
|
|
T = ray._origin - _p1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
T = _p1 - ray._origin;
|
|
|
|
det = -det;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If determinant is near zero, ray lies in plane of triangle
|
|
|
|
if (det < 0.0001f)
|
|
|
|
return false;
|
|
|
|
|
2019-02-27 17:16:25 +08:00
|
|
|
float t; // ray dist
|
|
|
|
float u, v;//barycentric coordinate
|
|
|
|
// Calculate u and make sure u <= 1
|
2015-06-23 14:27:19 +08:00
|
|
|
u = T.dot(P);
|
|
|
|
if (u < 0.0f || u > det)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// Q
|
2016-03-21 21:04:06 +08:00
|
|
|
Vec3 Q;
|
2019-02-27 17:16:25 +08:00
|
|
|
Vec3::cross(T, E1, &Q);
|
2015-06-23 14:27:19 +08:00
|
|
|
|
|
|
|
// Calculate v and make sure u + v <= 1
|
|
|
|
v = ray._direction.dot(Q);
|
|
|
|
if (v < 0.0f || u + v > det)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// Calculate t, scale parameters, ray intersects triangle
|
|
|
|
t = E2.dot(Q);
|
|
|
|
|
|
|
|
float fInvDet = 1.0f / det;
|
|
|
|
t *= fInvDet;
|
|
|
|
|
2017-01-16 11:20:07 +08:00
|
|
|
intersectPoint = ray._origin + ray._direction * t;
|
2015-06-23 14:27:19 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2019-02-27 17:16:25 +08:00
|
|
|
void Terrain::onBeforeDraw()
|
|
|
|
{
|
|
|
|
_stateBlockOld.save();
|
|
|
|
_stateBlock.apply();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Terrain::onAfterDraw()
|
|
|
|
{
|
|
|
|
_stateBlockOld.apply();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Terrain::StateBlock::save()
|
|
|
|
{
|
|
|
|
auto renderer = Director::getInstance()->getRenderer();
|
|
|
|
depthWrite = renderer->getDepthWrite();
|
|
|
|
depthTest = renderer->getDepthTest();
|
|
|
|
cullFace = renderer->getCullMode();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Terrain::StateBlock::apply()
|
|
|
|
{
|
|
|
|
auto renderer = Director::getInstance()->getRenderer();
|
|
|
|
renderer->setDepthTest(depthTest);
|
|
|
|
renderer->setDepthWrite(depthWrite);
|
|
|
|
renderer->setCullMode(cullFace);
|
|
|
|
}
|
|
|
|
|
2015-06-23 18:31:20 +08:00
|
|
|
NS_CC_END
|