Fix game:addSpawnShapesByZone
[ryzomcore.git] / nel / tools / 3d / zone_lighter / zone_lighter.cpp
blob20a8ddc0e2021c6da95a158caf9020e7772e946a
1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2014-2020 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
6 //
7 // This program is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU Affero General Public License as
9 // published by the Free Software Foundation, either version 3 of the
10 // License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU Affero General Public License for more details.
17 // You should have received a copy of the GNU Affero General Public License
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "nel/misc/stream.h"
21 #include "nel/misc/file.h"
22 #include "nel/misc/vector.h"
23 #include "nel/misc/time_nl.h"
24 #include "nel/misc/config_file.h"
25 #include "nel/misc/path.h"
28 #include "nel/georges/u_form.h"
29 #include "nel/georges/u_form_elm.h"
30 #include "nel/georges/u_form_loader.h"
33 #include "nel/3d/zone.h"
34 #include "nel/3d/zone_lighter.h"
35 #include "nel/3d/quad_grid.h"
36 #include "nel/3d/landscape.h"
37 #include "nel/3d/scene_group.h"
38 #include "nel/3d/shape.h"
39 #include "nel/3d/transform_shape.h"
40 #include "nel/3d/register_3d.h"
41 #include "nel/3d/water_shape.h"
43 #include "../zone_lib/zone_utility.h"
45 using namespace std;
46 using namespace NLMISC;
47 using namespace NL3D;
49 #define BAR_LENGTH 21
51 const char *progressbar[BAR_LENGTH]=
53 "[ ]",
54 "[. ]",
55 "[.. ]",
56 "[... ]",
57 "[.... ]",
58 "[..... ]",
59 "[...... ]",
60 "[....... ]",
61 "[........ ]",
62 "[......... ]",
63 "[.......... ]",
64 "[........... ]",
65 "[............ ]",
66 "[............. ]",
67 "[.............. ]",
68 "[............... ]",
69 "[................ ]",
70 "[................. ]",
71 "[.................. ]",
72 "[................... ]",
73 "[....................]"
76 // My zone lighter
77 class CMyZoneLighter : public CZoneLighter
79 // Progress bar
80 virtual void progress (const char *message, float progress)
82 // Progress bar
83 char msg[512];
84 uint pgId= (uint)(progress*(float)BAR_LENGTH);
85 pgId= min(pgId, (uint)(BAR_LENGTH-1));
86 sprintf (msg, "\r%s: %s", message, progressbar[pgId]);
87 uint i;
88 for (i=(uint)strlen(msg); i<79; i++)
89 msg[i]=' ';
90 msg[i]=0;
91 printf ("%s\r", msg);
95 struct CInstanceGroupRef
97 CInstanceGroup *IG;
98 bool AddLight;
101 //=======================================================================================
102 // load additionnal ig from a village (ryzom specific)
103 static void loadIGFromVillage(const NLGEORGES::UFormElm *villageItem, const std::string &continentName,
104 uint villageIndex, std::list<CInstanceGroupRef> &instanceGroups, CConfigFile::CVar &additionalIgNames)
106 const NLGEORGES::UFormElm *igNamesItem;
107 if (! (villageItem->getNodeByName (&igNamesItem, "IgList") && igNamesItem) )
109 nlwarning("No list of IGs was found in the continent form %s, village #%d", continentName.c_str(), villageIndex);
110 return;
113 // Get number of village
114 uint numIgs;
115 nlverify (igNamesItem->getArraySize (numIgs));
116 const NLGEORGES::UFormElm *currIg;
117 for(uint l = 0; l < numIgs; ++l)
119 if (!(igNamesItem->getArrayNode (&currIg, l) && currIg))
121 nlwarning("Couldn't get ig #%d in the continent form %s, in village #%d", l, continentName.c_str(), villageIndex);
122 continue;
124 const NLGEORGES::UFormElm *igNameItem;
125 currIg->getNodeByName (&igNameItem, "IgName");
126 std::string igName;
127 if (!igNameItem->getValue (igName))
129 nlwarning("Couldn't get ig name of ig #%d in the continent form %s, in village #%d", l, continentName.c_str(), villageIndex);
130 continue;
132 if (igName.empty())
134 nlwarning("Ig name of ig #%d in the continent form %s, in village #%d is an empty string", l, continentName.c_str(), villageIndex);
135 continue;
137 // ensure .ig
138 igName = CFile::getFilenameWithoutExtension(igName) + ".ig";
140 // verify that the ig is not already added (case of tr_water.ig in additional_igs)
141 for(uint igAdd= 0;igAdd<(uint)additionalIgNames.size();igAdd++)
143 if( toLowerAscii(additionalIgNames.asString()) == toLower(igName) )
145 nlwarning("Skipping Village Ig %s, cause already exist in additional ig", igName.c_str());
146 continue;
150 // add this ig
151 string nameLookup = CPath::lookup (igName, false, true);
152 if (!nameLookup.empty())
154 CIFile inputFile;
155 // Try to open the file
156 if (inputFile.open (nameLookup))
158 // New ig
159 CUniquePtr<CInstanceGroup> group(new CInstanceGroup);
162 group->serial (inputFile);
164 catch(const NLMISC::Exception &)
166 nlwarning ("Error while loading instance group %s", igName.c_str());
167 continue;
169 inputFile.close();
170 // Add to the list
171 CInstanceGroupRef iref;
172 iref.IG = group.release();
173 iref.AddLight = false;
174 instanceGroups.push_back (iref);
176 else
178 // Error
179 nlwarning ("Can't open instance group %s\n", igName.c_str());
186 //=======================================================================================
187 // load additionnal ig from a continent (ryzom specific)
188 static void loadIGFromContinent(NLMISC::CConfigFile &parameter, std::list<CInstanceGroupRef> &instanceGroups,
189 const std::vector<std::string> &zoneNameArray,
190 CConfigFile::CVar &additionalIgNames)
195 CConfigFile::CVar &continent_name_var = parameter.getVar ("continent_name");
196 CConfigFile::CVar &level_design_directory = parameter.getVar ("level_design_directory");
197 CConfigFile::CVar &level_design_world_directory = parameter.getVar ("level_design_world_directory");
198 CConfigFile::CVar &level_design_dfn_directory = parameter.getVar ("level_design_dfn_directory");
199 CPath::addSearchPath(level_design_dfn_directory.asString(), true, false);
200 CPath::addSearchPath(level_design_world_directory.asString(), true, false);
202 std::string continentName = continent_name_var.asString();
203 if (CFile::getExtension(continentName).empty())
204 continentName += ".continent";
205 // Load the form
206 NLGEORGES::UFormLoader *loader = NLGEORGES::UFormLoader::createLoader();
208 std::string pathName = CPath::lookup(continentName); // level_design_world_directory.asString() + "/" + continentName;
209 if (pathName.empty())
211 nlwarning("Can't find continent form : %s", continentName.c_str());
212 return;
214 NLGEORGES::UForm *villageForm;
215 villageForm = loader->loadForm(pathName.c_str());
216 if(villageForm != NULL)
218 NLGEORGES::UFormElm &rootItem = villageForm->getRootNode();
219 // try to get the village list
220 // Load the village list
221 NLGEORGES::UFormElm *villagesItem;
222 if(!(rootItem.getNodeByName (&villagesItem, "Villages") && villagesItem))
224 nlwarning("No villages where found in %s", continentName.c_str());
225 return;
228 // Get number of village
229 uint numVillage;
230 nlverify (villagesItem->getArraySize (numVillage));
232 // For each village
233 for(uint k = 0; k < numVillage; ++k)
235 NLGEORGES::UFormElm *currVillage;
236 if (!(villagesItem->getArrayNode (&currVillage, k) && currVillage))
238 nlwarning("Couldn't get village %d in continent %s", continentName.c_str(), k);
239 continue;
241 // check that this village is in the dependency zones
242 NLGEORGES::UFormElm *zoneNameItem;
243 if (!currVillage->getNodeByName (&zoneNameItem, "Zone") && zoneNameItem)
245 nlwarning("Couldn't get zone item of village %d in continent %s", continentName.c_str(), k);
246 continue;
248 std::string zoneName;
249 if (!zoneNameItem->getValue(zoneName))
251 nlwarning("Couldn't get zone name of village %d in continent %s", continentName.c_str(), k);
252 continue;
255 zoneName = CFile::getFilenameWithoutExtension(zoneName);
256 for(uint l = 0; l < zoneNameArray.size(); ++l)
258 if (NLMISC::nlstricmp(CFile::getFilenameWithoutExtension(zoneNameArray[l]), zoneName) == 0)
260 // ok, it is in the dependant zones
261 loadIGFromVillage(currVillage, continentName, k, instanceGroups, additionalIgNames);
262 break;
267 else
269 nlwarning("Can't load continent form : %s", continentName.c_str());
272 catch (const NLMISC::EUnknownVar &e)
274 nlinfo(e.what());
278 //=======================================================================================
279 int main(int argc, char* argv[])
281 // Start time
282 TTime time=CTime::getLocalTime ();
284 // Filter addSearchPath
285 NLMISC::createDebug();
286 InfoLog->addNegativeFilter ("adding the path");
287 WarningLog->addNegativeFilter ("continent.cfg");
289 // Register 3d
290 registerSerial3d ();
292 // Good number of args ?
293 if (argc<5)
295 // Help message
296 printf ("%s [zonein.zone] [zoneout.zone] [parameter_file] [dependancy_file] [-waterpatch bkupdir] \n", argv[0]);
298 else
300 // to patch only the tiles flags
301 bool tileWaterPatchOnly;
302 tileWaterPatchOnly= argc==7 && string(argv[5])=="-waterpatch";
303 string tileWaterPatchBkupDir;
304 if(tileWaterPatchOnly)
305 tileWaterPatchBkupDir = argv[6];
307 // Ok, read the zone
308 CIFile inputFile;
310 // Get extension
311 string ext=getExt (argv[1]);
312 string dir=getDir (argv[1]);
314 // Open it for reading
315 if (inputFile.open (argv[1]))
317 // Zone name
318 string zoneName=toLowerAscii (string ("zone_"+getName (argv[1])));
320 // Load the zone
323 // Read the config file
324 CConfigFile parameter;
325 CConfigFile dependency;
327 // Load and parse the dependency file
328 parameter.load (argv[3]);
330 // **********
331 // *** Build the lighter descriptor
332 // **********
334 CZoneLighter::CLightDesc lighterDesc;
336 // Get bank name
337 CConfigFile::CVar &bank_name = parameter.getVar ("bank_name");
339 // Load instance group ?
340 CConfigFile::CVar &load_ig= parameter.getVar ("load_ig");
341 bool loadInstanceGroup = load_ig.asInt ()!=0;
343 CConfigFile::CVar &additionnal_ig = parameter.getVar ("additionnal_ig");
345 // Grid size
346 CConfigFile::CVar &quad_grid_size = parameter.getVar ("quad_grid_size");
347 lighterDesc.GridSize=quad_grid_size.asInt();
349 // Grid size
350 CConfigFile::CVar &quad_grid_cell_size = parameter.getVar ("quad_grid_cell_size");
351 lighterDesc.GridCellSize=quad_grid_cell_size.asFloat();
353 // Heightfield cell size
354 CConfigFile::CVar &global_illumination_cell_size = parameter.getVar ("global_illumination_cell_size");
355 lighterDesc.HeightfieldCellSize=global_illumination_cell_size.asFloat();
357 // Heightfield size
358 CConfigFile::CVar &global_illumination_length = parameter.getVar ("global_illumination_length");
359 lighterDesc.HeightfieldSize=global_illumination_length.asFloat();
361 // Light direction
362 CConfigFile::CVar &sun_direction = parameter.getVar ("sun_direction");
363 lighterDesc.SunDirection.x=sun_direction.asFloat(0);
364 lighterDesc.SunDirection.y=sun_direction.asFloat(1);
365 lighterDesc.SunDirection.z=sun_direction.asFloat(2);
366 lighterDesc.SunDirection.normalize ();
368 // Light center position
369 CConfigFile::CVar &sun_center = parameter.getVar ("sun_center");
370 lighterDesc.SunCenter.x=sun_center.asFloat(0);
371 lighterDesc.SunCenter.y=sun_center.asFloat(1);
372 lighterDesc.SunCenter.z=sun_center.asFloat(2);
374 // Light distance
375 CConfigFile::CVar &sun_distance = parameter.getVar ("sun_distance");
376 lighterDesc.SunDistance=sun_distance.asFloat();
378 // Light FOV
379 CConfigFile::CVar &sun_fov = parameter.getVar ("sun_fov");
380 lighterDesc.SunFOV=sun_fov.asFloat();
382 // Light radius
383 CConfigFile::CVar &sun_radius = parameter.getVar ("sun_radius");
384 lighterDesc.SunRadius=sun_radius.asFloat();
386 // ZBuffer landscape size
387 CConfigFile::CVar &zbuffer_landscape_size = parameter.getVar ("zbuffer_landscape_size");
388 lighterDesc.ZBufferLandscapeSize=zbuffer_landscape_size.asInt();
390 // ZBuffer object size
391 CConfigFile::CVar &zbuffer_object_size = parameter.getVar ("zbuffer_object_size");
392 lighterDesc.ZBufferObjectSize=zbuffer_object_size.asInt();
394 // Soft shadow samples sqrt
395 CConfigFile::CVar &soft_shadow_samples_sqrt = parameter.getVar ("soft_shadow_samples_sqrt");
396 lighterDesc.SoftShadowSamplesSqrt=soft_shadow_samples_sqrt.asInt();
398 // Soft shadow jitter
399 CConfigFile::CVar &soft_shadow_jitter = parameter.getVar ("soft_shadow_jitter");
400 lighterDesc.SoftShadowJitter=soft_shadow_jitter.asFloat();
402 // Water rendering parameters
403 CConfigFile::CVar &water_zbias = parameter.getVar ("water_shadow_bias");
404 lighterDesc.WaterShadowBias = water_zbias.asFloat();
406 CConfigFile::CVar &water_ambient = parameter.getVar ("water_ambient");
407 lighterDesc.WaterAmbient = water_ambient.asFloat();
409 CConfigFile::CVar &water_diffuse = parameter.getVar ("water_diffuse");
410 lighterDesc.WaterDiffuse = water_diffuse.asFloat();
412 CConfigFile::CVar &modulate_water_color = parameter.getVar ("modulate_water_color");
413 lighterDesc.ModulateWaterColor = modulate_water_color.asInt() != 0;
415 CConfigFile::CVar &sky_contribution_for_water = parameter.getVar ("sky_contribution_for_water");
416 lighterDesc.SkyContributionForWater = sky_contribution_for_water.asInt() != 0;
418 // Number of CPU
419 CConfigFile::CVar &cpu_num = parameter.getVar ("cpu_num");
420 lighterDesc.NumCPU=cpu_num.asInt ();
422 // Sun contribution
423 CConfigFile::CVar &sun_contribution = parameter.getVar ("sun_contribution");
424 lighterDesc.SunContribution=sun_contribution.asInt ()!=0;
426 // Shadows enabled ?
427 CConfigFile::CVar &shadow = parameter.getVar ("shadow");
428 lighterDesc.Shadow=shadow.asInt ()!=0;
430 // Sky contribution
431 CConfigFile::CVar &sky_contribution = parameter.getVar ("sky_contribution");
432 lighterDesc.SkyContribution=sky_contribution.asInt ()!=0;
434 // Sky contribution
435 CConfigFile::CVar &sky_intensity = parameter.getVar ("sky_intensity");
436 lighterDesc.SkyIntensity=sky_intensity.asFloat ();
438 // Vegetable Height
439 CConfigFile::CVar &vegetable_height = parameter.getVar ("vegetable_height");
440 lighterDesc.VegetableHeight=vegetable_height.asFloat ();
443 // Shadow are enabled ?
444 if (lighterDesc.Shadow)
446 // Load and parse the dependency file
447 dependency.load (argv[4]);
450 // Get the search pathes
451 CConfigFile::CVar &search_pathes = parameter.getVar ("search_pathes");
452 uint path;
453 for (path = 0; path < (uint)search_pathes.size(); path++)
455 // Add to search path
456 CPath::addSearchPath (search_pathes.asString(path));
459 // A landscape allocated with new: it is not delete because destruction take 3 secondes more!
460 CLandscape *landscape=new CLandscape;
461 landscape->init();
463 // A zone lighter
464 CMyZoneLighter lighter;
465 lighter.init ();
467 // A vector of zone id
468 vector<uint> listZoneId;
470 // The zone
471 CZone zone;
473 // List of ig
474 std::list<CInstanceGroupRef> instanceGroup;
476 // Load
477 zone.serial (inputFile);
478 inputFile.close();
480 bool zoneIgLoaded = false;
482 // Load ig of the zone
483 string igName = getName (argv[1])+".ig";
484 string igNameLookup = CPath::lookup (igName, false, false);
485 if (!igNameLookup.empty())
486 igName = igNameLookup;
488 if (inputFile.open (igName))
490 // New ig
491 CInstanceGroup *group=new CInstanceGroup;
493 // Serial it
494 group->serial (inputFile);
495 inputFile.close();
497 // Add to the list
498 CInstanceGroupRef iref;
499 iref.IG = group;
500 iref.AddLight = true;
501 instanceGroup.push_back (iref);
502 zoneIgLoaded = true;
504 else
506 // Warning
507 fprintf (stderr, "Warning: can't load instance group %s\n", igName.c_str());
508 zoneIgLoaded = false;
511 // Load the bank
512 string bankName = bank_name.asString();
513 string bankNameLookup = CPath::lookup (bankName, false, false);
514 if (!bankNameLookup.empty())
515 bankName = bankNameLookup;
516 if (inputFile.open (bankName))
520 // Load
521 landscape->TileBank.serial (inputFile);
522 landscape->initTileBanks();
524 catch (const Exception &e)
526 // Error
527 nlwarning ("ERROR error loading tile bank %s\n%s\n", bankName.c_str(), e.what());
530 else
532 // Error
533 nlwarning ("ERROR can't load tile bank %s\n", bankName.c_str());
536 // Add the zone
537 landscape->addZone (zone);
538 listZoneId.push_back (zone.getZoneId());
540 // Continue to build ?
541 bool continu=true;
543 // Try to load additionnal instance group.
545 // Additionnal instance group
546 if (loadInstanceGroup)
550 for (uint add=0; add<(uint)additionnal_ig.size(); add++)
552 // Input file
553 CIFile inputFile;
555 // Name of the instance group
556 string name = additionnal_ig.asString(add);
557 string nameLookup = CPath::lookup (name, false, false);
558 if (!nameLookup.empty())
559 name = nameLookup;
561 // Try to open the file
562 if (inputFile.open (name))
564 // New ig
565 CInstanceGroup *group=new CInstanceGroup;
567 // Serial it
568 group->serial (inputFile);
569 inputFile.close();
571 // Add to the list
572 CInstanceGroupRef iref;
573 iref.IG = group;
574 iref.AddLight = false;
575 instanceGroup.push_back (iref);
577 else
579 // Error
580 nlwarning ("ERROR can't load instance group %s\n", name.c_str());
582 // Stop before build
583 continu=false;
587 catch (const NLMISC::EUnknownVar &)
589 nlinfo("No additionnal ig's to load");
593 // *** Scan dependency file
595 if (lighterDesc.Shadow)
597 CConfigFile::CVar &dependant_zones = dependency.getVar ("dependencies");
598 std::vector<std::string> zoneNameArray;
599 zoneNameArray.reserve(1 + (uint)dependant_zones.size());
600 zoneNameArray.push_back(argv[1]);
602 for (uint i=0; i<(uint)dependant_zones.size(); i++)
604 // Get zone name
605 string zoneName=dependant_zones.asString(i);
606 zoneNameArray.push_back(zoneName);
607 // Load the zone
608 CZone zoneBis;
610 // Open it for reading
611 if (inputFile.open (dir+zoneName+ext))
613 // Read it
614 zoneBis.serial (inputFile);
615 inputFile.close();
617 // Add the zone
618 landscape->addZone (zoneBis);
619 listZoneId.push_back (zoneBis.getZoneId());
621 else
623 // Error message and continue
624 nlwarning ("ERROR can't load zone %s\n", (dir+zoneName+ext).c_str());
627 // Try to load an instance group.
628 if (loadInstanceGroup)
630 string name = zoneName+".ig";
631 string nameLookup = CPath::lookup (name, false, false);
632 if (!nameLookup.empty())
633 name = nameLookup;
635 // Name of the instance group
636 if (inputFile.open (name))
638 // New ig
639 CInstanceGroup *group=new CInstanceGroup;
641 // Serial it
642 group->serial (inputFile);
643 inputFile.close();
645 // Add to the list
646 CInstanceGroupRef iref;
647 iref.IG = group;
648 iref.AddLight = true;
649 instanceGroup.push_back (iref);
651 else
653 // Error message and continue
654 nlwarning ("WARNING can't load instance group %s\n", name.c_str());
659 if (loadInstanceGroup)
661 // Ryzom specific : additionnal villages from a continent form
662 loadIGFromContinent(parameter, instanceGroup, zoneNameArray, additionnal_ig);
666 // A vector of CZoneLighter::CTriangle
667 vector<CZoneLighter::CTriangle> vectorTriangle;
669 // **********
670 // *** Build triangle array
671 // **********
673 landscape->checkBinds ();
675 // Add triangles from landscape
676 landscape->enableAutomaticLighting (false);
677 // no need to add obstacles in case of water patch
678 if(!tileWaterPatchOnly)
679 lighter.addTriangles (*landscape, listZoneId, 0, vectorTriangle);
681 // Map of shape
682 std::map<string, IShape*> shapeMap;
684 // For each instance group
685 std::list<CInstanceGroupRef>::iterator ite=instanceGroup.begin();
686 while (ite!=instanceGroup.end())
688 // Instance group
689 CInstanceGroup *group=ite->IG;
691 // Load and add shapes
692 if (lighterDesc.Shadow)
694 // For each instance
695 for (uint instance=0; instance<group->getNumInstance(); instance++)
697 // Get the instance shape name
698 string name=group->getShapeName (instance);
699 if (!name.empty())
701 // Skip it?? use the DontCastShadowForExterior flag. See doc of this flag
702 if(group->getInstance(instance).DontCastShadow || group->getInstance(instance).DontCastShadowForExterior)
703 continue;
705 if (toLowerAscii (CFile::getExtension (name)) == "pacs_prim")
707 nlwarning("EXPORT BUG: Can't read %s (not a shape), should not be part of .ig!", name.c_str());
708 continue;
711 // PS ?
712 if (toLowerAscii (CFile::getExtension (name)) == "ps")
713 continue;
715 // Add a .shape at the end ?
716 if (name.find('.') == std::string::npos)
717 name += ".shape";
719 // Add path
720 string nameLookup = CPath::lookup (name, false, false);
721 if (!nameLookup.empty())
722 name = nameLookup;
724 // Find the shape in the bank
725 std::map<string, IShape*>::iterator iteMap=shapeMap.find (name);
726 if (iteMap==shapeMap.end())
728 // Input file
729 CIFile inputFile;
731 if (inputFile.open (name))
733 // Load it
734 CShapeStream stream;
735 stream.serial (inputFile);
737 // Get the pointer
738 iteMap=shapeMap.insert (std::map<string, IShape*>::value_type (name, stream.getShapePointer ())).first;
740 else
742 // Error
743 nlwarning ("WARNING can't load shape %s\n", name.c_str());
747 // Loaded ?
748 if (iteMap!=shapeMap.end())
750 // Build the matrix
751 CMatrix scale;
752 scale.identity ();
753 scale.scale (group->getInstanceScale (instance));
754 CMatrix rot;
755 rot.identity ();
756 rot.setRot (group->getInstanceRot (instance));
757 CMatrix pos;
758 pos.identity ();
759 pos.setPos (group->getInstancePos (instance));
760 CMatrix mt=pos*rot*scale;
762 // Add triangles
763 // no need to add obstacles in case of water patch
764 if(!tileWaterPatchOnly)
765 lighter.addTriangles (*iteMap->second, mt, vectorTriangle);
767 /** If it is a lightable shape and we are dealing with the ig of the main zone,
768 * add it to the lightable shape list
770 IShape *shape = iteMap->second;
771 if (ite == instanceGroup.begin() /* are we dealing with main zone */
772 && zoneIgLoaded /* ig of the main zone loaded successfully (so its indeed the ig of the first zone) ? */
773 && CZoneLighter::isLightableShape(*shape)
774 && !tileWaterPatchOnly
777 lighter.addLightableShape(shape, mt);
780 /** If it is a water shape, add it to the lighter, so that it can check
781 * which tiles are above / below water for this zone. The result is saved in the flags of tiles.
782 * A tile that have their flags set to VegetableDisabled won't get setupped
784 if (dynamic_cast<NL3D::CWaterShape *>(shape))
786 lighter.addWaterShape(static_cast<NL3D::CWaterShape *>(shape), mt);
793 // For each point light of the ig. No need wor tileWaterPatchOnly
794 if (ite->AddLight && !tileWaterPatchOnly)
796 const std::vector<CPointLightNamed> &pointLightList= group->getPointLightList();
797 for (uint plId=0; plId<pointLightList.size(); plId++)
799 // Add it to the Ig.
800 lighter.addStaticPointLight(pointLightList[plId]);
804 // Next instance group
805 ite++;
808 // If no waterpatch, and no WaterShape at all, no op
809 bool tileWaterSkip= false;
810 if(continu && tileWaterPatchOnly && lighter.getNumWaterShape()==0)
812 nlinfo("NO WATER INTERSECTION FOUND: don't patch at all");
813 continu= false;
814 tileWaterSkip= true;
817 // Continue ?
818 if (continu)
820 // **********
821 // *** Light!
822 // **********
824 // Output zone
825 CZone output;
827 // normal lighting
828 if(!tileWaterPatchOnly)
830 // Light the zone
831 lighter.light (*landscape, output, zone.getZoneId(), lighterDesc, vectorTriangle, listZoneId);
833 else
835 // Load the zonel.
836 CIFile zonelFile;
838 // load the zonel (keep lighting)
839 if (zonelFile.open (argv[2]))
841 // load the new zone
844 // load it
845 output.serial (zonelFile);
847 catch (const Exception& except)
849 // Error message
850 nlwarning ("ERROR reading %s: %s\n", argv[2], except.what());
851 throw;
854 else
856 // Error can't open the file
857 nlwarning ("ERROR Can't open %s for reading\n", argv[1]);
858 throw Exception("ERROR Can't open the zonel for tile water patching. abort");
860 zonelFile.close();
863 // Bkup the zone
864 COFile outputFile;
865 string bkupFile= tileWaterPatchBkupDir + "/" + CFile::getFilename(argv[2]);
866 if (outputFile.open (bkupFile))
870 output.serial (outputFile);
872 catch (const Exception& except)
874 nlwarning ("ERROR backuping %s: %s\n", bkupFile.c_str(), except.what());
876 outputFile.close();
878 else
879 nlwarning ("ERROR Can't open %s for writing\n", bkupFile.c_str());
882 // patch water flags
883 lighter.computeTileFlagsOnly(*landscape, output, zone.getZoneId(), lighterDesc, listZoneId);
886 // Save the zone
887 COFile outputFile;
889 // Open it
890 if (outputFile.open (argv[2]))
892 // Save the new zone
895 // Save it
896 output.serial (outputFile);
898 catch (const Exception& except)
900 // Error message
901 nlwarning ("ERROR writing %s: %s\n", argv[2], except.what());
904 else
906 // Error can't open the file
907 nlwarning ("ERROR Can't open %s for writing\n", argv[2]);
910 // Compute time
911 printf ("\rCompute time: %d ms \r",
912 (uint)(CTime::getLocalTime ()-time));
914 else
916 if(!tileWaterSkip)
917 // Error
918 nlwarning ("ERROR Abort: files are missing.\n");
921 catch (const Exception& except)
923 // Error message
924 nlwarning ("ERROR %s\n", except.what());
927 else
929 // Error can't open the file
930 nlwarning ("ERROR Can't open %s for reading\n", argv[1]);
935 // Landscape is not deleted, nor the instanceGroups, for faster quit.
936 // Must disalbe BlockMemory checks (for pointLights).
937 NL3D_BlockMemoryAssertOnPurge= false;
939 // Compute time
940 printf ("\rCompute time: %d ms \n",
941 (uint)(CTime::getLocalTime ()-time));
943 // exit.
944 return 0;