209 lines
4.7 KiB
C++
209 lines
4.7 KiB
C++
/* -----------------------------------------------------------------------------
|
|
GSFramework
|
|
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
|
----------------------------------------------------------------------------- */
|
|
|
|
|
|
#ifndef __NTERRAIN__
|
|
#define __NTERRAIN__
|
|
|
|
|
|
#include "core/renderable.h"
|
|
#include "core/item.h"
|
|
#include "core/material.h"
|
|
#include "geometry/rect.h"
|
|
|
|
|
|
namespace GS {
|
|
namespace Core {
|
|
class Terrain;
|
|
class Geometry;
|
|
|
|
struct Patch
|
|
{
|
|
Terrain *terrain;
|
|
|
|
int u, v, w, h;
|
|
int decimation;
|
|
|
|
MinMax minmax;
|
|
|
|
iRect GetRect() const { return iRect(u, v, u + w, v + h); }
|
|
|
|
AutoPtr <Patch> children[4];
|
|
|
|
Patch() : terrain(0) {}
|
|
};
|
|
|
|
/*
|
|
@short Terrain.
|
|
@author Emmanuel Julien (ejulien@gsworks.fr)
|
|
*/
|
|
class Terrain : public Item, public Renderable
|
|
{
|
|
public:
|
|
|
|
struct Attrib
|
|
{
|
|
char nx, ny, nz;
|
|
};
|
|
|
|
struct Layer
|
|
{
|
|
bool enabled;
|
|
|
|
String diffuse, specular, normal, self;
|
|
float angle, tiling;
|
|
|
|
Layer()
|
|
{
|
|
enabled = true;
|
|
|
|
angle = 0.f;
|
|
tiling = 1.f;
|
|
}
|
|
};
|
|
|
|
protected:
|
|
|
|
float width, depth;
|
|
|
|
Array <float> heightmap;
|
|
Array <Attrib> attribmap;
|
|
|
|
int heightmap_w, heightmap_h;
|
|
float unit;
|
|
|
|
AutoPtr <Patch> root_node;
|
|
uint node_count;
|
|
|
|
void UpdatePatchMinMax(Patch *node) const;
|
|
|
|
/// Cull terrain primitive and push to the render queue.
|
|
void CullRenderablePrimitiveList(const Camera &view, const Camera &default_view, Stack <Render::Primitive *> &, Context, Patch *);
|
|
/// Helper function to create a geometry object for a given terrain patch.
|
|
Geometry *CreateNodeGeometry(const Patch *);
|
|
/// Build the terrain quad-tree for a specific terrain part.
|
|
Patch *BuildTerrainStaticQuadtree(int u, int v, int w, int h, int decimation, int depth);
|
|
|
|
/// Update a quadtree patch.
|
|
void UpdateQuadtreePatch(Patch *patch, iRect &update_rect);
|
|
|
|
/// Layer to tag.
|
|
NML::Tag *LayerAsMetaTag(int index);
|
|
|
|
public:
|
|
|
|
Layer layer[4];
|
|
|
|
/// Terrain render data.
|
|
struct RenderData
|
|
{
|
|
struct Layer
|
|
{
|
|
Render::sTexture diffuse, specular, normal, self;
|
|
};
|
|
|
|
Layer layer[4];
|
|
|
|
Render::sTexture blendmap;
|
|
Render::sMaterial material;
|
|
};
|
|
|
|
///
|
|
struct TraceResult
|
|
{
|
|
bool has_hit;
|
|
Vector4 w_i; ///< Intersection in world space.
|
|
Vector2 uv;
|
|
};
|
|
|
|
String material;
|
|
|
|
String heightmap_path,
|
|
blendmap_path,
|
|
shader_path;
|
|
|
|
AutoPtr <RenderData> render_data;
|
|
|
|
/// Compute the renderable bounding box.
|
|
virtual void ComputeRenderableMinMax(MinMax &);
|
|
/// Get the renderable primitive list.
|
|
virtual uint GetRenderablePrimitiveList(const Camera &view, const Camera &default_view, Stack <Render::Primitive *> &, Context = Context_Default, bool cull = true);
|
|
|
|
bool Raytrace(const Vector4 &s, const Vector4 &d, TraceResult &, float len = -1.f);
|
|
|
|
/*!
|
|
@short Apply several blur passes to the heightmap.
|
|
@note The normals are not blurred, so you might want to recompute
|
|
them when done.
|
|
*/
|
|
void ApplyBlur(int pass_count = 1);
|
|
/// Compute normals from the heightmap.
|
|
void ComputeNormals(int u = 0, int v = 0, int w = 0, int h = 0);
|
|
|
|
float GetWidth() const { return width; }
|
|
float GetDepth() const { return depth; }
|
|
|
|
/*!
|
|
@short Return the terrain normal for a given sample.
|
|
@note For performance critical code you might want to use the
|
|
attribute map directly.
|
|
*/
|
|
Vector4 GetNormalAt(int u, int v) const;
|
|
|
|
Attrib *GetAttributesMap() const { return attribmap; }
|
|
Attrib *GetAttributesMapAt(int u, int v) const;
|
|
|
|
float *GetHeightmap() const { return heightmap; }
|
|
int GetHeightmapWidth() const { return heightmap_w; }
|
|
int GetHeightmapHeight() const { return heightmap_h; }
|
|
int GetHeightmapPitch() const { return heightmap_w + 1; }
|
|
float GetUnit() const { return unit; }
|
|
|
|
bool LocalToTexture(const Vector4 &, float w, float h, float &u, float &v) const;
|
|
bool LocalToHeightmap(const Vector4 &p, float &u, float &v) const;
|
|
|
|
/// Sample height in heightmap space.
|
|
float SampleHeight(float u, float v) const;
|
|
/// Sample height in local space.
|
|
float SampleHeight(const Vector4 &) const;
|
|
|
|
/// Update a terrain quadtree zone.
|
|
void UpdateQuadtree(int u = 0, int v = 0, int w = 0, int h = 0);
|
|
|
|
Patch *BuildQuadtree();
|
|
|
|
void RenderSetup(ResourceFactories * = 0);
|
|
|
|
/// Set heightmap from file.
|
|
bool FromPicture(const char *, int blur_pass_count = 0);
|
|
|
|
/*!
|
|
@name Height map I/O.
|
|
@{
|
|
*/
|
|
bool LoadHeightmap(const char *);
|
|
bool SaveHeightmap(const char *);
|
|
/// @}
|
|
|
|
/*!
|
|
@short Allocate terrain.
|
|
@note This function does not allocate terrain patches.
|
|
*/
|
|
bool Allocate(uint w_res, uint h_res, float unit);
|
|
void Free();
|
|
|
|
bool FromMetaTag(NML::Tag &);
|
|
NML::Tag *AsMetaTag();
|
|
|
|
Terrain();
|
|
virtual ~Terrain();
|
|
};
|
|
|
|
} // Core
|
|
} // GS
|
|
|
|
|
|
#endif // __NTERRAIN__
|