/* ----------------------------------------------------------------------------- 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 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 heightmap; Array attribmap; int heightmap_w, heightmap_h; float unit; AutoPtr 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 &, 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 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 &, 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__