1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2010 Matt RAYKOWSKI (sfb) <matt.raykowski@gmail.com>
6 // Copyright (C) 2016 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
8 // This program is free software: you can redistribute it and/or modify
9 // it under the terms of the GNU Affero General Public License as
10 // published by the Free Software Foundation, either version 3 of the
11 // License, or (at your option) any later version.
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU Affero General Public License for more details.
18 // You should have received a copy of the GNU Affero General Public License
19 // along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "formFlora.h"
23 #include "formPlant.h"
27 #endif // NL_OS_WINDOWS
29 #include "nel/ligo/zone_region.h"
30 #include "nel/ligo/primitive.h"
32 #include "nel/georges/u_form_loader.h"
33 #include "nel/georges/u_form.h"
34 #include "nel/georges/u_form_elm.h"
36 #include "nel/3d/zone.h"
37 #include "nel/3d/landscape.h"
38 #include "nel/3d/scene_group.h"
39 #include "nel/3d/visual_collision_manager.h"
40 #include "nel/3d/visual_collision_entity.h"
42 #include "nel/misc/o_xml.h"
43 #include "nel/misc/i_xml.h"
44 #include "nel/misc/path.h"
45 #include "nel/misc/file.h"
48 #include "../master/ContinentCfg.h"
51 using namespace NLMISC
;
53 using namespace NLLIGO
;
54 using namespace NLGEORGES
;
57 const char *gExportSysDir
[MAX_SYS_DIR
] =
68 // ---------------------------------------------------------------------------
69 // ---------------------------------------------------------------------------
70 // ---------------------------------------------------------------------------
71 // ---------------------------------------------------------------------------
73 // -----------------------------------------------------------------------------------------------
74 // Segment line intersection P1P2 and P3P4
75 bool CExport::segmentIntersection(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
, double x4
, double y4
)
77 double denominator
= (y4
-y3
)*(x2
-x1
) - (x4
-x3
)*(y2
-y1
);
78 if( denominator
== 0.0 )
79 return false; // The segment are colinear
80 double k
= ((x4
-x3
)*(y1
-y3
) - (y4
-y3
)*(x1
-x3
) ) / denominator
;
81 if( (k
<=0.0) || (k
>=1.0) ) return false;
82 k
= ( (x2
-x1
)*(y1
-y3
) - (y2
-y1
)*(x1
-x3
) ) / denominator
;
83 if( (k
<=0.0) || (k
>=1.0) ) return false;
87 // ---------------------------------------------------------------------------
88 void CExport::delIGZone (sint32 x
, sint32 y
)
90 string sZoneName
= CExport::getZoneNameFromXY (x
, y
);
92 if (CFile::deleteFile(sZoneName
))
94 CTools::chdir (_ExeDir
);
95 string sTmp
= string(" zone ") + sZoneName
+ " deleted";
96 if (_ExportCB
!= NULL
)
97 _ExportCB
->dispInfo(sTmp
);
101 // ---------------------------------------------------------------------------
102 void CExport::delAllIGZoneUnderPoint (float fCellSize
, CPrimPoint
*pPoint
, const string
&sIGOutputDir
)
104 if (pPoint
== NULL
) return;
106 CTools::chdir (sIGOutputDir
);
107 nX
= (sint32
) floor (pPoint
->Point
.x
/ fCellSize
);
108 nY
= (sint32
) floor (pPoint
->Point
.y
/ fCellSize
);
110 CTools::chdir (sIGOutputDir
);
113 // ---------------------------------------------------------------------------
114 void CExport::delAllIGZoneUnderPath (float fCellSize
, CPrimPath
*pPath
, const string
&sIGOutputDir
)
116 if (pPath
== NULL
) return;
117 if (pPath
->VPoints
.empty()) return;
121 CTools::chdir (sIGOutputDir
);
122 vMin
= vMax
= pPath
->VPoints
[0];
123 for (i
= 0; i
< pPath
->VPoints
.size(); ++i
)
125 if (vMin
.x
> pPath
->VPoints
[i
].x
) vMin
.x
= pPath
->VPoints
[i
].x
;
126 if (vMin
.y
> pPath
->VPoints
[i
].y
) vMin
.y
= pPath
->VPoints
[i
].y
;
127 if (vMin
.z
> pPath
->VPoints
[i
].z
) vMin
.z
= pPath
->VPoints
[i
].z
;
128 if (vMax
.x
< pPath
->VPoints
[i
].x
) vMax
.x
= pPath
->VPoints
[i
].x
;
129 if (vMax
.y
< pPath
->VPoints
[i
].y
) vMax
.y
= pPath
->VPoints
[i
].y
;
130 if (vMax
.z
< pPath
->VPoints
[i
].z
) vMax
.z
= pPath
->VPoints
[i
].z
;
134 sint32 nMinX
, nMinY
, nMaxX
, nMaxY
;
135 nMinX
= (sint32
) floor (vMin
.x
/ fCellSize
);
136 nMinY
= (sint32
) floor (vMin
.y
/ fCellSize
);
137 nMaxX
= (sint32
) floor (vMax
.x
/ fCellSize
);
138 nMaxY
= (sint32
) floor (vMax
.y
/ fCellSize
);
140 for (x
= nMinX
; x
<= nMaxX
; ++x
)
141 for (y
= nMinY
; y
<= nMaxY
; ++y
)
143 // Does the zone (x,y) is under the patah ?
146 vSquare
[0].x
= x
* fCellSize
;
147 vSquare
[0].y
= y
* fCellSize
;
150 vSquare
[1].x
= (x
+1) * fCellSize
;
151 vSquare
[1].y
= y
* fCellSize
;
154 vSquare
[2].x
= (x
+1) * fCellSize
;
155 vSquare
[2].y
= (y
+1) * fCellSize
;
158 vSquare
[3].x
= x
* fCellSize
;
159 vSquare
[3].y
= (y
+1) * fCellSize
;
162 // Is a vertex of the path inside the zone ?
163 for (i
= 0; i
< pPath
->VPoints
.size(); ++i
)
165 if ((pPath
->VPoints
[i
].x
>= (x
*fCellSize
)) &&
166 (pPath
->VPoints
[i
].x
<= ((x
+1)*fCellSize
)) &&
167 (pPath
->VPoints
[i
].y
<= (y
*fCellSize
)) &&
168 (pPath
->VPoints
[i
].y
<= ((y
+1)*fCellSize
)))
171 CTools::chdir (sIGOutputDir
);
175 // Is an segment of the path cut an edge of the patat ?
176 for (i
= 0; i
< pPath
->VPoints
.size()-1; ++i
)
177 for (j
= 0; j
< 4; ++j
)
179 double x1
= vSquare
[j
].x
;
180 double y1
= vSquare
[j
].y
;
181 double x2
= vSquare
[(j
+1)%4].x
;
182 double y2
= vSquare
[(j
+1)%4].y
;
184 double x3
= pPath
->VPoints
[i
].x
;
185 double y3
= pPath
->VPoints
[i
].y
;
186 double x4
= pPath
->VPoints
[i
+1].x
;
187 double y4
= pPath
->VPoints
[i
+1].y
;
189 if (segmentIntersection(x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
))
192 CTools::chdir (sIGOutputDir
);
198 // ---------------------------------------------------------------------------
199 void CExport::delAllIGZoneUnderPatat (float fCellSize
, CPrimZone
*pPatat
, const string
&sIGOutputDir
)
201 if (pPatat
== NULL
) return;
202 if (pPatat
->VPoints
.empty()) return;
206 CTools::chdir (sIGOutputDir
);
207 vMin
= vMax
= pPatat
->VPoints
[0];
208 for (i
= 0; i
< pPatat
->VPoints
.size(); ++i
)
210 if (vMin
.x
> pPatat
->VPoints
[i
].x
) vMin
.x
= pPatat
->VPoints
[i
].x
;
211 if (vMin
.y
> pPatat
->VPoints
[i
].y
) vMin
.y
= pPatat
->VPoints
[i
].y
;
212 if (vMin
.z
> pPatat
->VPoints
[i
].z
) vMin
.z
= pPatat
->VPoints
[i
].z
;
213 if (vMax
.x
< pPatat
->VPoints
[i
].x
) vMax
.x
= pPatat
->VPoints
[i
].x
;
214 if (vMax
.y
< pPatat
->VPoints
[i
].y
) vMax
.y
= pPatat
->VPoints
[i
].y
;
215 if (vMax
.z
< pPatat
->VPoints
[i
].z
) vMax
.z
= pPatat
->VPoints
[i
].z
;
219 sint32 nMinX
, nMinY
, nMaxX
, nMaxY
;
220 nMinX
= (sint32
) floor (vMin
.x
/ fCellSize
);
221 nMinY
= (sint32
) floor (vMin
.y
/ fCellSize
);
222 nMaxX
= (sint32
) floor (vMax
.x
/ fCellSize
);
223 nMaxY
= (sint32
) floor (vMax
.y
/ fCellSize
);
225 for (x
= nMinX
; x
<= nMaxX
; ++x
)
226 for (y
= nMinY
; y
<= nMaxY
; ++y
)
228 // Does the zone (x,y) is under the patat ?
230 // Is a vertex of the zone in the patat ?
232 vSquare
[0].x
= x
* fCellSize
;
233 vSquare
[0].y
= y
* fCellSize
;
236 vSquare
[1].x
= (x
+1) * fCellSize
;
237 vSquare
[1].y
= y
* fCellSize
;
240 vSquare
[2].x
= (x
+1) * fCellSize
;
241 vSquare
[2].y
= (y
+1) * fCellSize
;
244 vSquare
[3].x
= x
* fCellSize
;
245 vSquare
[3].y
= (y
+1) * fCellSize
;
248 for (i
= 0; i
< 4; ++i
)
250 if (pPatat
->contains(vSquare
[i
]))
253 CTools::chdir (sIGOutputDir
);
257 // Is a vertex of the patat inside the zone ?
258 for (i
= 0; i
< pPatat
->VPoints
.size(); ++i
)
260 if ((pPatat
->VPoints
[i
].x
>= (x
*fCellSize
)) &&
261 (pPatat
->VPoints
[i
].x
<= ((x
+1)*fCellSize
)) &&
262 (pPatat
->VPoints
[i
].y
<= (y
*fCellSize
)) &&
263 (pPatat
->VPoints
[i
].y
<= ((y
+1)*fCellSize
)))
266 CTools::chdir (sIGOutputDir
);
270 // Is an edge of the zone cut an edge of the patat ?
271 for (i
= 0; i
< pPatat
->VPoints
.size(); ++i
)
272 for (j
= 0; j
< 4; ++j
)
274 double x1
= vSquare
[j
].x
;
275 double y1
= vSquare
[j
].y
;
276 double x2
= vSquare
[(j
+1)%4].x
;
277 double y2
= vSquare
[(j
+1)%4].y
;
279 double x3
= pPatat
->VPoints
[i
].x
;
280 double y3
= pPatat
->VPoints
[i
].y
;
281 double x4
= pPatat
->VPoints
[(i
+1)%pPatat
->VPoints
.size()].x
;
282 double y4
= pPatat
->VPoints
[(i
+1)%pPatat
->VPoints
.size()].y
;
284 if (segmentIntersection(x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
))
287 CTools::chdir (sIGOutputDir
);
293 // ---------------------------------------------------------------------------
294 // A patat needs an update if there is at least one zone under itself that is not present
295 bool CExport::isPatatNeedUpdate (float fCellSize
, CPrimZone
*pPatat
, const string
&sIGOutputDir
)
300 CTools::chdir (sIGOutputDir
);
301 if (pPatat
->VPoints
.empty())
303 vMin
= vMax
= pPatat
->VPoints
[0];
304 for (i
= 0; i
< pPatat
->VPoints
.size(); ++i
)
306 if (vMin
.x
> pPatat
->VPoints
[i
].x
) vMin
.x
= pPatat
->VPoints
[i
].x
;
307 if (vMin
.y
> pPatat
->VPoints
[i
].y
) vMin
.y
= pPatat
->VPoints
[i
].y
;
308 if (vMin
.z
> pPatat
->VPoints
[i
].z
) vMin
.z
= pPatat
->VPoints
[i
].z
;
309 if (vMax
.x
< pPatat
->VPoints
[i
].x
) vMax
.x
= pPatat
->VPoints
[i
].x
;
310 if (vMax
.y
< pPatat
->VPoints
[i
].y
) vMax
.y
= pPatat
->VPoints
[i
].y
;
311 if (vMax
.z
< pPatat
->VPoints
[i
].z
) vMax
.z
= pPatat
->VPoints
[i
].z
;
315 sint32 nMinX
, nMinY
, nMaxX
, nMaxY
;
316 nMinX
= (sint32
) floor (vMin
.x
/ fCellSize
);
317 nMinY
= (sint32
) floor (vMin
.y
/ fCellSize
);
318 nMaxX
= (sint32
) floor (vMax
.x
/ fCellSize
);
319 nMaxY
= (sint32
) floor (vMax
.y
/ fCellSize
);
321 for (x
= nMinX
; x
<= nMaxX
; ++x
)
322 for (y
= nMinY
; y
<= nMaxY
; ++y
)
324 // Does the zone (x,y) is under the patat ?
325 bool bZoneUnderPatat
= false;
326 // Is a vertex of the zone in the patat ?
328 vSquare
[0].x
= x
* fCellSize
;
329 vSquare
[0].y
= y
* fCellSize
;
332 vSquare
[1].x
= (x
+1) * fCellSize
;
333 vSquare
[1].y
= y
* fCellSize
;
336 vSquare
[2].x
= (x
+1) * fCellSize
;
337 vSquare
[2].y
= (y
+1) * fCellSize
;
340 vSquare
[3].x
= x
* fCellSize
;
341 vSquare
[3].y
= (y
+1) * fCellSize
;
344 for (i
= 0; i
< 4; ++i
)
346 if (pPatat
->contains(vSquare
[i
]))
348 string sTmp
= CExport::getZoneNameFromXY(x
,y
) + ".ig";
349 if (!CTools::fileExist(sTmp
)) // If the file does not exist
350 return true; // need update
354 // Is a vertex of the patat inside the zone ?
355 for (i
= 0; i
< pPatat
->VPoints
.size(); ++i
)
357 if ((pPatat
->VPoints
[i
].x
>= (x
*fCellSize
)) &&
358 (pPatat
->VPoints
[i
].x
<= ((x
+1)*fCellSize
)) &&
359 (pPatat
->VPoints
[i
].y
>= (y
*fCellSize
)) &&
360 (pPatat
->VPoints
[i
].y
<= ((y
+1)*fCellSize
)))
362 string sTmp
= CExport::getZoneNameFromXY(x
,y
) + ".ig";
363 if (!CTools::fileExist(sTmp
)) // If the file does not exist
364 return true; // need update
368 // Is an edge of the zone cut an edge of the patat ?
369 for (i
= 0; i
< pPatat
->VPoints
.size(); ++i
)
370 for (j
= 0; j
< 4; ++j
)
372 double x1
= vSquare
[j
].x
;
373 double y1
= vSquare
[j
].y
;
374 double x2
= vSquare
[(j
+1)%4].x
;
375 double y2
= vSquare
[(j
+1)%4].y
;
377 double x3
= pPatat
->VPoints
[i
].x
;
378 double y3
= pPatat
->VPoints
[i
].y
;
379 double x4
= pPatat
->VPoints
[(i
+1)%pPatat
->VPoints
.size()].x
;
380 double y4
= pPatat
->VPoints
[(i
+1)%pPatat
->VPoints
.size()].y
;
382 if (segmentIntersection(x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
))
384 string sTmp
= CExport::getZoneNameFromXY (x
, y
) + ".ig";
385 if (!CTools::fileExist(sTmp
)) // If the file does not exist
386 return true; // need update
393 // ---------------------------------------------------------------------------
394 // A path needs an update if there is at least one zone under itself that is not present
395 bool CExport::isPathNeedUpdate (float fCellSize
, CPrimPath
*pPath
, const string
&sIGOutputDir
)
400 CTools::chdir (sIGOutputDir
);
401 if (pPath
->VPoints
.empty())
403 vMin
= vMax
= pPath
->VPoints
[0];
404 for (i
= 0; i
< pPath
->VPoints
.size(); ++i
)
406 if (vMin
.x
> pPath
->VPoints
[i
].x
) vMin
.x
= pPath
->VPoints
[i
].x
;
407 if (vMin
.y
> pPath
->VPoints
[i
].y
) vMin
.y
= pPath
->VPoints
[i
].y
;
408 if (vMin
.z
> pPath
->VPoints
[i
].z
) vMin
.z
= pPath
->VPoints
[i
].z
;
409 if (vMax
.x
< pPath
->VPoints
[i
].x
) vMax
.x
= pPath
->VPoints
[i
].x
;
410 if (vMax
.y
< pPath
->VPoints
[i
].y
) vMax
.y
= pPath
->VPoints
[i
].y
;
411 if (vMax
.z
< pPath
->VPoints
[i
].z
) vMax
.z
= pPath
->VPoints
[i
].z
;
415 sint32 nMinX
, nMinY
, nMaxX
, nMaxY
;
416 nMinX
= (sint32
) floor (vMin
.x
/ fCellSize
);
417 nMinY
= (sint32
) floor (vMin
.y
/ fCellSize
);
418 nMaxX
= (sint32
) floor (vMax
.x
/ fCellSize
);
419 nMaxY
= (sint32
) floor (vMax
.y
/ fCellSize
);
421 for (x
= nMinX
; x
<= nMaxX
; ++x
)
422 for (y
= nMinY
; y
<= nMaxY
; ++y
)
424 // Does the zone (x,y) is under the patat ?
425 bool bZoneUnderPatat
= false;
426 // Is a vertex of the zone in the patat ?
428 vSquare
[0].x
= x
* fCellSize
;
429 vSquare
[0].y
= y
* fCellSize
;
432 vSquare
[1].x
= (x
+1) * fCellSize
;
433 vSquare
[1].y
= y
* fCellSize
;
436 vSquare
[2].x
= (x
+1) * fCellSize
;
437 vSquare
[2].y
= (y
+1) * fCellSize
;
440 vSquare
[3].x
= x
* fCellSize
;
441 vSquare
[3].y
= (y
+1) * fCellSize
;
444 // Is a vertex of the path inside the zone ?
445 for (i
= 0; i
< pPath
->VPoints
.size(); ++i
)
447 if ((pPath
->VPoints
[i
].x
>= (x
*fCellSize
)) &&
448 (pPath
->VPoints
[i
].x
<= ((x
+1)*fCellSize
)) &&
449 (pPath
->VPoints
[i
].y
>= (y
*fCellSize
)) &&
450 (pPath
->VPoints
[i
].y
<= ((y
+1)*fCellSize
)))
452 string sTmp
= CExport::getZoneNameFromXY(x
,y
) + ".ig";
453 if (!CTools::fileExist(sTmp
)) // If the file does not exist
454 return true; // need update
458 // Is an edge of the zone cut an edge of the patat ?
459 for (i
= 0; i
< (pPath
->VPoints
.size()-1); ++i
)
460 for (j
= 0; j
< 4; ++j
)
462 double x1
= vSquare
[j
].x
;
463 double y1
= vSquare
[j
].y
;
464 double x2
= vSquare
[(j
+1)%4].x
;
465 double y2
= vSquare
[(j
+1)%4].y
;
467 double x3
= pPath
->VPoints
[i
].x
;
468 double y3
= pPath
->VPoints
[i
].y
;
469 double x4
= pPath
->VPoints
[i
+1].x
;
470 double y4
= pPath
->VPoints
[i
+1].y
;
472 if (segmentIntersection(x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
))
474 string sTmp
= CExport::getZoneNameFromXY (x
, y
) + ".ig";
475 if (!CTools::fileExist(sTmp
)) // If the file does not exist
476 return true; // need update
483 // ---------------------------------------------------------------------------
484 // A path needs an update if there is at least one zone under itself that is not present
485 bool CExport::isPointNeedUpdate (float fCellSize
, CPrimPoint
*pPoint
, const string
&sIGOutputDir
)
487 CTools::chdir (sIGOutputDir
);
490 x
= (sint32
) floor (pPoint
->Point
.x
/ fCellSize
);
491 y
= (sint32
) floor (pPoint
->Point
.y
/ fCellSize
);
493 // Does the zone (x,y) is under the patat ?
494 bool bZoneUnderPatat
= false;
495 // Is a vertex of the zone in the patat ?
497 vSquare
[0].x
= x
* fCellSize
;
498 vSquare
[0].y
= y
* fCellSize
;
501 vSquare
[1].x
= (x
+1) * fCellSize
;
502 vSquare
[1].y
= y
* fCellSize
;
505 vSquare
[2].x
= (x
+1) * fCellSize
;
506 vSquare
[2].y
= (y
+1) * fCellSize
;
509 vSquare
[3].x
= x
* fCellSize
;
510 vSquare
[3].y
= (y
+1) * fCellSize
;
513 // Is the vertex inside the zone ?
514 if ((pPoint
->Point
.x
>= (x
*fCellSize
)) &&
515 (pPoint
->Point
.x
<= ((x
+1)*fCellSize
)) &&
516 (pPoint
->Point
.y
>= (y
*fCellSize
)) &&
517 (pPoint
->Point
.y
<= ((y
+1)*fCellSize
)))
519 string sTmp
= CExport::getZoneNameFromXY(x
,y
) + ".ig";
520 if (!CTools::fileExist(sTmp
)) // If the file does not exist
521 return true; // need update
527 // ---------------------------------------------------------------------------
529 // ---------------------------------------------------------------------------
531 // ---------------------------------------------------------------------------
532 SExportOptions::SExportOptions ()
537 // ---------------------------------------------------------------------------
538 bool SExportOptions::loadcf (CConfigFile
&cf
)
541 CConfigFile::CVar
&cvOutIGDir
= cf
.getVar("EXP_OutIGDir");
542 OutIGDir
= cvOutIGDir
.asString();
545 CConfigFile::CVar
&cvInLandscapeDir
= cf
.getVar("EXP_ZoneWDir");
546 InLandscapeDir
= cvInLandscapeDir
.asString();
548 CConfigFile::CVar
&cvLandBankFile
= cf
.getVar("EXP_SmallBank");
549 LandBankFile
= cvLandBankFile
.asString();
550 CConfigFile::CVar
&cvLandFarBankFile
= cf
.getVar("EXP_FarBank");
551 LandFarBankFile
= cvLandFarBankFile
.asString();
552 CConfigFile::CVar
&cvLandTileNoiseDir
= cf
.getVar("EXP_DisplaceDir");
553 LandTileNoiseDir
= cvLandTileNoiseDir
.asString();
555 CConfigFile::CVar
&cvCellSize
= cf
.getVar("EXP_CellSize");
556 CellSize
= cvCellSize
.asFloat();
558 CConfigFile::CVar
&cvPrimFloraDir
= cf
.getVar("EXP_PrimFloraDir");
559 PrimFloraDir
= cvPrimFloraDir
.asString();
564 // ---------------------------------------------------------------------------
565 bool SExportOptions::save (FILE *f
)
567 fprintf (f
,"\n// Export Options\n");
568 fprintf (f
, "EXP_OutIGDir = \"%s\";\n", OutIGDir
.c_str());
569 fprintf (f
, "EXP_ZoneWDir = \"%s\";\n", InLandscapeDir
.c_str());
570 fprintf (f
, "EXP_SmallBank = \"%s\";\n", LandBankFile
.c_str());
571 fprintf (f
, "EXP_FarBank = \"%s\";\n", LandFarBankFile
.c_str());
572 fprintf (f
, "EXP_DisplaceDir = \"%s\";\n", LandTileNoiseDir
.c_str());
573 fprintf (f
, "EXP_CellSize = %f;\n", CellSize
);
574 fprintf (f
, "EXP_PrimFloraDir = \"%s\";\n", PrimFloraDir
.c_str());
578 // ---------------------------------------------------------------------------
580 // ---------------------------------------------------------------------------
582 // ---------------------------------------------------------------------------
583 bool SExportPrimitive::operator == (const SExportPrimitive
&rRightArg
)
585 if (strcmp(this->FullPrimName
.c_str(), rRightArg
.FullPrimName
.c_str()) == 0)
586 if (strcmp(this->PrimitiveName
.c_str(), rRightArg
.PrimitiveName
.c_str()) == 0)
591 // ---------------------------------------------------------------------------
593 // ---------------------------------------------------------------------------
595 // ---------------------------------------------------------------------------
605 // ---------------------------------------------------------------------------
608 if (_Landscape
!= NULL
)
612 _VCM
->deleteEntity (_VCE
);
619 // ---------------------------------------------------------------------------
620 bool CExport::newExport (SExportOptions
&opt
, IExportCB
*expCB
)
622 _ExeDir
= CTools::pwd();
631 // First of all read the CFG
632 string sContinentDir
= _Options
->PrimFloraDir
;
634 sContinentDir
= CTools::normalizePath (sContinentDir
);
635 CTools::chdir (sContinentDir
.c_str()); // Relative to absolute path
636 sContinentDir
= CTools::pwd () + "\\";
637 CTools::chdir (_ExeDir
);
639 // Read continent.cfg
640 SContinentCfg ContinentCFG
;
642 string sTmp
= sContinentDir
+ "continent.cfg";
643 if (!ContinentCFG
.load(sTmp
.c_str()))
644 throw Exception("Cannot load continent.cfg");
647 // Ok set parameters from options first and with CFG if no options set
649 if (_Options
->OutIGDir
.empty())
650 _OutIGDir
= CTools::normalizePath (ContinentCFG
.OutIGDir
);
652 _OutIGDir
= CTools::normalizePath (_Options
->OutIGDir
);
654 if (_Options
->LandFile
.empty())
655 _LandFile
= ContinentCFG
.LandFile
;
657 _LandFile
= _Options
->LandFile
;
659 if (_Options
->DfnDir
.empty())
660 _DfnDir
= ContinentCFG
.DfnDir
;
662 _DfnDir
= _Options
->DfnDir
;
664 if (_Options
->GameElemDir
.empty())
665 _GameElemDir
= ContinentCFG
.GameElemDir
;
667 _GameElemDir
= _Options
->GameElemDir
;
669 if (_Options
->InLandscapeDir
.empty())
670 _InLandscapeDir
= ContinentCFG
.LandZoneWDir
; // Directory where to get .zonew files
672 _InLandscapeDir
= _Options
->InLandscapeDir
;
674 if (_Options
->LandFarBankFile
.empty())
675 _LandBankFile
= ContinentCFG
.LandBankFile
; // The .smallbank file associated with the landscape
677 _LandBankFile
= _Options
->LandBankFile
;
679 if (_Options
->LandFarBankFile
.empty())
680 _LandFarBankFile
= ContinentCFG
.LandFarBankFile
; // The .farbank file
682 _LandFarBankFile
= _Options
->LandFarBankFile
;
684 if (_Options
->LandTileNoiseDir
.empty())
685 _LandTileNoiseDir
= ContinentCFG
.LandTileNoiseDir
; // Directory where to get displacement map
687 _LandTileNoiseDir
= _Options
->LandTileNoiseDir
;
690 // Now create output directory
691 CTools::mkdir (_OutIGDir
);
693 CTools::chdir (_OutIGDir
.c_str());
694 _OutIGDir
= CTools::pwd () + "\\";
695 CTools::chdir (_ExeDir
);
698 CPath::addSearchPath (_DfnDir
, true, true);
699 CPath::addSearchPath (_GameElemDir
, true, true);
700 CPath::addSearchPath (_LandTileNoiseDir
, true, true);
704 vector
<string
> vRegions
;
705 WIN32_FIND_DATA findData
;
708 CTools::chdir (sContinentDir
);
709 hFind
= FindFirstFile ("*.*", &findData
);
710 while (hFind
!= INVALID_HANDLE_VALUE
)
712 if (GetFileAttributes(findData
.cFileName
)&FILE_ATTRIBUTE_DIRECTORY
)
714 // Look if the name is a system directory
716 for (i
= 0; i
< MAX_SYS_DIR
; ++i
)
717 if (stricmp (findData
.cFileName
, gExportSysDir
[i
]) == 0)
722 if (!bFound
) // No, ok lets recurse it
724 vRegions
.push_back (findData
.cFileName
);
727 if (FindNextFile (hFind
, &findData
) == 0)
733 // Process all regions
735 for (nRegion
= 0; nRegion
< vRegions
.size(); ++nRegion
)
737 CTools::chdir (sContinentDir
+ vRegions
[nRegion
]);
739 // Process if a flora has been modified
740 vector
<SFloraToUpdate
> vFloraToUpdate
;
743 // Fill the structure for update
745 // Get all new flora of the region
746 vector
<string
> vFloraFiles
;
747 CTools::dirSub ("*.flora", vFloraFiles
, true);
748 for (nFloraFile
= 0; nFloraFile
< vFloraFiles
.size(); ++nFloraFile
)
750 // Compare the date with the old file stored in the IG output directory
751 CTools::chdir (sContinentDir
+ vRegions
[nRegion
]);
752 string sBaseName
= vFloraFiles
[nFloraFile
].substr(sContinentDir
.size());
753 sBaseName
= sBaseName
.substr(0,sBaseName
.rfind('\\'));
754 for (i
= 0; i
< sBaseName
.size(); ++i
)
755 if (sBaseName
[i
] == '\\')
758 string sOldFloraName
= _OutIGDir
+ sBaseName
+ vFloraFiles
[nFloraFile
].substr(vFloraFiles
[nFloraFile
].rfind('\\')+1);
760 if (CTools::fileExist(sOldFloraName
))
762 if (CTools::fileDateCmp(vFloraFiles
[nFloraFile
], sOldFloraName
) > 0)
764 // Delete zones from the 2 files
765 SFloraToUpdate ftuTmp
;
766 // Delete zones from the newest file
767 ftuTmp
.FloraFile
= vFloraFiles
[nFloraFile
];
768 CTools::chdir (vFloraFiles
[nFloraFile
].substr(0,vFloraFiles
[nFloraFile
].rfind('\\')));
769 CTools::dir ("*.prim", ftuTmp
.PrimFile
, true);
770 vFloraToUpdate
.push_back (ftuTmp
);
771 // Delete zones from the oldest file
772 CTools::chdir (_OutIGDir
);
773 ftuTmp
.FloraFile
= sOldFloraName
;
774 CTools::dir (sBaseName
+ "*.prim", ftuTmp
.PrimFile
, true);
775 vFloraToUpdate
.push_back (ftuTmp
);
776 CTools::chdir (_ExeDir
);
777 sTmp
= vFloraFiles
[nFloraFile
] + " has been modified.";
778 if (_ExportCB
!= NULL
) _ExportCB
->dispInfo (sTmp
);
782 CTools::chdir (_ExeDir
);
783 sTmp
= vFloraFiles
[nFloraFile
] + string(" up to date.");
784 if (_ExportCB
!= NULL
) _ExportCB
->dispInfo (sTmp
);
789 // Delete zone from newest file
790 SFloraToUpdate ftuTmp
;
791 ftuTmp
.FloraFile
= vFloraFiles
[nFloraFile
];
792 CTools::chdir (vFloraFiles
[nFloraFile
].substr(0,vFloraFiles
[nFloraFile
].rfind('\\')));
793 CTools::dir ("*.prim", ftuTmp
.PrimFile
, true);
794 vFloraToUpdate
.push_back (ftuTmp
);
795 CTools::chdir (_ExeDir
);
796 sTmp
= vFloraFiles
[nFloraFile
] + " not generated.";
797 if (_ExportCB
!= NULL
) _ExportCB
->dispInfo (sTmp
);
801 // Get all old flora of the current region
802 CTools::chdir (_OutIGDir
);
803 CTools::dir (vRegions
[nRegion
] + "-*.flora", vFloraFiles
, true);
804 for (nFloraFile
= 0; nFloraFile
< vFloraFiles
.size(); ++nFloraFile
)
806 CTools::chdir (_OutIGDir
);
807 // if the old flora file still exist but the new one not -> delete zone for the oldest file
808 string sNewFloraName
= vFloraFiles
[nFloraFile
].substr(vFloraFiles
[nFloraFile
].rfind('\\')+1);
809 string sBaseName
= sNewFloraName
.substr (0, vFloraFiles
[nFloraFile
].rfind('-'));
810 for (i
= 0; i
< sNewFloraName
.size(); ++i
)
811 if (sNewFloraName
[i
] == '-')
812 sNewFloraName
[i
] = '\\';
814 sNewFloraName
= sContinentDir
+ sNewFloraName
;
815 if (!CTools::fileExist(sNewFloraName
))
817 SFloraToUpdate ftuTmp
;
818 // Delete zones from the oldest file
819 ftuTmp
.FloraFile
= vFloraFiles
[nFloraFile
];
820 CTools::dir (sBaseName
+ "*.prim", ftuTmp
.PrimFile
, true);
821 vFloraToUpdate
.push_back (ftuTmp
);
822 CTools::chdir (_ExeDir
);
823 sTmp
= vFloraFiles
[nFloraFile
] + " not needed anymore.";
824 if (_ExportCB
!= NULL
) _ExportCB
->dispInfo (sTmp
);
828 // End of fill the structure for update
830 // Interpret the FloraToUpdate
831 for (nFloraFile
= 0; nFloraFile
< vFloraToUpdate
.size(); ++nFloraFile
)
833 // Get all patats referenced by the flora and suppress zones under
835 // Load the .flora file
836 SFormFlora FormFlora
;
839 UFormLoader
*loader
= UFormLoader::createLoader ();
842 CSmartPtr
<UForm
> form
= loader
->loadForm (vFloraToUpdate
[nFloraFile
].FloraFile
.c_str ());
844 FormFlora
.build (form
->getRootNode ());
846 // Release the loader
847 UFormLoader::releaseLoader (loader
);
850 // Load all the .prim files that can be referenced by the flora
851 vector
<CPrimRegion
> vPrimRegions
;
853 vector
<string
> &rPrimFiles
= vFloraToUpdate
[nFloraFile
].PrimFile
;
854 for (i
= 0; i
< rPrimFiles
.size(); ++i
)
856 CPrimRegion tmpPrimRegion
;
858 fileIn
.open (rPrimFiles
[i
]);
861 tmpPrimRegion
.serial (input
);
862 vPrimRegions
.push_back (tmpPrimRegion
);
866 // Delete zones under the old prims referenced by the old zone
868 for (i
= 0; i
< FormFlora
.IncludePatats
.size(); ++i
)
871 CPrimZone
*pPatat
= NULL
;
872 CPrimPoint
*pPoint
= NULL
;
873 CPrimPath
*pPath
= NULL
;
874 for (j
= 0; j
< vPrimRegions
.size(); ++j
)
876 for (k
= 0; k
< vPrimRegions
[j
].VZones
.size(); ++k
)
877 if (vPrimRegions
[j
].VZones
[k
].getName() == FormFlora
.IncludePatats
[i
])
878 pPatat
= &vPrimRegions
[j
].VZones
[k
];
879 for (k
= 0; k
< vPrimRegions
[j
].VPoints
.size(); ++k
)
880 if (vPrimRegions
[j
].VPoints
[k
].getName() == FormFlora
.IncludePatats
[i
])
881 pPoint
= &vPrimRegions
[j
].VPoints
[k
];
882 for (k
= 0; k
< vPrimRegions
[j
].VPaths
.size(); ++k
)
883 if (vPrimRegions
[j
].VPaths
[k
].getName() == FormFlora
.IncludePatats
[i
])
884 pPath
= &vPrimRegions
[j
].VPaths
[k
];
887 if ((pPatat
== NULL
) && (pPoint
== NULL
) && (pPath
== NULL
))
889 CTools::chdir (_ExeDir
);
890 sTmp
= "WARNING : Cannot find " + FormFlora
.IncludePatats
[i
];
891 if (_ExportCB
!= NULL
) _ExportCB
->dispInfo (sTmp
);
895 if ((pPatat
!= NULL
) && (pPatat
->VPoints
.size() <= 2))
897 CTools::chdir (_ExeDir
);
898 sTmp
= "Patat " + pPatat
->getName() + " has less than 3 points";
899 if (_ExportCB
!= NULL
) _ExportCB
->dispInfo (sTmp
);
903 if ((pPath
!= NULL
) && (pPath
->VPoints
.size() < 2))
905 CTools::chdir (_ExeDir
);
906 sTmp
= "Patat " + pPatat
->getName() + " has less than 2 points";
907 if (_ExportCB
!= NULL
) _ExportCB
->dispInfo (sTmp
);
912 delAllIGZoneUnderPatat (160.0f
, pPatat
, _OutIGDir
);
914 delAllIGZoneUnderPoint (160.0f
, pPoint
, _OutIGDir
);
916 delAllIGZoneUnderPath (160.0f
, pPath
, _OutIGDir
);
919 // End of Process if a flora has been modified
921 // Process if a prim has been modified
922 // Fill the structure for update
923 CTools::chdir (sContinentDir
+ vRegions
[nRegion
]);
924 vector
<SPrimToUpdate
> vPrimToUpdate
;
927 vector
<string
> vPrimFiles
;
928 // Get all new prim of the region
929 CTools::dirSub ("*.prim", vPrimFiles
, true);
930 for (nPrimFile
= 0; nPrimFile
< vPrimFiles
.size(); ++nPrimFile
)
932 CTools::chdir (sContinentDir
+ vRegions
[nRegion
]);
933 // Compare the date with the old file stored in the IG output directory
934 string sBaseName
= vPrimFiles
[nPrimFile
].substr(sContinentDir
.size());
935 sBaseName
= sBaseName
.substr(0,sBaseName
.rfind('\\'));
936 for (i
= 0; i
< sBaseName
.size(); ++i
)
937 if (sBaseName
[i
] == '\\')
940 string sOldPrimName
= _OutIGDir
+ sBaseName
+ vPrimFiles
[nPrimFile
].substr(vPrimFiles
[nPrimFile
].rfind('\\')+1);
942 if (CTools::fileExist(sOldPrimName
))
944 if (CTools::fileDateCmp(vPrimFiles
[nPrimFile
], sOldPrimName
) > 0)
946 // Delete zones from the 2 files
947 SPrimToUpdate ptuTmp
;
948 // Delete zones from the newest file
949 ptuTmp
.PrimFile
= vPrimFiles
[nPrimFile
];
950 CTools::chdir (vPrimFiles
[nPrimFile
].substr(0,vPrimFiles
[nPrimFile
].rfind('\\')));
951 CTools::dir ("*.flora", ptuTmp
.FloraFile
, true);
952 vPrimToUpdate
.push_back (ptuTmp
);
953 // Delete zones from the oldest file
954 CTools::chdir (_OutIGDir
);
955 ptuTmp
.PrimFile
= sOldPrimName
;
956 CTools::dir (sBaseName
+ "*.flora", ptuTmp
.FloraFile
, true);
957 vPrimToUpdate
.push_back (ptuTmp
);
958 CTools::chdir (_ExeDir
);
959 sTmp
= vPrimFiles
[nPrimFile
] + " has been modified.";
960 if (_ExportCB
!= NULL
) _ExportCB
->dispInfo (sTmp
);
964 CTools::chdir (_ExeDir
);
965 sTmp
= vPrimFiles
[nPrimFile
] + " up to date.";
966 if (_ExportCB
!= NULL
) _ExportCB
->dispInfo (sTmp
);
971 // Delete zone from newest file
972 SPrimToUpdate ptuTmp
;
973 ptuTmp
.PrimFile
= vPrimFiles
[nPrimFile
];
974 CTools::chdir (vPrimFiles
[nPrimFile
].substr(0,vPrimFiles
[nPrimFile
].rfind('\\')));
975 CTools::dir ("*.flora", ptuTmp
.FloraFile
, true);
976 vPrimToUpdate
.push_back (ptuTmp
);
977 CTools::chdir (_ExeDir
);
978 sTmp
= vPrimFiles
[nPrimFile
] + " not generated.";
979 if (_ExportCB
!= NULL
) _ExportCB
->dispInfo (sTmp
);
983 // Get all old prim of the current region
984 CTools::chdir (_OutIGDir
);
985 CTools::dir (vRegions
[nRegion
] + "-*.prim", vPrimFiles
, false);
986 for (nPrimFile
= 0; nPrimFile
< vPrimFiles
.size(); ++nPrimFile
)
988 CTools::chdir (_OutIGDir
);
989 // if the old prim file still exist but the new one not -> delete zone for the oldest file
990 string sNewPrimName
= vPrimFiles
[nPrimFile
].substr(vPrimFiles
[nPrimFile
].rfind('\\')+1);
991 string sBaseName
= sNewPrimName
.substr (0, vPrimFiles
[nPrimFile
].rfind('-'));
992 for (i
= 0; i
< sNewPrimName
.size(); ++i
)
993 if (sNewPrimName
[i
] == '-')
994 sNewPrimName
[i
] = '\\';
996 sNewPrimName
= sContinentDir
+ sNewPrimName
;
997 if (!CTools::fileExist(sNewPrimName
))
999 // Delete zones from the oldest file
1000 CPrimRegion PrimRegion
;
1003 fileIn
.open (vPrimFiles
[nPrimFile
]);
1005 input
.init (fileIn
);
1006 PrimRegion
.serial (input
);
1009 for (j
= 0; j
< PrimRegion
.VZones
.size(); ++j
)
1010 delAllIGZoneUnderPatat (_Options
->CellSize
, &PrimRegion
.VZones
[j
], _OutIGDir
);
1011 for (j
= 0; j
< PrimRegion
.VPaths
.size(); ++j
)
1012 delAllIGZoneUnderPath (_Options
->CellSize
, &PrimRegion
.VPaths
[j
], _OutIGDir
);
1013 for (j
= 0; j
< PrimRegion
.VPoints
.size(); ++j
)
1014 delAllIGZoneUnderPoint (_Options
->CellSize
, &PrimRegion
.VPoints
[j
], _OutIGDir
);
1016 CTools::chdir (_ExeDir
);
1017 sTmp
= vPrimFiles
[nPrimFile
] + " not needed anymore.";
1018 if (_ExportCB
!= NULL
) _ExportCB
->dispInfo (sTmp
);
1022 // End of fill the structure for update
1024 // Interpretation of structure for update
1025 for (i
= 0; i
< vPrimToUpdate
.size(); ++i
)
1027 // Load all the .flora file
1028 vector
<SFormFlora
> vFormFloras
;
1029 for (j
= 0; j
< vPrimToUpdate
[i
].FloraFile
.size(); ++j
)
1031 // Create the loader
1032 UFormLoader
*loader
= UFormLoader::createLoader ();
1035 CSmartPtr
<UForm
> form
= loader
->loadForm (vPrimToUpdate
[i
].FloraFile
[j
].c_str ());
1038 SFormFlora FormFloraTmp
;
1039 FormFloraTmp
.build (form
->getRootNode ());
1040 vFormFloras
.push_back (FormFloraTmp
);
1043 // Release the loader
1044 UFormLoader::releaseLoader (loader
);
1047 // Load all the .prim files that can be referenced by the flora
1048 CPrimRegion PrimRegion
;
1051 fileIn
.open (vPrimToUpdate
[i
].PrimFile
);
1053 input
.init (fileIn
);
1054 PrimRegion
.serial (input
);
1057 // Delete zones under the prims that has been referenced by a flora
1059 for (j
= 0; j
< PrimRegion
.VZones
.size(); ++j
)
1062 CPrimZone
*pPatat
= NULL
;
1064 // Check if the current patat is referenced by a flora
1065 for (k
= 0; k
< vFormFloras
.size(); ++k
)
1066 for (m
= 0; m
< vFormFloras
[k
].IncludePatats
.size(); ++m
)
1067 if (PrimRegion
.VZones
[j
].getName() == vFormFloras
[k
].IncludePatats
[m
])
1068 pPatat
= &PrimRegion
.VZones
[j
];
1070 if ((pPatat
== NULL
) || (pPatat
->VPoints
.size() <= 2))
1074 delAllIGZoneUnderPatat (_Options
->CellSize
, pPatat
, _OutIGDir
);
1076 for (j
= 0; j
< PrimRegion
.VPoints
.size(); ++j
)
1079 CPrimPoint
*pPoint
= NULL
;
1081 // Check if the current point is referenced by a flora
1082 for (k
= 0; k
< vFormFloras
.size(); ++k
)
1083 for (m
= 0; m
< vFormFloras
[k
].IncludePatats
.size(); ++m
)
1084 if (PrimRegion
.VPoints
[j
].getName() == vFormFloras
[k
].IncludePatats
[m
])
1085 pPoint
= &PrimRegion
.VPoints
[j
];
1086 delAllIGZoneUnderPoint (_Options
->CellSize
, pPoint
, _OutIGDir
);
1088 for (j
= 0; j
< PrimRegion
.VPaths
.size(); ++j
)
1091 CPrimPath
*pPath
= NULL
;
1093 // Check if the current path is referenced by a flora
1094 for (k
= 0; k
< vFormFloras
.size(); ++k
)
1095 for (m
= 0; m
< vFormFloras
[k
].IncludePatats
.size(); ++m
)
1096 if (PrimRegion
.VPaths
[j
].getName() == vFormFloras
[k
].IncludePatats
[m
])
1097 pPath
= &PrimRegion
.VPaths
[j
];
1098 delAllIGZoneUnderPath (_Options
->CellSize
, pPath
, _OutIGDir
);
1101 // End of Process if a prim has been modified
1104 // End of process all regions
1106 // Check all patat to export (a patat that has no zone under itself (deleted or not present))
1107 vector
<SExportPrimitive
> vExportPrimitives
;
1108 vector
<string
> vAllPrimFiles
; // All prim files of a continent
1109 CTools::chdir (sContinentDir
);
1110 CTools::dirSub ("*.prim", vAllPrimFiles
, true);
1111 for (i
= 0; i
< vAllPrimFiles
.size(); ++i
)
1113 vAllPrimFiles
[i
] = strlwr(vAllPrimFiles
[i
]);
1114 // Load the primfile
1115 CPrimRegion PrimRegion
;
1118 fileIn
.open (vAllPrimFiles
[i
]);
1120 input
.init (fileIn
);
1121 PrimRegion
.serial (input
);
1124 for (j
= 0; j
< PrimRegion
.VZones
.size(); ++j
)
1126 // Check all zones to know if this patat must be updated
1127 if (isPatatNeedUpdate(_Options
->CellSize
, &PrimRegion
.VZones
[j
], _OutIGDir
))
1129 SExportPrimitive epTmp
;
1130 epTmp
.FullPrimName
= vAllPrimFiles
[i
];
1131 epTmp
.PrimitiveName
= PrimRegion
.VZones
[j
].getName();
1132 vExportPrimitives
.push_back (epTmp
);
1136 for (j
= 0; j
< PrimRegion
.VPaths
.size(); ++j
)
1138 // Check all pathes to know if some must be updated (if no zone under)
1139 if (isPathNeedUpdate(_Options
->CellSize
, &PrimRegion
.VPaths
[j
], _OutIGDir
))
1141 SExportPrimitive epTmp
;
1142 epTmp
.FullPrimName
= vAllPrimFiles
[i
];
1143 epTmp
.PrimitiveName
= PrimRegion
.VPaths
[j
].getName();
1144 vExportPrimitives
.push_back (epTmp
);
1148 for (j
= 0; j
< PrimRegion
.VPoints
.size(); ++j
)
1150 // Check all points to know if some must be updated (if no zone under)
1151 if (isPointNeedUpdate(_Options
->CellSize
, &PrimRegion
.VPoints
[j
], _OutIGDir
))
1153 SExportPrimitive epTmp
;
1154 epTmp
.FullPrimName
= vAllPrimFiles
[i
];
1155 epTmp
.PrimitiveName
= PrimRegion
.VPoints
[j
].getName();
1156 vExportPrimitives
.push_back (epTmp
);
1163 CTools::chdir (_ExeDir
);
1164 _Options
->PrimFloraDir
= sContinentDir
;
1166 if (_ExportCB
!= NULL
) _ExportCB
->dispInfo (sTmp
);
1167 doExport (*_Options
, _ExportCB
, &vExportPrimitives
);
1169 // Copy new files for incremental purpose
1170 CTools::chdir (_ExeDir
);
1171 sTmp
= "Incrementing";
1172 if (_ExportCB
!= NULL
) _ExportCB
->dispInfo (sTmp
);
1173 for (nRegion
= 0; nRegion
< vRegions
.size(); ++nRegion
)
1175 CTools::chdir (sContinentDir
+ vRegions
[nRegion
]);
1176 vector
<string
> vFiles
;
1177 CTools::dirSub ("*.prim", vFiles
, true);
1178 for (i
= 0; i
< vFiles
.size(); ++i
)
1180 string sDst
= vFiles
[i
].substr (sContinentDir
.size());
1181 for (j
= 0; j
< sDst
.size(); ++j
)
1182 if (sDst
[j
] == '\\')
1184 sDst
= _OutIGDir
+ sDst
;
1185 CTools::copy (sDst
, vFiles
[i
]);
1187 CTools::chdir (sContinentDir
+ vRegions
[nRegion
]);
1188 CTools::dirSub ("*.flora", vFiles
, true);
1189 for (i
= 0; i
< vFiles
.size(); ++i
)
1191 string sDst
= vFiles
[i
].substr (sContinentDir
.size());
1192 for (j
= 0; j
< sDst
.size(); ++j
)
1193 if (sDst
[j
] == '\\')
1195 sDst
= _OutIGDir
+ sDst
;
1196 CTools::copy (sDst
, vFiles
[i
]);
1199 // -------------------------------------------------------------------
1200 // If the new file do not exists anymore but the old file exists -> delete old file
1201 CTools::chdir (_OutIGDir
);
1202 CTools::dir (vRegions
[nRegion
] + "-*.prim", vFiles
, false);
1203 for (i
= 0; i
< vFiles
.size(); ++i
)
1205 // Get the name of the recent file
1206 string sNewName
= vFiles
[i
];
1207 for (j
= 0; j
< sNewName
.size(); ++j
)
1208 if (sNewName
[j
] == '-')
1211 sNewName
= sContinentDir
+ sNewName
;
1212 if (!CTools::fileExist(sNewName
))
1214 // Delete the oldest file
1215 CFile::deleteFile(vFiles
[i
]);
1219 // If the new file do not exists anymore but the old file exists -> delete old file
1220 CTools::dir (vRegions
[nRegion
] + "-*.flora", vFiles
, false);
1221 for (i
= 0; i
< vFiles
.size(); ++i
)
1223 // Get the name of the recent file
1224 string sNewName
= vFiles
[i
];
1225 for (j
= 0; j
< sNewName
.size(); ++j
)
1226 if (sNewName
[j
] == '-')
1229 sNewName
= sContinentDir
+ sNewName
;
1230 if (!CTools::fileExist(sNewName
))
1232 // Delete the oldest file
1233 CFile::deleteFile(vFiles
[i
]);
1238 CTools::chdir (_ExeDir
);
1242 // ---------------------------------------------------------------------------
1243 bool CExport::doExport (SExportOptions
&opt
, IExportCB
*expCB
, vector
<SExportPrimitive
> *selection
)
1245 char sTmp
[MAX_PATH
];
1246 GetCurrentDirectory (MAX_PATH
, sTmp
);
1251 // Does we have something to export
1252 if ((selection
!= NULL
) && (selection
->empty()))
1255 _ExportCB
->dispInfo ("Nothing to export");
1259 // If we want to generate flora then we have to load the landscape
1263 _ExportCB
->dispPass ("Load Landscape");
1264 if (_Landscape
== NULL
)
1266 _Landscape
= new CLandscape
;
1267 _Landscape
->init ();
1268 _VCM
= new CVisualCollisionManager
;
1269 _VCE
= _VCM
->createEntity ();
1270 _VCM
->setLandscape (_Landscape
);
1271 _VCE
->setSnapToRenderedTesselation (false);
1274 CIFile
bankFile (_LandBankFile
);
1275 _Landscape
->TileBank
.serial (bankFile
);
1276 CIFile
farbankFile (_LandFarBankFile
);
1277 _Landscape
->TileFarBank
.serial (farbankFile
);
1278 _Landscape
->TileBank
.makeAllPathRelative ();
1279 _Landscape
->TileBank
.setAbsPath ("");
1280 _Landscape
->TileBank
.makeAllExtensionDDS ();
1281 _Landscape
->initTileBanks ();
1283 loadLandscape (_LandFile
);
1285 catch (const Exception
&/*e*/)
1288 _ExportCB
->dispError ("Cannot load banks files");
1292 _FloraInsts
.clear ();
1294 _ExportCB
->dispPass ("Generate Flora");
1295 vector
<string
> allFloraFiles
;
1296 SetCurrentDirectory (_Options
->PrimFloraDir
.c_str());
1297 getAllFiles (".Flora", allFloraFiles
);
1298 SetCurrentDirectory (sTmp
);
1299 for (i
= 0; i
< allFloraFiles
.size(); ++i
)
1301 generateIGFromFlora (allFloraFiles
[i
], selection
);
1304 writeFloraIG (_LandFile
, (selection
!= NULL
)); // If selection != NULL then test for writing
1306 SetCurrentDirectory (sTmp
);
1308 _ExportCB
->dispPass ("Finished");
1313 // ---------------------------------------------------------------------------
1314 void CExport::getAllFiles (const string
&ext
, vector
<string
> &files
)
1316 char sCurDir
[MAX_PATH
];
1317 GetCurrentDirectory (MAX_PATH
, sCurDir
);
1319 WIN32_FIND_DATA findData
;
1320 HANDLE hFind
= FindFirstFile ("*.*", &findData
);
1321 while (hFind
!= INVALID_HANDLE_VALUE
)
1323 if (!((strcmp (findData
.cFileName
, ".") == 0) || (strcmp (findData
.cFileName
, "..") == 0)))
1325 if (findData
.dwFileAttributes
&FILE_ATTRIBUTE_DIRECTORY
)
1327 string sNewDir
= sCurDir
;
1328 sNewDir
+= string("\\") + findData
.cFileName
;
1329 SetCurrentDirectory (sNewDir
.c_str());
1330 getAllFiles (ext
, files
);
1331 SetCurrentDirectory (sCurDir
);
1335 if (strlen(findData
.cFileName
) > strlen(ext
.c_str()))
1336 if (stricmp(&findData
.cFileName
[strlen(findData
.cFileName
)-strlen(ext
.c_str())], ext
.c_str()) == 0)
1338 string fullName
= sCurDir
;
1339 fullName
+= string("\\") + findData
.cFileName
;
1340 fullName
= strlwr (fullName
);
1341 files
.push_back (fullName
);
1346 if (FindNextFile (hFind
, &findData
) == 0)
1351 SetCurrentDirectory (sCurDir
);
1354 // ---------------------------------------------------------------------------
1355 bool CExport::searchFile (const std::string
&plantName
, std::string
&dir
)
1357 char sCurDir
[MAX_PATH
];
1358 bool bFound
= false;
1359 GetCurrentDirectory (MAX_PATH
, sCurDir
);
1361 WIN32_FIND_DATA findData
;
1362 HANDLE hFind
= FindFirstFile ("*.*", &findData
);
1363 while (hFind
!= INVALID_HANDLE_VALUE
)
1365 string filename
= findData
.cFileName
;
1366 filename
= strlwr(filename
);
1367 if (!((filename
== ".") || (filename
== "..")))
1369 if (findData
.dwFileAttributes
&FILE_ATTRIBUTE_DIRECTORY
)
1371 string sNewDir
= sCurDir
;
1372 sNewDir
+= string("\\") + filename
;
1373 SetCurrentDirectory (sNewDir
.c_str());
1374 if (searchFile (plantName
, dir
))
1379 SetCurrentDirectory (sCurDir
);
1383 if (strlwr(plantName
) == filename
)
1392 if (FindNextFile (hFind
, &findData
) == 0)
1396 SetCurrentDirectory (sCurDir
);
1400 // ---------------------------------------------------------------------------
1401 bool CExport::generateIGFromFlora (const std::string
&SrcFile
, std::vector
<SExportPrimitive
> *selection
)
1403 uint32 i
, j
, k
, l
, m
;
1406 _ExportCB
->dispPass ("Generating From " + SrcFile
);
1409 vector
<CPrimRegion
> allPrimRegion
;
1410 vector
<string
> allPrimFiles
;
1412 char sCurDir
[MAX_PATH
];
1413 GetCurrentDirectory (MAX_PATH
, sCurDir
);
1414 SetCurrentDirectory (_Options
->PrimFloraDir
.c_str());
1415 getAllFiles (".prim", allPrimFiles
);
1416 SetCurrentDirectory (sCurDir
);
1417 for (i
= 0; i
< allPrimFiles
.size(); ++i
)
1421 CPrimRegion tmpPrimRegion
;
1423 fileIn
.open (allPrimFiles
[i
]);
1425 input
.init (fileIn
);
1426 tmpPrimRegion
.serial (input
);
1427 allPrimRegion
.push_back (tmpPrimRegion
);
1429 catch (const Exception
&/*e*/)
1431 if (_ExportCB
!= NULL
)
1432 _ExportCB
->dispWarning (string("Cant load ") + allPrimFiles
[i
]);
1433 CPrimRegion tmpPrimRegion
;
1434 allPrimRegion
.push_back (tmpPrimRegion
);
1439 // Load the .Flora file (georges file) and load all associated .plant
1440 SFormFlora formFlora
;
1441 map
<string
, SFormPlant
> Plants
;
1444 UFormLoader
*loader
= UFormLoader::createLoader ();
1445 // CPath::addSearchPath (_Options->DfnDir, true, true);
1446 // CPath::addSearchPath (_Options->GameElemDir, true, true);
1447 // CPath::addSearchPath (_Options->LandTileNoiseDir, true, true);
1450 CSmartPtr
<UForm
> form
= loader
->loadForm (SrcFile
.c_str ());
1453 if (_ExportCB
!= NULL
)
1454 _ExportCB
->dispError (string("Cant load ") + SrcFile
);
1459 formFlora
.build (form
->getRootNode ());
1461 // Load the .plant associated
1462 for (i
= 0; i
< formFlora
.PlantInstances
.size(); ++i
)
1464 const string
&plantName
= formFlora
.PlantInstances
[i
].Name
;
1465 map
<string
, SFormPlant
>::iterator it
= Plants
.find (plantName
);
1466 if (it
!= Plants
.end()) // Already here ?!
1469 char sCurDir
[MAX_PATH
];
1470 GetCurrentDirectory (MAX_PATH
, sCurDir
);
1474 SetCurrentDirectory (_GameElemDir
.c_str());
1477 if (searchFile (plantName
, dir
))
1479 string tmpName
= dir
+ string("\\") + plantName
;
1481 CSmartPtr
<UForm
> form2
= loader
->loadForm (tmpName
.c_str());
1484 SFormPlant plantTmp
;
1485 plantTmp
.build (form2
->getRootNode ());
1486 Plants
.insert (map
<string
, SFormPlant
>::value_type(plantName
, plantTmp
));
1490 if (_ExportCB
!= NULL
)
1491 _ExportCB
->dispWarning (string("Cant load ") + plantName
);
1496 if (_ExportCB
!= NULL
)
1497 _ExportCB
->dispWarning (string("Cant load ") + plantName
);
1499 SetCurrentDirectory (sCurDir
);
1501 catch (const Exception
&e
)
1503 SetCurrentDirectory (sCurDir
);
1504 if (_ExportCB
!= NULL
)
1505 _ExportCB
->dispWarning (string("Cant load ") + plantName
+ "(" + e
.what() + ")" );
1511 // Sort PlantInstances by biggest radius first
1512 if (formFlora
.PlantInstances
.size() > 1)
1513 for (i
= 0; i
< (formFlora
.PlantInstances
.size()-1); ++i
)
1514 for (j
= i
+1; j
< formFlora
.PlantInstances
.size(); ++j
)
1516 SPlantInstance
&rPlantI
= formFlora
.PlantInstances
[i
];
1517 SPlantInstance
&rPlantJ
= formFlora
.PlantInstances
[j
];
1518 map
<string
, SFormPlant
>::iterator it
= Plants
.find (rPlantI
.Name
);
1519 if (it
== Plants
.end())
1521 SFormPlant
&rFormPlantI
= it
->second
;
1523 it
= Plants
.find (rPlantJ
.Name
);
1524 if (it
== Plants
.end())
1526 SFormPlant
&rFormPlantJ
= it
->second
;
1527 if (rFormPlantI
.BoundingRadius
< rFormPlantJ
.BoundingRadius
)
1529 SPlantInstance pi
= formFlora
.PlantInstances
[i
];
1530 formFlora
.PlantInstances
[i
] = formFlora
.PlantInstances
[j
];
1531 formFlora
.PlantInstances
[j
] = pi
;
1536 float jitter
= formFlora
.JitterPos
;
1537 clamp (jitter
, 0.0f
, 1.0f
);
1538 srand (formFlora
.RandomSeed
);
1539 for (i
= 0; i
< formFlora
.IncludePatats
.size(); ++i
)
1541 uint32 nCurPlant
= 0;
1545 _ExportCB
->dispPass ("IncludePatats("+toString(i
+1)+"/"+toString(formFlora
.IncludePatats
.size())+")");
1548 CPrimZone
*pPatat
= NULL
;
1549 CPrimPoint
*pPoint
= NULL
;
1550 CPrimPath
*pPath
= NULL
;
1552 // Look if this is a patat
1553 for (j
= 0; j
< allPrimRegion
.size(); ++j
)
1555 for (k
= 0; k
< allPrimRegion
[j
].VZones
.size(); ++k
)
1557 if (allPrimRegion
[j
].VZones
[k
].getName() == formFlora
.IncludePatats
[i
])
1559 if (selection
!= NULL
)
1561 SExportPrimitive epTmp
;
1562 epTmp
.FullPrimName
= allPrimFiles
[j
];
1563 epTmp
.PrimitiveName
= allPrimRegion
[j
].VZones
[k
].getName();
1564 for (m
= 0; m
< selection
->size(); ++m
)
1565 if (selection
->operator[](m
) == epTmp
)
1567 pPatat
= &allPrimRegion
[j
].VZones
[k
];
1573 pPatat
= &allPrimRegion
[j
].VZones
[k
];
1579 //Look if this is a point
1580 for (j
= 0; j
< allPrimRegion
.size(); ++j
)
1582 for (k
= 0; k
< allPrimRegion
[j
].VPoints
.size(); ++k
)
1584 if (allPrimRegion
[j
].VPoints
[k
].getName() == formFlora
.IncludePatats
[i
])
1586 if (selection
!= NULL
)
1588 SExportPrimitive epTmp
;
1589 epTmp
.FullPrimName
= allPrimFiles
[j
];
1590 epTmp
.PrimitiveName
= allPrimRegion
[j
].VPoints
[k
].getName();
1591 for (m
= 0; m
< selection
->size(); ++m
)
1592 if (selection
->operator[](m
) == epTmp
)
1594 pPoint
= &allPrimRegion
[j
].VPoints
[k
];
1600 pPoint
= &allPrimRegion
[j
].VPoints
[k
];
1606 //Look if this is a path
1607 for (j
= 0; j
< allPrimRegion
.size(); ++j
)
1609 for (k
= 0; k
< allPrimRegion
[j
].VPaths
.size(); ++k
)
1611 if (allPrimRegion
[j
].VPaths
[k
].getName() == formFlora
.IncludePatats
[i
])
1613 if (selection
!= NULL
)
1615 SExportPrimitive epTmp
;
1616 epTmp
.FullPrimName
= allPrimFiles
[j
];
1617 epTmp
.PrimitiveName
= allPrimRegion
[j
].VPaths
[k
].getName();
1618 for (m
= 0; m
< selection
->size(); ++m
)
1619 if (selection
->operator[](m
) == epTmp
)
1621 pPath
= &allPrimRegion
[j
].VPaths
[k
];
1627 pPath
= &allPrimRegion
[j
].VPaths
[k
];
1634 if ((pPatat
== NULL
) && (pPoint
== NULL
) && (pPath
== NULL
))
1636 if (selection
== NULL
)
1638 _ExportCB
->dispWarning ("Cannot find " + formFlora
.IncludePatats
[i
]);
1642 if ((pPatat
!= NULL
) && (pPatat
->VPoints
.size() <= 2))
1645 _ExportCB
->dispWarning ("Patat " + pPatat
->getName() + " has less than 3 points");
1649 if ((pPath
!= NULL
) && (pPath
->VPoints
.size() <= 1))
1652 _ExportCB
->dispWarning ("Path " + pPath
->getName() + " has less than 2 points");
1656 // Generate for a patat
1659 vMin
= vMax
= pPatat
->VPoints
[0];
1660 for (j
= 0; j
< pPatat
->VPoints
.size(); ++j
)
1662 if (vMin
.x
> pPatat
->VPoints
[j
].x
) vMin
.x
= pPatat
->VPoints
[j
].x
;
1663 if (vMin
.y
> pPatat
->VPoints
[j
].y
) vMin
.y
= pPatat
->VPoints
[j
].y
;
1664 if (vMin
.z
> pPatat
->VPoints
[j
].z
) vMin
.z
= pPatat
->VPoints
[j
].z
;
1665 if (vMax
.x
< pPatat
->VPoints
[j
].x
) vMax
.x
= pPatat
->VPoints
[j
].x
;
1666 if (vMax
.y
< pPatat
->VPoints
[j
].y
) vMax
.y
= pPatat
->VPoints
[j
].y
;
1667 if (vMax
.z
< pPatat
->VPoints
[j
].z
) vMax
.z
= pPatat
->VPoints
[j
].z
;
1670 for (j
= 0; j
< formFlora
.PlantInstances
.size(); ++j
)
1672 SPlantInstance
&rPlant
= formFlora
.PlantInstances
[j
];
1673 map
<string
, SFormPlant
>::iterator it
= Plants
.find (rPlant
.Name
);
1674 if (it
== Plants
.end())
1677 _ExportCB
->dispWarning ("Cannot find " + rPlant
.Name
);
1680 SFormPlant
&rFormPlant
= it
->second
;
1682 float squareLength
= (float)sqrt (Pi
*rFormPlant
.BoundingRadius
*rFormPlant
.BoundingRadius
/ rPlant
.Density
);
1683 uint32 nNbPlantX
= 1+(int)floor ((vMax
.x
-vMin
.x
) / squareLength
);
1684 uint32 nNbPlantY
= 1+(int)floor ((vMax
.y
-vMin
.y
) / squareLength
);
1685 for (l
= 0; l
< nNbPlantY
; ++l
)
1686 for (k
= 0; k
< nNbPlantX
; ++k
)
1689 _ExportCB
->dispPassProgress (((float)(k
+l
*nNbPlantX
))/((float)(nNbPlantX
*nNbPlantY
)));
1691 bool bExists
= false;
1694 for (m
= 0; m
< 32; ++m
)
1696 pos
.x
= vMin
.x
+ squareLength
* k
+ (frand(2.0f
)-1.0f
) * jitter
* 0.5f
* squareLength
;
1697 pos
.y
= vMin
.y
+ squareLength
* l
+ (frand(2.0f
)-1.0f
) * jitter
* 0.5f
* squareLength
;
1699 scaleTmp
= (formFlora
.ScaleMax
-formFlora
.ScaleMin
)*frand(1.0)+formFlora
.ScaleMin
;
1700 if (pPatat
->contains(pos
))
1702 if (isWellPlaced(pos
, rPlant
, rFormPlant
, scaleTmp
))
1704 // Testt finally with the exclude patats ...
1706 for (uint32 expat
= 0; expat
< formFlora
.ExcludePatats
.size(); ++expat
)
1708 CPrimZone
*pExPatat
= NULL
;
1709 for (uint32 epj
= 0; epj
< allPrimRegion
.size(); ++epj
)
1710 for (uint32 epk
= 0; epk
< allPrimRegion
[epj
].VZones
.size(); ++epk
)
1711 if (allPrimRegion
[epj
].VZones
[epk
].getName() == formFlora
.ExcludePatats
[expat
])
1713 pExPatat
= &allPrimRegion
[epj
].VZones
[epk
];
1716 if (pExPatat
!= NULL
)
1718 if (pExPatat
->contains(pos
))
1735 vi
.ShapeName
= rFormPlant
.Shape
;
1736 vi
.PlantName
= rPlant
.Name
;
1737 vi
.Scale
= scaleTmp
;
1738 vi
.Radius
= rFormPlant
.BoundingRadius
* vi
.Scale
;
1739 vi
.Rot
= (float)Pi
* frand (1.0);
1741 if (formFlora
.PutOnWater
)
1743 if (pos
.z
< formFlora
.WaterHeight
)
1744 pos
.z
= formFlora
.WaterHeight
;
1747 _FloraInsts
.push_back (vi
);
1748 } // End of for all position of a plant x,y check if we cant put it
1749 } // End of for all plant instances
1750 } // End of Generate for a patat
1752 // Generate for a point
1757 for (j
= 0; j
< formFlora
.PlantInstances
.size(); ++j
)
1759 total
+= formFlora
.PlantInstances
[j
].Density
;
1761 float posf
= total
* frand(1.0);
1763 for (j
= 0; j
< formFlora
.PlantInstances
.size(); ++j
)
1765 total
+= formFlora
.PlantInstances
[j
].Density
;
1766 if (posf
< total
) break;
1768 if (j
== formFlora
.PlantInstances
.size())
1769 j
= (uint32
)formFlora
.PlantInstances
.size()-1;
1771 SPlantInstance
&rPlant
= formFlora
.PlantInstances
[j
];
1772 map
<string
, SFormPlant
>::iterator it
= Plants
.find (rPlant
.Name
);
1773 if (it
== Plants
.end())
1776 _ExportCB
->dispWarning ("Cannot find " + rPlant
.Name
);
1779 SFormPlant
&rFormPlant
= it
->second
;
1782 vi
.ShapeName
= rFormPlant
.Shape
;
1783 vi
.PlantName
= rPlant
.Name
;
1784 vi
.Scale
= (formFlora
.ScaleMax
-formFlora
.ScaleMin
)*frand(1.0)+formFlora
.ScaleMin
;
1785 vi
.Radius
= rFormPlant
.BoundingRadius
* vi
.Scale
;
1786 vi
.Rot
= (float)Pi
* frand (1.0);
1789 pos
.x
= pPoint
->Point
.x
;
1790 pos
.y
= pPoint
->Point
.y
;
1791 pos
.z
= getZFromXY (pos
.x
, pos
.y
);
1792 if (formFlora
.PutOnWater
)
1794 if (pos
.z
< formFlora
.WaterHeight
)
1795 pos
.z
= formFlora
.WaterHeight
;
1798 if (pos
.z
> -90000.0f
)
1799 _FloraInsts
.push_back (vi
);
1800 } // End of Generate for a point
1802 // Generate for a path
1805 float rLength
= 0.0f
; // Total length of the broken line
1806 for (j
= 0; j
< pPath
->VPoints
.size()-1; ++j
)
1808 rLength
+= (pPath
->VPoints
[j
]-pPath
->VPoints
[j
+1]).norm();
1811 for (j
= 0; j
< formFlora
.PlantInstances
.size(); ++j
)
1813 SPlantInstance
&rPlant
= formFlora
.PlantInstances
[j
];
1814 map
<string
, SFormPlant
>::iterator it
= Plants
.find (rPlant
.Name
);
1815 if (it
== Plants
.end())
1818 _ExportCB
->dispWarning ("Cannot find " + rPlant
.Name
);
1821 SFormPlant
&rFormPlant
= it
->second
;
1823 float squareLength
= (float)(2*rFormPlant
.BoundingRadius
/ rPlant
.Density
);
1824 uint32 nNbPlant
= 1+(int)floor (rLength
/ squareLength
);
1826 for (k
= 0; k
< nNbPlant
; ++k
)
1829 _ExportCB
->dispPassProgress (((float)(k
))/((float)(nNbPlant
)));
1831 bool bExists
= false;
1834 for (m
= 0; m
< 32; ++m
)
1836 // Calculate the curviline abscisse
1837 float curvAbs
= squareLength
* k
+ (frand(2.0f
)-1.0f
) * jitter
* 0.5f
* squareLength
;
1838 float TempLength
= 0.0f
;
1839 // Convert to a real point along the curve (broken line)
1840 for (l
= 0; l
< pPath
->VPoints
.size()-1; ++l
)
1842 float newSize
= (pPath
->VPoints
[l
]-pPath
->VPoints
[l
+1]).norm();
1843 if (curvAbs
< (TempLength
+newSize
))
1845 curvAbs
-= TempLength
;
1848 TempLength
+= newSize
;
1850 if (l
== (pPath
->VPoints
.size()-1))
1852 l
= (uint32
)pPath
->VPoints
.size()-2;
1853 curvAbs
= (pPath
->VPoints
[l
]-pPath
->VPoints
[l
+1]).norm();
1855 // Calculate the coord
1856 curvAbs
= curvAbs
/ (pPath
->VPoints
[l
]-pPath
->VPoints
[l
+1]).norm();
1857 pos
= pPath
->VPoints
[l
] + (pPath
->VPoints
[l
+1]-pPath
->VPoints
[l
])*curvAbs
;
1859 scaleTmp
= (formFlora
.ScaleMax
-formFlora
.ScaleMin
)*frand(1.0)+formFlora
.ScaleMin
;
1860 if (isWellPlaced(pos
, rPlant
, rFormPlant
, scaleTmp
))
1862 // Test finally with the exclude patats ...
1864 for (uint32 expat
= 0; expat
< formFlora
.ExcludePatats
.size(); ++expat
)
1866 CPrimZone
*pExPatat
= NULL
;
1867 for (uint32 epj
= 0; epj
< allPrimRegion
.size(); ++epj
)
1868 for (uint32 epk
= 0; epk
< allPrimRegion
[epj
].VZones
.size(); ++epk
)
1869 if (allPrimRegion
[epj
].VZones
[epk
].getName() == formFlora
.ExcludePatats
[expat
])
1871 pExPatat
= &allPrimRegion
[epj
].VZones
[epk
];
1874 if (pExPatat
!= NULL
)
1876 if (pExPatat
->contains(pos
))
1892 vi
.ShapeName
= rFormPlant
.Shape
;
1893 vi
.PlantName
= rPlant
.Name
;
1894 vi
.Scale
= scaleTmp
;
1895 vi
.Radius
= rFormPlant
.BoundingRadius
* vi
.Scale
;
1896 vi
.Rot
= (float)Pi
* frand (1.0);
1898 if (formFlora
.PutOnWater
)
1900 if (pos
.z
< formFlora
.WaterHeight
)
1901 pos
.z
= formFlora
.WaterHeight
;
1904 _FloraInsts
.push_back (vi
);
1905 } // End of for all position of a plant x,y check if we cant put it
1906 } // End of for all plant instances
1908 } // End of Generate for a path
1910 } // End of for all IncludePatats
1914 // ---------------------------------------------------------------------------
1915 float CExport::getZFromXY (float x
, float y
)
1917 CVector pos
= CVector(x
, y
, 0);
1919 float z
, zmin
, zmax
;
1921 // Approximate the z with patch bounding boxes
1922 sint32 zoneX
= (sint32
)floor (x
/_Options
->CellSize
);
1923 sint32 zoneY
= (sint32
)floor (-y
/_Options
->CellSize
);
1924 sint32 zoneId
= zoneY
* 256 + zoneX
;
1925 CZone
*pZone
= _Landscape
->getZone (zoneId
);
1929 CAABBoxExt bb
= pZone
->getZoneBB();
1930 zmin
= bb
.getMin().z
;
1931 zmax
= bb
.getMax().z
;
1936 if (_VCE
->snapToGround(pos
, normal
))
1938 z
+= CVisualCollisionEntity::BBoxRadiusZ
/ 2.0f
; // Super sampling due to max frequency on radiosity
1948 // ---------------------------------------------------------------------------
1949 bool CExport::isWellPlaced (CVector
&pos
, SPlantInstance
&rPI
, SFormPlant
&rFP
, float scale
)
1953 // Look if this Flora intersect with one of the current ones
1954 for (i
= 0; i
< _FloraInsts
.size(); ++i
)
1956 CVector temp
= _FloraInsts
[i
].Pos
- pos
;
1958 if (temp
.norm() < (_FloraInsts
[i
].Radius
+ scale
*rFP
.BoundingRadius
))
1963 pos
.z
= getZFromXY (pos
.x
, pos
.y
);
1964 if (pos
.z
< -90000.0f
)
1967 // Get some Z around to see if we can put the Flora on the ground
1968 uint32 nNbSamples
= 8; // Const to be put somewhere
1969 vector
<CVector
> base
;
1970 base
.resize (nNbSamples
);
1971 for (i
= 0; i
< nNbSamples
; ++i
)
1974 base
[i
].x
+= scale
* rFP
.CollisionRadius
* cosf((2.0f
*(float)Pi
*i
)/(float)nNbSamples
);
1975 base
[i
].y
+= scale
* rFP
.CollisionRadius
* sinf((2.0f
*(float)Pi
*i
)/(float)nNbSamples
);
1976 base
[i
].z
= getZFromXY (base
[i
].x
, base
[i
].y
);
1978 if (fabs(base
[i
].z
-pos
.z
) > 0.8f
)
1985 // ---------------------------------------------------------------------------
1986 void CExport::writeFloraIG (const string
&LandFile
, bool bTestForWriting
)
1990 if (_FloraInsts
.empty())
1993 CZoneRegion zoneRegion
;
1995 if (inFile
.open (LandFile
))
1999 zoneRegion
.serial (xml
);
2005 nlwarning ("Can't open the file %s", LandFile
.c_str());
2010 for (j
= zoneRegion
.getMinY(); j
<= zoneRegion
.getMaxY(); ++j
)
2011 for (i
= zoneRegion
.getMinX(); i
<= zoneRegion
.getMaxX(); ++i
)
2013 if ((zoneRegion
.getName(i
,j
) == STRING_OUT_OF_BOUND
) ||
2014 (zoneRegion
.getName(i
,j
) == STRING_UNUSED
))
2017 vector
<int> vegZone
;
2018 // Take all Flora instances in the zone (i,j)
2019 for (k
= 0; k
< (sint32
)_FloraInsts
.size(); ++k
)
2021 if (((i
*_Options
->CellSize
) < _FloraInsts
[k
].Pos
.x
) && (_FloraInsts
[k
].Pos
.x
< ((i
+1)*_Options
->CellSize
)) &&
2022 ((j
*_Options
->CellSize
) < _FloraInsts
[k
].Pos
.y
) && (_FloraInsts
[k
].Pos
.y
< ((j
+1)*_Options
->CellSize
)))
2024 vegZone
.push_back (k
);
2031 ZoneName
+= NLMISC::toString(-j
) + "_";
2032 ZoneName
+= 'a' + (i
/26);
2033 ZoneName
+= 'a' + (i
%26);
2035 CVector vGlobalPos
= CVector (0.0f
, 0.0f
, 0.0f
);
2036 CInstanceGroup::TInstanceArray Instances
;
2037 vector
<CCluster
> Portals
;
2038 vector
<CPortal
> Clusters
;
2039 Instances
.resize (vegZone
.size());
2041 for (k
= 0; k
< (sint32
)vegZone
.size(); ++k
)
2043 //vGlobalPos += _FloraInsts[vegZone[k]].Pos;
2044 Instances
[k
].Pos
= _FloraInsts
[vegZone
[k
]].Pos
;
2045 Instances
[k
].Rot
= CQuat(CVector::K
, _FloraInsts
[vegZone
[k
]].Rot
);
2046 Instances
[k
].Scale
= CVector(_FloraInsts
[vegZone
[k
]].Scale
, _FloraInsts
[vegZone
[k
]].Scale
, _FloraInsts
[vegZone
[k
]].Scale
);
2047 Instances
[k
].nParent
= -1;
2048 Instances
[k
].Name
= _FloraInsts
[vegZone
[k
]].ShapeName
;
2049 Instances
[k
].InstanceName
= _FloraInsts
[vegZone
[k
]].PlantName
;
2050 /*Instances[k].InstanceName = "Flora_"; // see if it works
2051 Instances[k].InstanceName += ZoneName + "_";
2052 Instances[k].InstanceName += '0' + ((k/1000)%10);
2053 Instances[k].InstanceName += '0' + ((k/100) %10);
2054 Instances[k].InstanceName += '0' + ((k/10) %10);
2055 Instances[k].InstanceName += '0' + ( k %10);*/
2058 // \todo trap -> look why it dont seems to work with a global positionning
2059 //vGlobalPos /= (float)vegZone.size();
2060 //for (k = 0; k < (sint32)vegZone.size(); ++k)
2061 // Instances[k].Pos -= vGlobalPos;
2064 IG
.build (vGlobalPos
, Instances
, Portals
, Clusters
);
2066 ZoneName
= _OutIGDir
+ "\\" + ZoneName
;
2069 CIFile inFile
; // If file already exists and we have selection...
2070 if (bTestForWriting
)
2071 if (inFile
.open(ZoneName
))
2079 COFile
outFile (ZoneName
);
2080 IG
.serial (outFile
);
2081 if (_ExportCB
!= NULL
)
2082 _ExportCB
->dispInfo (ZoneName
+ " generated");
2084 catch (const Exception
&e
)
2086 if (_ExportCB
!= NULL
)
2087 _ExportCB
->dispWarning ("Cant write " + ZoneName
+ " (" + e
.what() + ")");
2092 // ---------------------------------------------------------------------------
2093 void CExport::loadLandscape (const string
&LandFile
)
2095 CZoneRegion zoneRegion
;
2100 if (inFile
.open (LandFile
))
2104 zoneRegion
.serial (xml
);
2110 if (_ExportCB
!= NULL
)
2111 _ExportCB
->dispWarning (string("Can't open file ") + LandFile
);
2114 catch (const Exception
&e
)
2116 if (_ExportCB
!= NULL
)
2117 _ExportCB
->dispWarning (string("Cant load ") + LandFile
+ " : " + e
.what());
2121 sint32 nTotalFile
= (1 + zoneRegion
.getMaxY() - zoneRegion
.getMinY()) * (1 + zoneRegion
.getMaxX() - zoneRegion
.getMinX());
2122 sint32 nCurrentFile
= 0;
2123 for (sint32 j
= zoneRegion
.getMinY(); j
<= zoneRegion
.getMaxY(); ++j
)
2124 for (sint32 i
= zoneRegion
.getMinX(); i
<= zoneRegion
.getMaxX(); ++i
)
2127 if (_ExportCB
!= NULL
)
2128 _ExportCB
->dispPassProgress(((float)nCurrentFile
)/((float)nTotalFile
));
2130 if ((zoneRegion
.getName(i
,j
) == STRING_OUT_OF_BOUND
) ||
2131 (zoneRegion
.getName(i
,j
) == STRING_UNUSED
))
2134 // Generate zone name
2136 string ZoneName
= getZoneNameFromXY (i
, j
);
2138 ZoneName
= _InLandscapeDir
+ string("\\") + ZoneName
;
2140 //if (_ExportCB != NULL)
2141 // _ExportCB->dispInfo (string("Loading ") + ZoneName);
2146 if (!inFile
.open (ZoneName
+ string(".zonew")))
2147 inFile
.open (ZoneName
+ string(".zonel"));
2148 zone
.serial (inFile
);
2150 _Landscape
->addZone (zone
);
2152 catch(const Exception
&/*e*/)
2154 if (_ExportCB
!= NULL
)
2155 _ExportCB
->dispWarning (string("Cant load ") + ZoneName
+ string(".zone(l,w)"));
2157 if ((_ExportCB
!= NULL
) && (_ExportCB
->isCanceled()))
2166 // ---------------------------------------------------------------------------
2167 string
CExport::getZoneNameFromXY (sint32 x
, sint32 y
)
2171 if ((y
>0) || (y
<-255) || (x
<0) || (x
>255))
2173 tmp
= toString(-y
) + "_";
2174 tmp
+= ('A' + (x
/26));
2175 tmp
+= ('A' + (x
%26));
2179 // ---------------------------------------------------------------------------
2180 sint32
CExport::getXFromZoneName (const string
&ZoneName
)
2184 while (ZoneName
[i
] != '_')
2186 yStr
+= ZoneName
[i
]; ++i
;
2187 if (i
== ZoneName
.size())
2191 while (i
< ZoneName
.size())
2193 xStr
+= ZoneName
[i
]; ++i
;
2195 return ((xStr
[0] - 'A')*26 + (xStr
[1] - 'A'));
2198 // ---------------------------------------------------------------------------
2199 sint32
CExport::getYFromZoneName (const string
&ZoneName
)
2203 while (ZoneName
[i
] != '_')
2205 yStr
+= ZoneName
[i
]; ++i
;
2206 if (i
== ZoneName
.size())
2210 while (i
< ZoneName
.size())
2212 xStr
+= ZoneName
[i
]; ++i
;
2214 return -atoi(yStr
.c_str());