2019-11-23 20:27:39 +08:00
|
|
|
/****************************************************************************
|
|
|
|
Copyright (c) 2015-2016 Chukong Technologies Inc.
|
|
|
|
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
|
|
|
|
|
|
|
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.
|
|
|
|
****************************************************************************/
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
#include "2d/CCNode.h"
|
|
|
|
#include "2d/CCCamera.h"
|
|
|
|
#include "renderer/CCTexture2D.h"
|
|
|
|
#include "renderer/CCMeshCommand.h"
|
|
|
|
#include "renderer/CCCallbackCommand.h"
|
|
|
|
#include "renderer/CCGroupCommand.h"
|
|
|
|
#include "renderer/CCRenderState.h"
|
|
|
|
#include "renderer/backend/Types.h"
|
|
|
|
#include "renderer/backend/ProgramState.h"
|
|
|
|
#include "3d/CCAABB.h"
|
|
|
|
#include "3d/CCRay.h"
|
|
|
|
#include "base/CCEventListenerCustom.h"
|
|
|
|
#include "base/CCEventDispatcher.h"
|
|
|
|
|
|
|
|
NS_CC_BEGIN
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @addtogroup _3d
|
|
|
|
* @{
|
|
|
|
*/
|
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
/**
|
2019-11-23 20:27:39 +08:00
|
|
|
* the maximum amount of the chunks
|
|
|
|
**/
|
|
|
|
#define MAX_CHUNKES 256
|
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
/**
|
|
|
|
* Terrain
|
|
|
|
* Defines a Terrain that is capable of rendering large landscapes from 2D heightmap images.
|
|
|
|
* Terrains can be constructed from several different internal formats heightmap sources:
|
|
|
|
* 1. RGB888
|
|
|
|
* 2. RGBA8888
|
|
|
|
* 3. Luminance(gray-scale)8
|
|
|
|
*
|
|
|
|
* Terrain use TerrainData struct to initialize.the TerrainData struct warp
|
|
|
|
* all parameters that Terrain initialization need.
|
|
|
|
* TerrainData provide several handy constructor for users
|
|
|
|
*
|
|
|
|
* Surface detail is provided via texture splatting, where multiple Detail texture layers can be added
|
|
|
|
* along with alpha map to define how different Detail texture blend with each other. These DetailTexture
|
|
|
|
* can be defined in TerrainData. The number of supported Detail texture is Four. although typically 2-3 levels is
|
|
|
|
* sufficient. For simple usage ,surface detail also is provided via simple Texture.
|
|
|
|
*
|
|
|
|
* Internally, Terrain is divide into smaller, more manageable chunks, which can be culled
|
|
|
|
* separately for more efficient rendering. The size of the terrain chunks can be controlled
|
|
|
|
* via the chunkSize property in TerrainData.
|
|
|
|
*
|
|
|
|
* Chunks are managed under the QuadTree.As DE FACTO terminal Node of the QuadTree;
|
|
|
|
* let us cull chunks efficiently to reduce drawCall amount And reduce the VBOs'Size that pass to the GPU.
|
|
|
|
*
|
|
|
|
* Level of detail (LOD) is supported using a technique that is similar to texture mipmapping -- called GeoMapping.
|
|
|
|
* A distance-to-camera based test used to decide
|
|
|
|
* the appropriate LOD for a terrain chunk. The number of LOD levels is 0 by default (which
|
|
|
|
* means only the base level is used),the maximum number of LOD levels is 4. Of course ,you can hack the value
|
|
|
|
*individually.
|
|
|
|
*
|
|
|
|
* Finally, when LOD is enabled, cracks can begin to appear between terrain Chunks of
|
|
|
|
* different LOD levels. An acceptable solution might be to simply reduce the lower LOD(high detail,smooth) chunks
|
|
|
|
*border, And let the higher LOD(rough) chunks to seamlessly connect it.
|
|
|
|
*
|
|
|
|
* We can use ray-terrain intersection to pick a point of the terrain;
|
|
|
|
* Also we can get an arbitrary point of the terrain's height and normal vector for convenience .
|
|
|
|
**/
|
2019-11-23 20:27:39 +08:00
|
|
|
class CC_DLL Terrain : public Node
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
/**the crack fix type. use to fix the gaps between different LOD chunks */
|
2021-12-25 10:04:45 +08:00
|
|
|
enum class CrackFixedType
|
|
|
|
{
|
2019-11-23 20:27:39 +08:00
|
|
|
SKIRT,
|
|
|
|
INCREASE_LOWER,
|
|
|
|
};
|
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
/**
|
|
|
|
*DetailMap
|
|
|
|
*this struct maintain a detail map data ,including source file ,detail size.
|
|
|
|
*the DetailMap can use for terrain splatting
|
|
|
|
**/
|
|
|
|
struct CC_DLL DetailMap
|
|
|
|
{
|
2019-11-23 20:27:39 +08:00
|
|
|
/*Constructors*/
|
|
|
|
DetailMap();
|
2021-12-28 21:27:32 +08:00
|
|
|
DetailMap(std::string_view detailMapSrc, float size = 35);
|
2019-11-23 20:27:39 +08:00
|
|
|
/*detail Image source file path*/
|
|
|
|
std::string _detailMapSrc;
|
|
|
|
/*detailMapSize determine how many tiles that Terrain represent*/
|
|
|
|
float _detailMapSize;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Triangle
|
|
|
|
*/
|
|
|
|
struct Triangle
|
|
|
|
{
|
|
|
|
Triangle(const Vec3& p1, const Vec3& p2, const Vec3& p3);
|
|
|
|
bool getIntersectPoint(const Ray& ray, Vec3& intersectPoint) const;
|
|
|
|
|
|
|
|
void transform(const Mat4& matrix);
|
|
|
|
Vec3 _p1, _p2, _p3;
|
|
|
|
};
|
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
/**
|
|
|
|
*TerrainData
|
|
|
|
*This TerrainData struct warp all parameter that Terrain need to create
|
|
|
|
*/
|
2019-11-23 20:27:39 +08:00
|
|
|
struct CC_DLL TerrainData
|
|
|
|
{
|
|
|
|
/**empty constructor*/
|
|
|
|
TerrainData();
|
|
|
|
/**constructor, this constructor construct a simple terrain which only have 1 detailmap*/
|
2021-12-28 21:27:32 +08:00
|
|
|
TerrainData(std::string_view heightMapsrc,
|
|
|
|
std::string_view textureSrc,
|
2021-12-25 10:04:45 +08:00
|
|
|
const Vec2& chunksize = Vec2(32, 32),
|
|
|
|
float mapHeight = 2,
|
|
|
|
float mapScale = 0.1);
|
2019-11-23 20:27:39 +08:00
|
|
|
/**constructor, this constructor construct a terrain which have 4 detailmaps, 1 alpha map*/
|
2021-12-28 21:27:32 +08:00
|
|
|
TerrainData(std::string_view heightMapsrc,
|
|
|
|
std::string_view alphamap,
|
2021-12-25 10:04:45 +08:00
|
|
|
const DetailMap& detail1,
|
|
|
|
const DetailMap& detail2,
|
|
|
|
const DetailMap& detail3,
|
|
|
|
const DetailMap& detail4,
|
|
|
|
const Vec2& chunksize = Vec2(32, 32),
|
|
|
|
float mapHeight = 2,
|
|
|
|
float mapScale = 0.1);
|
2019-11-23 20:27:39 +08:00
|
|
|
/**constructor, this constructor construct a terrain which have 3 detailmaps, 1 alpha map*/
|
2021-12-28 21:27:32 +08:00
|
|
|
TerrainData(std::string_view heightMapsrc,
|
|
|
|
std::string_view alphamap,
|
2021-12-25 10:04:45 +08:00
|
|
|
const DetailMap& detail1,
|
|
|
|
const DetailMap& detail2,
|
|
|
|
const DetailMap& detail3,
|
|
|
|
const Vec2& chunksize = Vec2(32, 32),
|
|
|
|
float mapHeight = 2,
|
|
|
|
float mapScale = 0.1);
|
2019-11-23 20:27:39 +08:00
|
|
|
/**
|
2021-12-25 10:04:45 +08:00
|
|
|
*determine the chunk size,chunk is the minimal subdivision of the Terrain
|
|
|
|
*/
|
2021-10-23 23:27:14 +08:00
|
|
|
Vec2 _chunkSize;
|
2019-11-23 20:27:39 +08:00
|
|
|
/**height Map source path*/
|
|
|
|
std::string _heightMapSrc;
|
|
|
|
/**the source path of the alpha map*/
|
|
|
|
std::string _alphaMapSrc;
|
|
|
|
/**detail maps*/
|
|
|
|
DetailMap _detailMaps[4];
|
|
|
|
/**terrain Maximum height*/
|
|
|
|
float _mapHeight;
|
|
|
|
/**terrain scale factor,you can combine setScale later.*/
|
|
|
|
float _mapScale;
|
|
|
|
/**the amount of detailmap*/
|
|
|
|
int _detailMapAmount;
|
|
|
|
/**the skirt height ratio, only effect when terrain use skirt to fix crack*/
|
|
|
|
float _skirtHeightRatio;
|
|
|
|
};
|
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
private:
|
2019-11-23 20:27:39 +08:00
|
|
|
struct ChunkIndices
|
|
|
|
{
|
|
|
|
ChunkIndices() = default;
|
2021-12-25 10:04:45 +08:00
|
|
|
ChunkIndices(const ChunkIndices&);
|
|
|
|
ChunkIndices& operator=(const ChunkIndices& o);
|
2019-11-23 20:27:39 +08:00
|
|
|
~ChunkIndices();
|
2021-12-25 10:04:45 +08:00
|
|
|
backend::Buffer* _indexBuffer = nullptr;
|
|
|
|
unsigned short _size = 0;
|
2019-11-23 20:27:39 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
struct ChunkLODIndices
|
|
|
|
{
|
|
|
|
int _relativeLod[5];
|
|
|
|
ChunkIndices _chunkIndices;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct ChunkLODIndicesSkirt
|
|
|
|
{
|
|
|
|
int _selfLod;
|
|
|
|
ChunkIndices _chunkIndices;
|
|
|
|
};
|
|
|
|
/*
|
2021-12-25 10:04:45 +08:00
|
|
|
*terrain vertices internal data format
|
|
|
|
**/
|
2019-11-23 20:27:39 +08:00
|
|
|
struct CC_DLL TerrainVertexData
|
|
|
|
{
|
|
|
|
/*constructor*/
|
|
|
|
TerrainVertexData(){};
|
|
|
|
TerrainVertexData(const Vec3& v1, const Tex2F& v2)
|
|
|
|
{
|
|
|
|
_position = v1;
|
|
|
|
_texcoord = v2;
|
|
|
|
}
|
|
|
|
/*the vertex's attributes*/
|
|
|
|
cocos2d::Vec3 _position;
|
|
|
|
cocos2d::Tex2F _texcoord;
|
|
|
|
cocos2d::Vec3 _normal;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct CC_DLL QuadTree;
|
|
|
|
/*
|
2021-12-25 10:04:45 +08:00
|
|
|
*the terminal node of quad, use to subdivision terrain mesh and LOD
|
|
|
|
**/
|
2019-11-23 20:27:39 +08:00
|
|
|
struct Chunk
|
|
|
|
{
|
|
|
|
/**Constructor*/
|
2021-12-25 10:04:45 +08:00
|
|
|
Chunk(Terrain*);
|
2019-11-23 20:27:39 +08:00
|
|
|
/**destructor*/
|
|
|
|
~Chunk();
|
|
|
|
/*vertices*/
|
|
|
|
std::vector<TerrainVertexData> _originalVertices;
|
|
|
|
/*LOD indices*/
|
2021-12-25 10:04:45 +08:00
|
|
|
struct LOD
|
|
|
|
{
|
2019-11-23 20:27:39 +08:00
|
|
|
std::vector<uint16_t> _indices;
|
|
|
|
};
|
2021-12-25 10:04:45 +08:00
|
|
|
ChunkIndices _chunkIndices;
|
2019-11-23 20:27:39 +08:00
|
|
|
/**we now support four levels of detail*/
|
|
|
|
LOD _lod[4];
|
|
|
|
/**AABB in local space*/
|
|
|
|
AABB _aabb;
|
|
|
|
/**setup Chunk data*/
|
2021-12-25 10:04:45 +08:00
|
|
|
void generate(int map_width, int map_height, int m, int n, const unsigned char* data);
|
2019-11-23 20:27:39 +08:00
|
|
|
/**calculateAABB*/
|
|
|
|
void calculateAABB();
|
|
|
|
/**internal use draw function*/
|
|
|
|
void bindAndDraw();
|
|
|
|
/**finish opengl setup*/
|
|
|
|
void finish();
|
|
|
|
/*use linear-sample vertices for LOD mesh*/
|
|
|
|
void updateVerticesForLOD();
|
|
|
|
/*updateIndices */
|
|
|
|
void updateIndicesLOD();
|
|
|
|
|
|
|
|
void updateIndicesLODSkirt();
|
|
|
|
|
|
|
|
/**calculate the average slop of chunk*/
|
|
|
|
void calculateSlope();
|
|
|
|
|
|
|
|
bool getIntersectPointWithRay(const Ray& ray, Vec3& intersectPoint);
|
|
|
|
|
|
|
|
/**current LOD of the chunk*/
|
|
|
|
int _currentLod;
|
|
|
|
|
|
|
|
int _oldLod;
|
|
|
|
|
|
|
|
int _neighborOldLOD[4];
|
|
|
|
/*the left,right,front,back neighbors*/
|
2021-12-25 10:04:45 +08:00
|
|
|
Chunk* _left;
|
|
|
|
Chunk* _right;
|
|
|
|
Chunk* _front;
|
|
|
|
Chunk* _back;
|
2019-11-23 20:27:39 +08:00
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
QuadTree* _parent;
|
2019-11-23 20:27:39 +08:00
|
|
|
|
|
|
|
/**the position X in terrain space*/
|
|
|
|
int _posX;
|
|
|
|
/**the position Y in terrain space*/
|
|
|
|
int _posY;
|
|
|
|
/**parent terrain*/
|
2021-12-25 10:04:45 +08:00
|
|
|
Terrain* _terrain;
|
2019-11-23 20:27:39 +08:00
|
|
|
/**chunk size*/
|
2021-10-23 23:27:14 +08:00
|
|
|
Vec2 _size;
|
2019-11-23 20:27:39 +08:00
|
|
|
/**chunk's estimated slope*/
|
|
|
|
float _slope;
|
|
|
|
std::vector<TerrainVertexData> _currentVertices;
|
|
|
|
|
|
|
|
std::vector<Triangle> _trianglesList;
|
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
backend::Buffer* _buffer = nullptr;
|
2019-11-23 20:27:39 +08:00
|
|
|
MeshCommand _command;
|
|
|
|
};
|
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
/**
|
|
|
|
*QuadTree
|
|
|
|
* @brief use to hierarchically frustum culling and set LOD
|
|
|
|
**/
|
2019-11-23 20:27:39 +08:00
|
|
|
struct CC_DLL QuadTree
|
|
|
|
{
|
|
|
|
/**constructor*/
|
2021-12-25 10:04:45 +08:00
|
|
|
QuadTree(int x, int y, int width, int height, Terrain* terrain);
|
2019-11-23 20:27:39 +08:00
|
|
|
/**destructor*/
|
|
|
|
~QuadTree();
|
|
|
|
/**recursively draw*/
|
|
|
|
void draw();
|
|
|
|
/**recursively set itself and its children is need to draw*/
|
|
|
|
void resetNeedDraw(bool value);
|
|
|
|
/**recursively potential visible culling*/
|
2021-12-25 10:04:45 +08:00
|
|
|
void cullByCamera(const Camera* camera, const Mat4& worldTransform);
|
2019-11-23 20:27:39 +08:00
|
|
|
/**precalculate the AABB(In world space) of each quad*/
|
2021-12-25 10:04:45 +08:00
|
|
|
void preCalculateAABB(const Mat4& worldTransform);
|
|
|
|
QuadTree* _tl;
|
|
|
|
QuadTree* _tr;
|
|
|
|
QuadTree* _bl;
|
|
|
|
QuadTree* _br;
|
2019-11-23 20:27:39 +08:00
|
|
|
/**A flag present current quadTree node whether a terminal node,the terminal node is de facto the chunk*/
|
|
|
|
bool _isTerminal;
|
2021-12-25 10:04:45 +08:00
|
|
|
Chunk* _chunk;
|
2019-11-23 20:27:39 +08:00
|
|
|
int _posX;
|
|
|
|
int _posY;
|
|
|
|
int _height;
|
|
|
|
int _width;
|
2021-12-25 10:04:45 +08:00
|
|
|
QuadTree* _parent;
|
2019-11-23 20:27:39 +08:00
|
|
|
/**AABB's cache (in local space)*/
|
|
|
|
AABB _localAABB;
|
|
|
|
/**AABB's cache (in world space)*/
|
|
|
|
AABB _worldSpaceAABB;
|
2021-12-25 10:04:45 +08:00
|
|
|
Terrain* _terrain;
|
2019-11-23 20:27:39 +08:00
|
|
|
/** a flag determine whether a quadTree node need draw*/
|
|
|
|
bool _needDraw;
|
|
|
|
};
|
|
|
|
friend QuadTree;
|
|
|
|
friend Chunk;
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2019-11-23 20:27:39 +08:00
|
|
|
public:
|
|
|
|
/** set light map texture */
|
2021-12-28 21:27:32 +08:00
|
|
|
void setLightMap(std::string_view fileName);
|
2019-11-23 20:27:39 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
set directional light for the terrain
|
2021-12-25 10:04:45 +08:00
|
|
|
@param lightDir The direction of directional light, Note that lightDir is in the terrain's local space. Most of the
|
|
|
|
time terrain is placed at (0,0,0) and without rotation, so lightDir is also in the world space.
|
2019-11-23 20:27:39 +08:00
|
|
|
*/
|
|
|
|
void setLightDir(const Vec3& lightDir);
|
|
|
|
/*init function*/
|
|
|
|
/**initialize all Properties which terrain need */
|
|
|
|
bool initProperties();
|
|
|
|
/**initialize heightMap data */
|
2021-12-28 21:27:32 +08:00
|
|
|
bool initHeightMap(std::string_view heightMap);
|
2019-11-23 20:27:39 +08:00
|
|
|
/**initialize alphaMap ,detailMaps textures*/
|
|
|
|
bool initTextures();
|
|
|
|
/**create entry*/
|
2021-12-25 10:04:45 +08:00
|
|
|
static Terrain* create(TerrainData& parameter, CrackFixedType fixedType = CrackFixedType::INCREASE_LOWER);
|
2019-11-23 20:27:39 +08:00
|
|
|
/**get specified position's height mapping to the terrain,use bi-linear interpolation method
|
|
|
|
* @param x the X position
|
|
|
|
* @param z the Z position
|
2021-12-25 10:04:45 +08:00
|
|
|
* @param normal the specified position's normal vector in terrain . if this argument is NULL or nullptr,Normal
|
|
|
|
*calculation shall be skip.
|
|
|
|
* @return the height value of the specified position of the terrain, if the (X,Z) position is out of the terrain
|
|
|
|
*bounds,it shall return 0;
|
2019-11-23 20:27:39 +08:00
|
|
|
**/
|
2021-12-25 10:04:45 +08:00
|
|
|
float getHeight(float x, float z, Vec3* normal = nullptr) const;
|
2019-11-23 20:27:39 +08:00
|
|
|
|
|
|
|
/**get specified position's height mapping to the terrain,use bi-linear interpolation method
|
|
|
|
* @param pos the position (X,Z)
|
2021-12-25 10:04:45 +08:00
|
|
|
* @param normal the specified position's normal vector in terrain . if this argument is NULL or nullptr,Normal
|
|
|
|
*calculation shall be skip.
|
|
|
|
* @return the height value of the specified position of the terrain, if the (X,Z) position is out of the terrain
|
|
|
|
*bounds,it shall return 0;
|
2019-11-23 20:27:39 +08:00
|
|
|
**/
|
|
|
|
float getHeight(const Vec2& pos, Vec3* normal = nullptr) const;
|
|
|
|
|
|
|
|
/**get the normal of the specified position in terrain
|
|
|
|
* @return the normal vector of the specified position of the terrain.
|
|
|
|
* @note the fast normal calculation may not get precise normal vector.
|
|
|
|
**/
|
|
|
|
Vec3 getNormal(int pixelX, int pixelY) const;
|
|
|
|
/**get height from the raw height filed*/
|
|
|
|
float getImageHeight(int pixelX, int pixelY) const;
|
|
|
|
/**show the wireline instead of the surface,Debug Use only.
|
|
|
|
* @Note only support desktop platform
|
|
|
|
**/
|
|
|
|
void setDrawWire(bool boolValue);
|
|
|
|
/**
|
|
|
|
* Set threshold distance of each LOD level,must equal or greater than the chunk size
|
|
|
|
* @Note when invoke initHeightMap, the LOD distance will be automatic calculated.
|
|
|
|
*/
|
|
|
|
void setLODDistance(float lod1, float lod2, float lod3);
|
|
|
|
|
|
|
|
/**Switch frustum Culling Flag
|
2021-12-25 10:04:45 +08:00
|
|
|
* @Note frustum culling will remarkable improve your terrain rendering performance.
|
2019-11-23 20:27:39 +08:00
|
|
|
*/
|
|
|
|
void setIsEnableFrustumCull(bool boolValue);
|
|
|
|
|
|
|
|
/** set the alpha map*/
|
2021-12-25 10:04:45 +08:00
|
|
|
void setAlphaMap(cocos2d::Texture2D* newAlphaMapTexture);
|
2019-11-23 20:27:39 +08:00
|
|
|
/**set the Detail Map */
|
|
|
|
void setDetailMap(unsigned int index, DetailMap detailMap);
|
|
|
|
|
|
|
|
// Overrides, internal use only
|
2021-12-25 10:04:45 +08:00
|
|
|
virtual void draw(cocos2d::Renderer* renderer, const cocos2d::Mat4& transform, uint32_t flags) override;
|
2019-11-23 20:27:39 +08:00
|
|
|
/**
|
|
|
|
* Ray-Terrain intersection.
|
|
|
|
* @return the intersection point
|
|
|
|
*/
|
2021-12-25 10:04:45 +08:00
|
|
|
Vec3 getIntersectionPoint(const Ray& ray) const;
|
2019-11-23 20:27:39 +08:00
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
/**
|
|
|
|
* Ray-Terrain intersection.
|
|
|
|
* @param ray to hit the terrain
|
|
|
|
* @param intersectionPoint hit point if hit
|
|
|
|
* @return true if hit, false otherwise
|
|
|
|
*/
|
|
|
|
bool getIntersectionPoint(const Ray& ray, Vec3& intersectionPoint) const;
|
2019-11-23 20:27:39 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* set the MaxDetailAmount.
|
|
|
|
*/
|
|
|
|
void setMaxDetailMapAmount(int maxValue);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Convert a world Space position (X,Z) to terrain space position (X,Z)
|
|
|
|
*/
|
|
|
|
Vec2 convertToTerrainSpace(const Vec2& worldSpace) const;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* reset the heightmap data.
|
|
|
|
*/
|
2021-12-28 21:27:32 +08:00
|
|
|
void resetHeightMap(std::string_view heightMap);
|
2019-11-23 20:27:39 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* get the terrain's minimal height.
|
|
|
|
*/
|
|
|
|
float getMinHeight();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* get the terrain's maximal height.
|
|
|
|
*/
|
|
|
|
float getMaxHeight();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* get the terrain's AABB(in world space)
|
|
|
|
*/
|
|
|
|
AABB getAABB();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* set the skirt height ratio
|
|
|
|
*/
|
|
|
|
void setSkirtHeightRatio(float ratio);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* get the terrain's quad tree which is also the root node.
|
|
|
|
*/
|
2021-12-25 10:04:45 +08:00
|
|
|
QuadTree* getQuadTree();
|
2019-11-23 20:27:39 +08:00
|
|
|
|
|
|
|
void reload();
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2019-11-23 20:27:39 +08:00
|
|
|
/**
|
|
|
|
* get the terrain's size
|
|
|
|
*/
|
2021-10-23 23:27:14 +08:00
|
|
|
Vec2 getTerrainSize() const { return Vec2(static_cast<float>(_imageWidth), static_cast<float>(_imageHeight)); }
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2019-11-23 20:27:39 +08:00
|
|
|
/**
|
|
|
|
* get the terrain's height data
|
|
|
|
*/
|
|
|
|
std::vector<float> getHeightData() const;
|
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
CC_CONSTRUCTOR_ACCESS : Terrain();
|
2019-11-23 20:27:39 +08:00
|
|
|
virtual ~Terrain();
|
2021-12-25 10:04:45 +08:00
|
|
|
bool initWithTerrainData(TerrainData& parameter, CrackFixedType fixedType);
|
|
|
|
|
2019-11-23 20:27:39 +08:00
|
|
|
protected:
|
|
|
|
/**
|
|
|
|
* recursively set each chunk's LOD
|
|
|
|
* @param cameraPos the camera position in world space
|
|
|
|
**/
|
|
|
|
void setChunksLOD(const Vec3& cameraPos);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* load Vertices from height filed for the whole terrain.
|
|
|
|
**/
|
|
|
|
void loadVertices();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* calculate Normal Line for each Vertex
|
|
|
|
**/
|
|
|
|
void calculateNormal();
|
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
// override
|
2019-11-23 20:27:39 +08:00
|
|
|
virtual void onEnter() override;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* cache all uniform locations in GLSL.
|
|
|
|
**/
|
|
|
|
void cacheUniformAttribLocation();
|
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
// IBO generate & cache
|
|
|
|
ChunkIndices lookForIndicesLODSkrit(int selfLod, bool* result);
|
2019-11-23 20:27:39 +08:00
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
ChunkIndices lookForIndicesLOD(int neighborLod[4], int selfLod, bool* result);
|
2019-11-23 20:27:39 +08:00
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
ChunkIndices insertIndicesLOD(int neighborLod[4], int selfLod, uint16_t* indices, int size);
|
2019-11-23 20:27:39 +08:00
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
ChunkIndices insertIndicesLODSkirt(int selfLod, uint16_t* indices, int size);
|
|
|
|
|
|
|
|
Chunk* getChunkByIndex(int x, int y) const;
|
2019-11-23 20:27:39 +08:00
|
|
|
|
|
|
|
private:
|
|
|
|
void onBeforeDraw();
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2019-11-23 20:27:39 +08:00
|
|
|
void onAfterDraw();
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2019-11-23 20:27:39 +08:00
|
|
|
protected:
|
2021-12-25 10:04:45 +08:00
|
|
|
std::vector<ChunkLODIndices> _chunkLodIndicesSet;
|
2019-11-23 20:27:39 +08:00
|
|
|
std::vector<ChunkLODIndicesSkirt> _chunkLodIndicesSkirtSet;
|
|
|
|
Mat4 _CameraMatrix;
|
|
|
|
bool _isCameraViewChanged;
|
|
|
|
TerrainData _terrainData;
|
|
|
|
bool _isDrawWire;
|
2021-12-25 10:04:45 +08:00
|
|
|
unsigned char* _data;
|
2019-11-23 20:27:39 +08:00
|
|
|
float _lodDistance[3];
|
2021-12-25 10:04:45 +08:00
|
|
|
Texture2D* _detailMapTextures[4];
|
|
|
|
Texture2D* _alphaMap;
|
|
|
|
Texture2D* _lightMap;
|
|
|
|
Texture2D* _dummyTexture = nullptr;
|
2019-11-23 20:27:39 +08:00
|
|
|
Vec3 _lightDir;
|
2021-12-25 10:04:45 +08:00
|
|
|
QuadTree* _quadRoot;
|
|
|
|
Chunk* _chunkesArray[MAX_CHUNKES][MAX_CHUNKES];
|
2019-11-23 20:27:39 +08:00
|
|
|
std::vector<TerrainVertexData> _vertices;
|
|
|
|
std::vector<unsigned int> _indices;
|
|
|
|
int _imageWidth;
|
|
|
|
int _imageHeight;
|
2021-10-23 23:27:14 +08:00
|
|
|
Vec2 _chunkSize;
|
2019-11-23 20:27:39 +08:00
|
|
|
bool _isEnableFrustumCull;
|
|
|
|
int _maxDetailMapValue;
|
2021-12-25 10:04:45 +08:00
|
|
|
cocos2d::Image* _heightMapImage;
|
2019-11-23 20:27:39 +08:00
|
|
|
Mat4 _oldCameraModelMatrix;
|
|
|
|
Mat4 _terrainModelMatrix;
|
|
|
|
float _maxHeight;
|
|
|
|
float _minHeight;
|
|
|
|
CrackFixedType _crackFixedType;
|
|
|
|
float _skirtRatio;
|
|
|
|
int _skirtVerticesOffset[4];
|
2021-12-25 10:04:45 +08:00
|
|
|
struct StateBlock
|
|
|
|
{
|
|
|
|
// bool blend;
|
|
|
|
bool depthWrite = true;
|
|
|
|
bool depthTest = true;
|
2019-11-23 20:27:39 +08:00
|
|
|
backend::CullMode cullFace = backend::CullMode::FRONT;
|
2021-12-25 10:04:45 +08:00
|
|
|
backend::Winding winding = backend::Winding::CLOCK_WISE;
|
2019-11-23 20:27:39 +08:00
|
|
|
void apply();
|
|
|
|
void save();
|
|
|
|
};
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2019-11-23 20:27:39 +08:00
|
|
|
StateBlock _stateBlock;
|
|
|
|
StateBlock _stateBlockOld;
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2019-11-23 20:27:39 +08:00
|
|
|
private:
|
2021-12-25 10:04:45 +08:00
|
|
|
// uniform locations
|
2019-11-23 20:27:39 +08:00
|
|
|
backend::UniformLocation _detailMapLocation[4];
|
|
|
|
backend::UniformLocation _alphaMapLocation;
|
|
|
|
backend::UniformLocation _alphaIsHasAlphaMapLocation;
|
|
|
|
backend::UniformLocation _lightMapCheckLocation;
|
|
|
|
backend::UniformLocation _lightMapLocation;
|
|
|
|
backend::UniformLocation _detailMapSizeLocation;
|
|
|
|
backend::UniformLocation _lightDirLocation;
|
|
|
|
|
|
|
|
backend::UniformLocation _mvpMatrixLocation;
|
|
|
|
#if CC_ENABLE_CACHE_TEXTURE_DATA
|
|
|
|
EventListenerCustom* _backToForegroundListener;
|
|
|
|
#endif
|
|
|
|
};
|
|
|
|
|
|
|
|
// end of actions group
|
|
|
|
/// @}
|
|
|
|
|
|
|
|
NS_CC_END
|