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 #include "triangle_mesh_terrain.h"
21 
22 #include <map>
23 
24 #include "noise.h"
25 
TriangleMeshTerrain(Progress * progress)26 TriangleMeshTerrain::TriangleMeshTerrain(Progress* progress)
27   :TriangleMesh(progress)
28   ,max_height(0.0)
29 {}
30 
~TriangleMeshTerrain()31 TriangleMeshTerrain::~TriangleMeshTerrain()
32 {}
33 
34 
do_noise(const ParametersTerrain & parameters)35 void TriangleMeshTerrain::do_noise(const ParametersTerrain& parameters)
36 {
37   if (parameters.noise.terms==0 || parameters.noise.amplitude==0) return;
38 
39   const uint steps=vertices();
40   uint step=0;
41 
42   progress_start(100,"Noise");
43 
44   MultiscaleNoise noise(parameters.seed,parameters.noise.terms,parameters.noise.amplitude_decay);
45   for (uint i=0;i<vertices();i++)
46     {
47       step++;
48       progress_step((100*step)/steps);
49 
50       const float h=vertex_height(i);
51       const float p=parameters.noise.amplitude*noise(parameters.noise.frequency*vertex(i).position());
52 
53       set_vertex_height(i,h+p);
54     }
55 
56   progress_complete("Noise complete");
57 }
58 
do_sea_level(const ParametersTerrain &)59 void TriangleMeshTerrain::do_sea_level(const ParametersTerrain& /*parameters*/)
60 {
61   // Introduce sea level
62   const uint steps=vertices()+triangles();
63   uint step=0;
64 
65   progress_start(100,"Sea level");
66   {
67     std::vector<bool> sea_vertices(vertices());    // Flag vertices forced to sea level
68 
69     for (uint i=0;i<vertices();i++)
70       {
71 	step++;
72 	progress_step((100*step)/steps);
73 
74 	const float m=vertex_height(i);
75 
76 	if (m<=0.0)
77 	  {
78 	    set_vertex_height(i,0.0);
79 	    sea_vertices[i]=true;
80 	  }
81 	else if (m>max_height)
82 	  max_height=m;
83       }
84 
85     std::vector<Triangle> land_sea[2];
86 
87     for (uint i=0;i<triangles();i++)
88       {
89 	step++;
90 	progress_step((100*step)/steps);
91 
92 	const Triangle& t=triangle(i);
93 	land_sea[sea_vertices[t.vertex(0)] && sea_vertices[t.vertex(1)] && sea_vertices[t.vertex(2)]].push_back(t);
94       }
95 
96     _triangle_switch_colour=land_sea[0].size();
97     _triangle=land_sea[0];
98     _triangle.insert(_triangle.end(),land_sea[1].begin(),land_sea[1].end());
99   }
100   progress_complete("Sea level completed");
101 }
102 
do_power_law(const ParametersTerrain & parameters)103 void TriangleMeshTerrain::do_power_law(const ParametersTerrain& parameters)
104 {
105   const uint steps=vertices();
106   uint step=0;
107 
108   progress_start(100,"Power law");
109 
110   for (uint i=0;i<vertices();i++)
111     {
112       step++;
113       progress_step((100*step)/steps);
114 
115       const float h=vertex_height(i);
116       if (h>geometry().epsilon())
117 	set_vertex_height(i,max_height*pow(h/max_height,parameters.power_law));
118     }
119 
120   progress_complete("Power law completed");
121 }
122 
insert_unique(std::vector<uint> & v,uint x)123 inline void insert_unique(std::vector<uint>& v,uint x)
124 {
125   if (std::find(v.begin(),v.end(),x)==v.end()) v.push_back(x);
126 }
127 
do_rivers(const ParametersTerrain & parameters)128 void TriangleMeshTerrain::do_rivers(const ParametersTerrain& parameters)
129 {
130   if (parameters.rivers==0) return;
131 
132   Random01 r01(parameters.rivers_seed);
133 
134   std::vector<bool> is_sea_vertex(vertices());
135 
136   // Used to use a vector of sets, but this saves memory and there aren't many elements to each set
137   std::vector<std::vector<uint> > vertex_neighbours(vertices());
138 
139   progress_start(100,"River preparation");
140 
141   const uint prep_steps=triangles();
142   uint step=0;
143 
144   // Need to know each vertex's neighbours (for land vertices)
145   for (uint i=0;i<triangles_of_colour0();i++)
146     {
147       step++;
148       progress_step((100*step)/prep_steps);
149 
150       const Triangle& t=triangle(i);
151       insert_unique(vertex_neighbours[t.vertex(0)],t.vertex(1));
152       insert_unique(vertex_neighbours[t.vertex(0)],t.vertex(2));
153       insert_unique(vertex_neighbours[t.vertex(1)],t.vertex(0));
154       insert_unique(vertex_neighbours[t.vertex(1)],t.vertex(2));
155       insert_unique(vertex_neighbours[t.vertex(2)],t.vertex(0));
156       insert_unique(vertex_neighbours[t.vertex(2)],t.vertex(1));
157     }
158 
159   for (uint i=triangles_of_colour0();i!=triangles();i++)
160     {
161       step++;
162       progress_step((100*step)/prep_steps);
163 
164       const Triangle& t=triangle(i);
165       is_sea_vertex[t.vertex(0)]=true;
166       is_sea_vertex[t.vertex(1)]=true;
167       is_sea_vertex[t.vertex(2)]=true;
168     }
169 
170   progress_complete("River preparation completed");
171 
172   progress_start(100,"Rivers");
173 
174   const uint maximum_lake_size=(uint)(vertices()*parameters.lake_becomes_sea);
175 
176   const uint steps=parameters.rivers;
177   step=0;
178 
179   for (uint r=0;r<parameters.rivers;r++)
180     {
181       step++;
182       progress_step((100*step)/steps);
183 
184       unsigned int last_stall_warning=0;
185 
186       std::set<uint> vertices_to_add;
187       // Also track the height of vertices in the river.
188       // When a river level rise is forced we can look for upstream points to bring back into the current set
189       std::multimap<float,uint> vertices_to_add_by_height;
190 
191       std::set<uint> current_vertices;
192       float current_vertices_height;
193 
194       // Pick a random non sea triangle to start river
195       // Would like to use __gnu_cxx::random_sample_n but can't get it to work
196       uint source_vertex=(uint)(r01()*vertices());
197 
198       // Rivers starting in the sea are skipped to keep river density independent of land area, and to avoid lock-up on all-sea planets
199       if (is_sea_vertex[source_vertex])
200 	continue;
201 
202       current_vertices.insert(source_vertex);
203       current_vertices_height=vertex_height(source_vertex);
204 
205       while(true)
206 	{
207 	  bool reached_sea=false;
208 	  std::set<uint> current_vertices_neighbours;
209 
210 	  for (std::set<uint>::const_iterator it=current_vertices.begin();it!=current_vertices.end();it++)
211 	    {
212 	      vertices_to_add.insert(*it);
213 	      vertices_to_add_by_height.insert(std::make_pair(current_vertices_height,*it));
214 	      reached_sea|=(is_sea_vertex[*it]);
215 
216 	      const std::vector<uint>& neighbours=vertex_neighbours[*it];
217 
218 	      // Only vertices NOT in the current river section are of interest
219 	      for (std::vector<uint>::const_iterator it_n=neighbours.begin();it_n!=neighbours.end();it_n++)
220 		{
221 		  if (current_vertices.find(*it_n)==current_vertices.end())
222 		    current_vertices_neighbours.insert(*it_n);
223 		}
224 	    }
225 
226 	  // Find the heights of everything we could flow to
227 	  std::multimap<float,uint> flow_candidates;
228 	  for (std::set<uint>::const_iterator it=current_vertices_neighbours.begin();it!=current_vertices_neighbours.end();it++)
229 	    {
230 	      flow_candidates.insert(std::multimap<float,uint>::value_type(vertex_height(*it),*it));
231 	    }
232 
233 	  if (reached_sea)
234 	    {
235 	      break;
236 	    }
237 	  else if (current_vertices.size()>=maximum_lake_size)
238 	    {
239 	      break;  // Lake becomes an inland sea
240 	    }
241 	  else
242 	    {
243 	      // If there is any intersection between the current river hexes and completed rivers then we're done
244 	      bool meets_existing=false;
245 	      for (std::set<uint>::const_iterator it=current_vertices.begin();it!=current_vertices.end();it++)
246 		{
247 		  if (river_vertices.find(*it)!=river_vertices.end())
248 		    {
249 		      meets_existing=true;
250 		      break;
251 		    }
252 		}
253 	      if (meets_existing)
254 		{
255 		  break;
256 		}
257 	    }
258 
259 	  unsigned int num_current_vertices=0;
260 	  if (flow_candidates.empty()) // Not sure how this could ever happen, but just to be safe...
261 	    {
262 	      std::cerr << "Warning: Unexpected internal state: no flow candidates for a river\n";
263 	      break;
264 	    }
265 	  else if ((*(flow_candidates.begin())).first<current_vertices_height-geometry().epsilon())  // Can flow downhill...
266 	    {
267 	      // We just flow into ONE vertex, otherwise rivers will expand to inundate all lower terrain
268 	      current_vertices.clear();
269 	      current_vertices_height=(*(flow_candidates.begin())).first;
270 	      current_vertices.insert((*(flow_candidates.begin())).second);
271 	      num_current_vertices=1;
272 	      //std::cerr << "-" << current_vertices.size();
273 	    }
274 	  else if ((*(flow_candidates.begin())).first<current_vertices_height+geometry().epsilon())  // Or expand across flat...
275 	    {
276 	      // But if there are multiple candidates on the same level, flow into all of them
277 	      std::multimap<float,uint>::const_iterator flat_end=flow_candidates.upper_bound(current_vertices_height+geometry().epsilon());
278 
279 	      for (std::multimap<float,uint>::const_iterator it_flat=flow_candidates.begin();it_flat!=flat_end;it_flat++)
280 		{
281 		  current_vertices.insert((*it_flat).second);
282 		}
283 	      num_current_vertices=current_vertices.size();
284 	      //std::cerr << "=" << current_vertices.size();
285 	    }
286 	  else // Otherwise the water level must rise to height of the lowest flow candidate
287 	    {
288 	      current_vertices_height=(*(flow_candidates.begin())).first+geometry().epsilon();   // Rise a bit more to avoid getting stuck due to precision.
289 	      const uint outflow_vertex=(*(flow_candidates.begin())).second;
290 	      current_vertices.insert(outflow_vertex);
291 
292 	      // Any vertices upstream below the new height should now become part of the current set, and have their level raised.
293 	      std::multimap<float,uint>::iterator backflow_end=vertices_to_add_by_height.upper_bound(current_vertices_height);
294 	      for (std::multimap<float,uint>::iterator it=vertices_to_add_by_height.begin();it!=backflow_end;it++)
295 		{
296 		  const uint v=(*it).second;
297 		  current_vertices.insert(v);
298 		  set_vertex_height(v,current_vertices_height);
299 		}
300 	      vertices_to_add_by_height.erase(vertices_to_add_by_height.begin(),backflow_end);
301 
302 	      // Raise level of everything in the working set
303 	      // Also count vertices rather than having .size() iterate over them again.
304 	      for (std::set<uint>::const_iterator it=current_vertices.begin();it!=current_vertices.end();it++)
305 		{
306 		  set_vertex_height(*it,current_vertices_height);
307 		  num_current_vertices++;
308 		}
309 	      //std::cerr << "+" << current_vertices.size();
310 	    }
311 
312 	  if (num_current_vertices>=last_stall_warning+100)
313 	    {
314 	      std::ostringstream msg;
315 	      msg << "Rivers (delay: " << num_current_vertices << " vertex lake)";
316 	      progress_stall(msg.str());
317 	      last_stall_warning=num_current_vertices;
318 	    }
319 	  else if (num_current_vertices+100<=last_stall_warning)
320 	    {
321 	      std::ostringstream msg;
322 	      msg << "Rivers: lake complete";
323 	      progress_stall(msg.str());
324 	      last_stall_warning=num_current_vertices;
325 	    }
326 	}
327 
328       river_vertices.insert(vertices_to_add.begin(),vertices_to_add.end());
329     }
330 
331   progress_complete("Rivers completed");
332 }
333 
do_colours(const ParametersTerrain & parameters)334 void TriangleMeshTerrain::do_colours(const ParametersTerrain& parameters)
335 {
336   const uint steps=triangles_of_colour1()+vertices();
337   uint step=0;
338 
339   progress_start(100,"Colouring");
340 
341   // Colour any triangles which need colouring (ie just sea)
342   ByteRGBA colour_ocean(parameters.colour_ocean);
343   ByteRGBA colour_river(parameters.colour_river);
344   if (parameters.oceans_and_rivers_emissive>0.0f)
345     {
346       colour_ocean.a=0;
347       colour_river.a=0;
348     }
349 
350   for (uint i=triangles_of_colour0();i!=triangles();i++)
351     {
352       step++;
353       progress_step((100*step)/steps);
354 
355       vertex(triangle(i).vertex(0)).colour(1,colour_ocean);
356       vertex(triangle(i).vertex(1)).colour(1,colour_ocean);
357       vertex(triangle(i).vertex(2)).colour(1,colour_ocean);
358 
359       // For debugging, set the colour0 of those triangles to red
360       vertex(triangle(i).vertex(0)).colour(0,ByteRGBA(255,0,0,255));
361       vertex(triangle(i).vertex(1)).colour(0,ByteRGBA(255,0,0,255));
362       vertex(triangle(i).vertex(2)).colour(0,ByteRGBA(255,0,0,255));
363     }
364 
365   const float treeline=0.25;
366   const float beachline=0.01;
367 
368   // Colour all vertices
369   for (uint i=0;i<vertices();i++)
370     {
371       step++;
372       progress_step((100*step)/steps);
373 
374       bool is_river=(river_vertices.find(i)!=river_vertices.end());
375 
376       float average_slope=1.0-(geometry().up(vertex(i).position())%vertex(i).normal());
377 
378       const float normalised_height=vertex_height(i)/max_height;
379 
380       float snowline_here=
381 	parameters.snowline_equator
382 	+fabs(geometry().normalised_latitude(vertex(i).position()))*(parameters.snowline_pole-parameters.snowline_equator)
383 	+parameters.snowline_slope_effect*average_slope
384 	-(is_river ? parameters.snowline_glacier_effect : 0.0);
385 
386       if (snowline_here>0.0)
387 	snowline_here=pow(snowline_here,parameters.snowline_power_law);
388 
389       if (normalised_height>snowline_here)
390 	{
391 	  vertex(i).colour(0,parameters.colour_snow);
392 	}
393       else if (is_river)
394 	{
395 	  vertex(i).colour(0,parameters.colour_river);
396 	}
397       else if (normalised_height<beachline)
398 	{
399 	  vertex(i).colour(0,parameters.colour_shoreline);
400 	}
401       else if (normalised_height<treeline)
402 	{
403 	  const float blend=normalised_height/treeline;
404 	  vertex(i).colour(0,blend*parameters.colour_high+(1.0-blend)*parameters.colour_low);
405 	}
406       else
407 	{
408 	  vertex(i).colour(0,parameters.colour_high);
409 	}
410     }
411 
412   progress_complete("Colouring completed");
413 }
414 
do_terrain(const ParametersTerrain & parameters)415 void TriangleMeshTerrain::do_terrain(const ParametersTerrain& parameters)
416 {
417   do_noise(parameters);
418   do_sea_level(parameters);
419   do_power_law(parameters);
420   do_rivers(parameters);
421   compute_vertex_normals();
422   do_colours(parameters);
423   set_emissive(parameters.oceans_and_rivers_emissive);
424 }
425 
write_blender(std::ofstream & out,const ParametersSave &,const ParametersTerrain &,const std::string & mesh_name) const426 void TriangleMeshTerrain::write_blender(std::ofstream& out,const ParametersSave&,const ParametersTerrain&,const std::string& mesh_name) const
427 {
428   TriangleMesh::write_blender(out,mesh_name+".terrain",0);
429 }
430 
431 namespace
432 {
lerp(float l,const T & v0,const T & v1)433   template <typename T> const T lerp(float l,const T& v0,const T& v1)
434   {
435     return (1.0f-l)*v0+l*v1;
436   }
437 
fn(const XYZ & v)438   FloatRGBA fn(const XYZ& v)
439   {
440     const XYZ n(v.normalised());
441     return FloatRGBA(0.5f+0.5f*n.x,0.5f+0.5f*n.y,0.5f+0.5f*n.z,0.0f);
442   }
443 
444   class ScanConvertHelper : public ScanConvertBackend
445   {
446   public:
ScanConvertHelper(Raster<ByteRGBA> & image,Raster<ushort> * dem,Raster<ByteRGBA> * normalmap,const boost::array<FloatRGBA,3> & vertex_colours,const boost::array<float,3> & vertex_heights,const boost::array<XYZ,3> & vertex_normals)447     ScanConvertHelper
448     (
449      Raster<ByteRGBA>& image,
450      Raster<ushort>* dem,
451      Raster<ByteRGBA>* normalmap,
452      const boost::array<FloatRGBA,3>& vertex_colours,
453      const boost::array<float,3>& vertex_heights,
454      const boost::array<XYZ,3>& vertex_normals
455      )
456       :ScanConvertBackend(image.width(),image.height())
457        ,_image(image)
458        ,_dem(dem)
459        ,_normalmap(normalmap)
460        ,_vertex_colours(vertex_colours)
461        ,_vertex_heights(vertex_heights)
462        ,_vertex_normals(vertex_normals)
463     {
464       if (_dem) assert(_image.width()==_dem->width() && _image.height()==_dem->height());
465       if (_normalmap) assert(_image.width()==_normalmap->width() && _image.height()==_normalmap->height());
466     }
~ScanConvertHelper()467     virtual ~ScanConvertHelper()
468     {}
469 
scan_convert_backend(uint y,const ScanEdge & edge0,const ScanEdge & edge1) const470     virtual void scan_convert_backend(uint y,const ScanEdge& edge0,const ScanEdge& edge1) const
471     {
472       const FloatRGBA c0=lerp(edge0.lambda,_vertex_colours[edge0.vertex0],_vertex_colours[edge0.vertex1]);
473       const FloatRGBA c1=lerp(edge1.lambda,_vertex_colours[edge1.vertex0],_vertex_colours[edge1.vertex1]);
474       _image.scan(y,edge0.x,c0,edge1.x,c1);
475 
476       if (_dem)
477 	{
478 	  const float h0=lerp(edge0.lambda,_vertex_heights[edge0.vertex0],_vertex_heights[edge0.vertex1]);
479 	  const float h1=lerp(edge1.lambda,_vertex_heights[edge1.vertex0],_vertex_heights[edge1.vertex1]);
480 	  _dem->scan(y,edge0.x,h0,edge1.x,h1);
481 	}
482       if (_normalmap)
483 	{
484 	  const XYZ n0(lerp(edge0.lambda,_vertex_normals[edge0.vertex0],_vertex_normals[edge0.vertex1]).normalised());
485 	  const XYZ n1(lerp(edge1.lambda,_vertex_normals[edge1.vertex0],_vertex_normals[edge1.vertex1]).normalised());
486 	  _normalmap->scan<XYZ>(y,edge0.x,n0,edge1.x,n1,fn);
487 	}
488     }
489 
subdivide(const boost::array<XYZ,3> & v,const XYZ & m,const ScanConverter & scan_converter) const490     virtual void subdivide(const boost::array<XYZ,3>& v,const XYZ& m,const ScanConverter& scan_converter) const
491     {
492       // Subdivision pattern (into 7) avoids creating any mid-points in edges shared with other triangles.
493       const boost::array<XYZ,3> vm=
494 	{{
495 	  (v[1]+v[2]+m)/3.0f,
496 	  (v[0]+v[2]+m)/3.0f,
497 	  (v[0]+v[1]+m)/3.0f
498 	}};
499 
500       //! \todo This isn't right (for correct value would need to compute barycentric coordinates of m), but it will should only affect one facet at the pole.
501       const boost::array<FloatRGBA,3> cm=
502 	{{
503 	  0.5f*(_vertex_colours[1]+_vertex_colours[2]),
504 	  0.5f*(_vertex_colours[0]+_vertex_colours[2]),
505 	  0.5f*(_vertex_colours[0]+_vertex_colours[1])
506 	}};
507       const boost::array<float,3> hm=
508 	{{
509 	  0.5f*(_vertex_heights[1]+_vertex_heights[2]),
510 	  0.5f*(_vertex_heights[0]+_vertex_heights[2]),
511 	  0.5f*(_vertex_heights[0]+_vertex_heights[1])
512 	}};
513       const boost::array<XYZ,3> nm=
514 	{{
515 	  (_vertex_normals[1]+_vertex_normals[2]).normalised(),
516 	  (_vertex_normals[0]+_vertex_normals[2]).normalised(),
517 	  (_vertex_normals[0]+_vertex_normals[1]).normalised()
518 	}};
519 
520       {
521 	const boost::array<XYZ,3> p={{v[0],v[1],vm[2]}};
522 	const boost::array<FloatRGBA,3> c={{_vertex_colours[0],_vertex_colours[1],cm[2]}};
523 	const boost::array<float,3> h={{_vertex_heights[0],_vertex_heights[1],hm[2]}};
524 	const boost::array<XYZ,3> n={{_vertex_normals[0],_vertex_normals[1],nm[2]}};
525 	scan_converter.scan_convert(p,ScanConvertHelper(_image,_dem,_normalmap,c,h,n));
526       }
527 
528       {
529 	const boost::array<XYZ,3> p={{v[1],v[2],vm[0]}};
530 	const boost::array<FloatRGBA,3> c={{_vertex_colours[1],_vertex_colours[2],cm[0]}};
531 	const boost::array<float,3> h={{_vertex_heights[1],_vertex_heights[2],hm[0]}};
532 	const boost::array<XYZ,3> n={{_vertex_normals[1],_vertex_normals[2],nm[0]}};
533 	scan_converter.scan_convert(p,ScanConvertHelper(_image,_dem,_normalmap,c,h,n));
534       }
535 
536       {
537 	const boost::array<XYZ,3> p={{v[2],v[0],vm[1]}};
538 	const boost::array<FloatRGBA,3> c={{_vertex_colours[2],_vertex_colours[0],cm[1]}};
539 	const boost::array<float,3> h={{_vertex_heights[2],_vertex_heights[0],hm[1]}};
540 	const boost::array<XYZ,3> n={{_vertex_normals[2],_vertex_normals[0],nm[1]}};
541 	scan_converter.scan_convert(p,ScanConvertHelper(_image,_dem,_normalmap,c,h,n));
542       }
543 
544       {
545 	const boost::array<XYZ,3> p={{v[0],vm[2],vm[1]}};
546 	const boost::array<FloatRGBA,3> c={{_vertex_colours[0],cm[2],cm[1]}};
547 	const boost::array<float,3> h={{_vertex_heights[0],hm[2],hm[1]}};
548 	const boost::array<XYZ,3> n={{_vertex_normals[0],nm[2],nm[1]}};
549 	scan_converter.scan_convert(p,ScanConvertHelper(_image,_dem,_normalmap,c,h,n));
550       }
551 
552       {
553 	const boost::array<XYZ,3> p={{v[1],vm[0],vm[2]}};
554 	const boost::array<FloatRGBA,3> c={{_vertex_colours[1],cm[0],cm[2]}};
555 	const boost::array<float,3> h={{_vertex_heights[1],hm[0],hm[2]}};
556 	const boost::array<XYZ,3> n={{_vertex_normals[1],nm[0],nm[2]}};
557 	scan_converter.scan_convert(p,ScanConvertHelper(_image,_dem,_normalmap,c,h,n));
558       }
559 
560       {
561 	const boost::array<XYZ,3> p={{v[2],vm[1],vm[0]}};
562 	const boost::array<FloatRGBA,3> c={{_vertex_colours[2],cm[1],cm[0]}};
563 	const boost::array<float,3> h={{_vertex_heights[2],hm[1],hm[0]}};
564 	const boost::array<XYZ,3> n={{_vertex_normals[2],nm[1],nm[0]}};
565 	scan_converter.scan_convert(p,ScanConvertHelper(_image,_dem,_normalmap,c,h,n));
566       }
567 
568       {
569 	scan_converter.scan_convert(vm,ScanConvertHelper(_image,_dem,_normalmap,cm,hm,nm));
570       }
571 
572     }
573 
574   private:
575     Raster<ByteRGBA>& _image;
576     Raster<ushort>* _dem;
577     Raster<ByteRGBA>* _normalmap;
578     const boost::array<FloatRGBA,3>& _vertex_colours;
579     const boost::array<float,3>& _vertex_heights;
580     const boost::array<XYZ,3>& _vertex_normals;
581   };
582 }
583 
render_texture(Raster<ByteRGBA> & image,Raster<ushort> * dem,Raster<ByteRGBA> * normal_map,bool shading,float ambient,const XYZ & illumination) const584 void TriangleMeshTerrain::render_texture
585 (
586  Raster<ByteRGBA>& image,
587  Raster<ushort>* dem,
588  Raster<ByteRGBA>* normal_map,
589  bool shading,
590  float ambient,
591  const XYZ& illumination
592  ) const
593 {
594   progress_start(100,"Generating textures");
595 
596   for (uint i=0;i<triangles();i++)
597     {
598       const Triangle& t=triangle(i);
599       const boost::array<const Vertex*,3> vertices
600 	={{
601 	  &vertex(t.vertex(0)),
602 	  &vertex(t.vertex(1)),
603 	  &vertex(t.vertex(2)),
604 	}};
605 
606       const boost::array<XYZ,3> vertex_positions
607 	={{
608 	  vertices[0]->position(),
609 	  vertices[1]->position(),
610 	  vertices[2]->position()
611 	}};
612 
613       const uint which_colour=(i<triangles_of_colour0() ? 0 : 1);
614       const boost::array<FloatRGBA,3> vertex_colours
615 	={{
616 	  FloatRGBA(vertices[0]->colour(which_colour))*(shading ? ambient+(1.0f-ambient)*std::max(0.0f,vertices[0]->normal()%illumination) : 1.0f),
617 	  FloatRGBA(vertices[1]->colour(which_colour))*(shading ? ambient+(1.0f-ambient)*std::max(0.0f,vertices[1]->normal()%illumination) : 1.0f),
618 	  FloatRGBA(vertices[2]->colour(which_colour))*(shading ? ambient+(1.0f-ambient)*std::max(0.0f,vertices[2]->normal()%illumination) : 1.0f)
619 	}};
620       const boost::array<float,3> vertex_heights
621 	={{
622 	  std::max(0.0f,std::min(65535.0f,65535.0f*geometry().height(vertices[0]->position()))),
623 	  std::max(0.0f,std::min(65535.0f,65535.0f*geometry().height(vertices[1]->position()))),
624 	  std::max(0.0f,std::min(65535.0f,65535.0f*geometry().height(vertices[2]->position())))
625 	}};
626       const boost::array<XYZ,3> vertex_normals
627 	={{
628 	  vertices[0]->normal(),
629 	  vertices[1]->normal(),
630 	  vertices[2]->normal()
631 	}};
632 
633       ScanConvertHelper backend(image,dem,normal_map,vertex_colours,vertex_heights,vertex_normals);
634 
635       geometry().scan_convert
636 	(
637 	 vertex_positions,
638 	 backend
639 	 );
640 
641       progress_step((100*i)/(triangles()-1));
642     }
643 
644   progress_complete("Texture generation completed");
645 }
646 
TriangleMeshTerrainPlanet(const ParametersTerrain & parameters,Progress * progress)647 TriangleMeshTerrainPlanet::TriangleMeshTerrainPlanet(const ParametersTerrain& parameters,Progress* progress)
648   :TriangleMesh(progress)
649   ,TriangleMeshTerrain(progress)
650   ,TriangleMeshSubdividedIcosahedron(1.0+parameters.variation.z*parameters.base_height,parameters.subdivisions,parameters.subdivisions_unperturbed,parameters.seed,parameters.variation,progress)
651 {
652   do_terrain(parameters);
653 }
654 
write_povray(std::ofstream & out,const ParametersSave & param_save,const ParametersTerrain & parameters_terrain) const655 void TriangleMeshTerrainPlanet::write_povray(std::ofstream& out,const ParametersSave& param_save,const ParametersTerrain& parameters_terrain) const
656 {
657   if (param_save.pov_sea_object)
658     {
659       out
660 	<< "sphere {<0.0,0.0,0.0>,1.0 pigment{rgb "
661 	<< parameters_terrain.colour_ocean.format_pov_rgb()
662 	<< "} finish {ambient "
663 	<< emissive()
664 	<< " diffuse "
665 	<< 1.0f-emissive()
666 	<< "}}\n";
667     }
668 
669   if (param_save.pov_atmosphere)
670     {
671       out
672 	<< "sphere {<0.0,0.0,0.0>,1.025 hollow texture {pigment {color rgbf 1}} interior{media{scattering{1,color rgb <1.0,1.0,1.0> extinction 1}}}}\n"
673 	<< "sphere {<0.0,0.0,0.0>,1.05  hollow texture {pigment {color rgbf 1}} interior{media{scattering{1,color rgb <0.0,0.0,1.0> extinction 1}}}}\n";
674     }
675 
676   TriangleMesh::write_povray(out,param_save.pov_sea_object,false,false); // Don't double illuminate.  Don't no-shadow.
677 }
678 
TriangleMeshTerrainFlat(const ParametersTerrain & parameters,Progress * progress)679 TriangleMeshTerrainFlat::TriangleMeshTerrainFlat(const ParametersTerrain& parameters,Progress* progress)
680   :TriangleMesh(progress)
681   ,TriangleMeshTerrain(progress)
682   ,TriangleMeshFlat(parameters.object_type,parameters.variation.z*parameters.base_height,parameters.seed,progress)
683 {
684   subdivide(parameters.subdivisions,parameters.subdivisions_unperturbed,parameters.variation);
685 
686   do_terrain(parameters);
687 }
688 
write_povray(std::ofstream & out,const ParametersSave & param_save,const ParametersTerrain & parameters_terrain) const689 void TriangleMeshTerrainFlat::write_povray(std::ofstream& out,const ParametersSave& param_save,const ParametersTerrain& parameters_terrain) const
690 {
691   if (param_save.pov_sea_object)
692     {
693       out
694 	<< "plane {<0.0,1.0,0.0>,0.0 pigment{rgb "
695 	<< parameters_terrain.colour_ocean.format_pov_rgb()
696 	<< "} finish {ambient "
697 	<< emissive()
698 	<< " diffuse "
699 	<< 1.0f-emissive()
700 	<< "}}\n";
701     }
702 
703   if (param_save.pov_atmosphere)
704     {
705       out
706 	<< "plane {<0.0,1.0,0.0>,0.05 hollow texture {pigment {color rgbf 1}} interior{media{scattering{1,color rgb <1.0,1.0,1.0> extinction 1}}}}\n"
707 	<< "plane {<0.0,1.0,0.0>,0.1  hollow texture {pigment {color rgbf 1}} interior{media{scattering{1,color rgb <0.0,0.0,1.0> extinction 1}}}}\n";
708     }
709 
710   TriangleMesh::write_povray(out,param_save.pov_sea_object,false,false); // Don't double illuminate.  Don't no-shadow.
711 }
712