1 /**************************************************************************/ 2 /* Copyright 2009 Tim Day */ 3 /* */ 4 /* This file is part of Fracplanet */ 5 /* */ 6 /* Fracplanet is free software: you can redistribute it and/or modify */ 7 /* it under the terms of the GNU General Public License as published by */ 8 /* the Free Software Foundation, either version 3 of the License, or */ 9 /* (at your option) any later version. */ 10 /* */ 11 /* Fracplanet is distributed in the hope that it will be useful, */ 12 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ 13 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ 14 /* GNU General Public License for more details. */ 15 /* */ 16 /* You should have received a copy of the GNU General Public License */ 17 /* along with Fracplanet. If not, see <http://www.gnu.org/licenses/>. */ 18 /**************************************************************************/ 19 20 #ifndef _triangle_mesh_h_ 21 #define _triangle_mesh_h_ 22 23 #include "common.h" 24 #include "geometry.h" 25 #include "parameters_save.h" 26 #include "parameters_terrain.h" 27 #include "progress.h" 28 #include "random.h" 29 #include "triangle.h" 30 #include "triangle_edge.h" 31 #include "vertex.h" 32 33 /*! \file 34 \brief Interface for class TriangleMesh. 35 */ 36 37 //! Contains vertices and triangles of a triangle mesh. 38 /*! Abstract base class because specific classes must specify a geometry. 39 Not as general-purpose as it might be due to constraints imposed by OpenGL. 40 In particular, Triangle can have no attributes (e.g normal, colour) if a single 41 OpenGL call is to be made to draw all triangles, so this information is entirely associated with Vertex. 42 Two colours can be associated with each vertex 43 (required for fracplanet application to obtain sharp coastlines), 44 and it it a requirement for subclasses to sort triangles so that all 45 those before _triangle_switch_colour use vertex colour index 0, 46 and those afterwards vertex colour index 1. 47 \todo The geometry() method is a mess. 48 It would surely be better to have a Geometry* in the base class passed in via the constructor. 49 */ 50 class TriangleMesh 51 { 52 public: 53 54 //! Constructor. 55 TriangleMesh(Progress* progress); 56 57 //! Destructor. 58 virtual ~TriangleMesh(); 59 60 //! Accessor set_emissive(float e)61 void set_emissive(float e) 62 { 63 _emissive=e; 64 } 65 66 //! Accessor emissive()67 float emissive() const 68 { 69 return _emissive; 70 } 71 72 //! Append a vertex. add_vertex(const Vertex & v)73 void add_vertex(const Vertex& v) 74 { 75 _vertex.push_back(v); 76 } 77 78 //! Append a triangle. add_triangle(const Triangle & t)79 void add_triangle(const Triangle& t) 80 { 81 _triangle.push_back(t); 82 } 83 84 //! Accessor. vertex(uint i)85 const Vertex& vertex(uint i) const 86 { 87 return _vertex[i]; 88 } 89 90 //! Accessor. triangle(uint i)91 const Triangle& triangle(uint i) const 92 { 93 return _triangle[i]; 94 } 95 96 //! Access the geometry of this class (needed to abstract concepts like "mid-point" and "height"). 97 virtual const Geometry& geometry() const 98 =0; 99 100 //! Return height of a vertex. vertex_height(uint i)101 float vertex_height(uint i) const 102 { 103 return geometry().height(vertex(i).position()); 104 } 105 106 //! Set height of a vertex. set_vertex_height(uint i,float h)107 void set_vertex_height(uint i,float h) 108 { 109 XYZ p(vertex(i).position()); 110 geometry().set_height(p,h); 111 vertex(i).position(p); 112 } 113 114 //! Return minimum height of a triangle's vertices. triangle_height_min(uint i)115 float triangle_height_min(uint i) const 116 { 117 const Triangle& t=triangle(i); 118 return minimum 119 ( 120 vertex_height(t.vertex(0)), 121 vertex_height(t.vertex(1)), 122 vertex_height(t.vertex(2)) 123 ); 124 } 125 126 //! Return maximum height of a triangle's vertices. triangle_height_max(uint i)127 float triangle_height_max(uint i) const 128 { 129 const Triangle& t=triangle(i); 130 return maximum 131 ( 132 vertex_height(t.vertex(0)), 133 vertex_height(t.vertex(1)), 134 vertex_height(t.vertex(2)) 135 ); 136 } 137 138 //! Return mean height of a triangle's vertices. triangle_height_average(uint i)139 float triangle_height_average(uint i) const 140 { 141 const Triangle& t=triangle(i); 142 return 143 ( 144 vertex_height(t.vertex(0)) 145 +vertex_height(t.vertex(1)) 146 +vertex_height(t.vertex(2)) 147 )/3.0; 148 } 149 150 //! Compute and return the normal to a triangle 151 const XYZ triangle_normal(uint i) const; 152 153 //! Return which vertex colour to use for a triangle. which_colour_for_triangle(uint t)154 uint which_colour_for_triangle(uint t) const 155 { 156 return (t<_triangle_switch_colour ? 0 : 1); 157 } 158 159 //! Returns number of vertices in mesh. vertices()160 uint vertices() const 161 { 162 return _vertex.size(); 163 } 164 //! Returns number of triangles in mesh. triangles()165 uint triangles() const 166 { 167 return _triangle.size(); 168 } 169 170 //! Returns number of triangles in mesh indexing colour[0] of vertices. triangles_of_colour0()171 uint triangles_of_colour0() const 172 { 173 return _triangle_switch_colour; 174 } 175 176 //! Returns number of triangles in mesh indexing colour[1] of vertices. triangles_of_colour1()177 uint triangles_of_colour1() const 178 { 179 return triangles()-_triangle_switch_colour; 180 } 181 182 //! (Re-)computes vertex normals. 183 void compute_vertex_normals(); 184 185 //! Perform a single subdivision pass with perturbations up to the specified size 186 void subdivide(const XYZ& variation,uint level,uint levels); 187 188 //! Perform a number of subdivisions, possibly some unperturbed ("flat"), and halving the perturbation variation each iteration. 189 void subdivide(uint subdivisions,uint flat_subdivisions,const XYZ& variation); 190 191 //! Dump the mesh to the file in a form suitable for use by POVRay. 192 void write_povray(std::ofstream& out,bool exclude_alternate_colour,bool double_illuminate,bool no_shadow) const; 193 194 //! Dump the mesh to the file in a form suitable for use by Blender. 195 void write_blender(std::ofstream& out,const std::string& mesh_name,const FloatRGBA* fake_alpha) const; 196 197 protected: 198 199 //! The vertices of this mesh. 200 std::vector<Vertex> _vertex; 201 202 //! The triangles of this mesh. 203 std::vector<Triangle> _triangle; 204 205 //! The index of the triangle at which we switch to the alternate colour. 206 uint _triangle_switch_colour; 207 208 //! The emission level for vertices with the _emissive flag set 209 float _emissive; 210 211 //! Pointer to the progress object to which progress reports should be made. 212 Progress*const _progress; 213 214 //! Accessor. vertex(uint i)215 Vertex& vertex(uint i) 216 { 217 return _vertex[i]; 218 } 219 220 //! Accessor. triangle(uint i)221 Triangle& triangle(uint i) 222 { 223 return _triangle[i]; 224 } 225 226 //! Convenience wrapper with null test. 227 void progress_start(uint steps,const std::string& info) const; 228 229 //! Convenience wrapper with null test. 230 void progress_stall(const std::string& reason) const; 231 232 //! Convenience wrapper with null test. 233 void progress_step(uint step) const; 234 235 //! Convenience wrapper with null test. 236 void progress_complete(const std::string& info) const; 237 238 private: 239 240 //! Fake per-vertex alpha for Blender. 241 static ByteRGBA blender_alpha_workround(const ByteRGBA*,const ByteRGBA&); 242 }; 243 244 //! A single triangle lying in the z-plane. 245 class TriangleMeshFlat : virtual public TriangleMesh 246 { 247 public: 248 249 //! Constructor. 250 TriangleMeshFlat(ParametersObject::ObjectType obj,float z,uint seed,Progress* progress); 251 252 //! Destructor. ~TriangleMeshFlat()253 ~TriangleMeshFlat() 254 {} 255 256 //! Returns the specific geometry. geometry()257 virtual const Geometry& geometry() const 258 { 259 return _geometry; 260 } 261 262 private: 263 264 //! The specifc geometry for this mesh. 265 GeometryFlat _geometry; 266 }; 267 268 //! An icosahedron. 269 class TriangleMeshIcosahedron : virtual public TriangleMesh 270 { 271 public: 272 273 //! Constructor. 274 TriangleMeshIcosahedron(float radius,uint seed,Progress* progress); 275 276 //! Destructor. ~TriangleMeshIcosahedron()277 ~TriangleMeshIcosahedron() 278 {} 279 280 //! Returns the specific geometry. geometry()281 virtual const Geometry& geometry() const 282 { 283 return _geometry; 284 } 285 286 private: 287 288 //! The specifc geometry for this mesh. 289 GeometrySpherical _geometry; 290 }; 291 292 //! A subdivided icosahedron. 293 class TriangleMeshSubdividedIcosahedron : public TriangleMeshIcosahedron 294 { 295 public: 296 297 //! Constructor. 298 TriangleMeshSubdividedIcosahedron(float radius,uint subdivisions,uint flat_subdivisions,uint seed,const XYZ& variation,Progress* progress); 299 300 //! Destructor. ~TriangleMeshSubdividedIcosahedron()301 ~TriangleMeshSubdividedIcosahedron() 302 {} 303 }; 304 305 #endif 306