Fix game:addSpawnShapesByZone
[ryzomcore.git] / nel / tools / pacs / build_rbank / build_surf.h
blob14324fab4472ac72e9a905292ca61cd081d55a23
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) 2010 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 #ifndef NL_BUILD_SURF_H
21 #define NL_BUILD_SURF_H
23 #include <vector>
25 #include "nel/misc/debug.h"
26 #include "nel/misc/file.h"
28 #include "nel/3d/zone.h"
29 #include "nel/3d/patch.h"
30 #include "nel/3d/mesh.h"
31 #include "nel/3d/landscape.h"
33 #include "nel/3d/quad_tree.h"
34 #include "nel/3d/quad_grid.h"
36 #include "nel/misc/vector.h"
37 #include "nel/misc/aabbox.h"
38 #include "nel/misc/geom_ext.h"
39 #include "nel/misc/polygon.h"
41 #include "nel/pacs/surface_quad.h"
42 #include "nel/pacs/retrievable_surface.h"
44 #include "prim_checker.h"
48 extern std::string OutputRootPath;
49 extern std::string OutputDirectory;
50 extern std::string OutputPath;
51 extern std::string TessellationPath;
52 extern std::string IGBoxes;
53 extern uint TessellateLevel;
54 extern bool ReduceSurfaces;
55 extern bool SmoothBorders;
56 extern bool ComputeElevation;
57 extern bool ComputeLevels;
58 extern std::vector<std::string> ZoneNames;
59 extern std::string ZoneExt;
60 extern std::string ZoneNHExt;
61 extern std::string ZoneLookUpPath;
63 extern bool ProcessAllPasses;
64 extern bool CheckPrims;
65 extern bool TessellateZones;
66 extern bool MoulineZones;
67 extern bool TessellateAndMoulineZones;
68 extern bool ProcessRetrievers;
69 extern std::string PreprocessDirectory;
71 extern float WaterThreshold;
73 extern bool UseZoneSquare;
74 extern std::string ZoneUL;
75 extern std::string ZoneDR;
77 extern std::string GlobalRetriever;
78 extern std::string RetrieverBank;
79 extern std::string GlobalUL;
80 extern std::string GlobalDR;
81 extern bool ProcessGlobal;
82 extern bool Verbose;
83 extern bool CheckConsistency;
85 extern CPrimChecker PrimChecker;
87 std::string getZoneNameById(uint16 id);
88 uint16 getZoneIdByName(std::string &name);
89 NLMISC::CAABBox getZoneBBoxById(uint16 id);
90 uint16 getZoneIdByPos(NLMISC::CVector &pos);
91 NL3D::CMesh *generateMeshFromBBox(const NLMISC::CAABBox &bbox, NLMISC::CRGBA color = NLMISC::CRGBA(255, 128, 0));
93 namespace NLPACS
96 class CSurfElement;
97 class CComputableSurfaceBorder;
98 class CComputableSurface;
99 class CPatchTessellation;
100 class CZoneTessellation;
104 /**/
106 const sint32 UnaffectedSurfaceId = -1;
119 * CSurfElement is an element of an iso-criteria surface. It is basically a CTriangle, and
120 * contains the various criteria values such as incline class, landscape material ...
121 * \author Benjamin Legros
122 * \author Nevrax France
123 * \date 2001
125 class CSurfElement
127 public:
131 uint32 ElemId;
134 * The support of the surface element.
135 * The index to the 3 vertices of the triangle.
137 uint32 Tri[3];
140 * The element normal vector
142 NLMISC::CVector Normal;
145 * The area of the element
147 float Area;
150 * The zone id
152 uint16 ZoneId;
155 * The tessellation vertices
157 std::vector<NLMISC::CVector> *Vertices;
160 /* Here the surface criteria.
161 Probably some normal quantization, material, flags ... */
162 uint8 WaterShape;
163 uint8 QuantHeight;
165 uint32 ForceMerge;
167 bool ForceInvalid;
168 bool IsBorder;
169 bool IsValid;
170 bool IsMergable;
171 bool ClusterHint;
172 bool IsUnderWater;
174 enum
176 NumNormalQuantas = 4,
177 NumOrientationQuantas = 4
181 /**
182 * The links to the neighboring elements.
183 * Each edge is related to the opposite vertex in the triangle */
184 CSurfElement *EdgeLinks[3];
187 * A flag for each edge, set if the edge has already been evaluated (in
188 * the surface border computation.
190 bool EdgeFlag[3];
193 * The Id of the surface container.
195 sint32 SurfaceId;
197 public:
199 * Constructor.
200 * Creates a simple CSurfElement.
202 CSurfElement()
204 ElemId = 0;
205 EdgeLinks[0] = NULL;
206 EdgeLinks[1] = NULL;
207 EdgeLinks[2] = NULL;
208 EdgeFlag[0] = false;
209 EdgeFlag[1] = false;
210 EdgeFlag[2] = false;
211 SurfaceId = UnaffectedSurfaceId;
212 IsBorder = false;
213 IsValid = false;
214 IsMergable = true;
215 ClusterHint = false;
216 ForceInvalid = false;
217 IsUnderWater = false;
218 WaterShape = 255;
219 QuantHeight = 0;
220 ForceMerge = 0;
221 ZoneId = 0;
224 /// Computes the bbox of the surface element.
225 NLMISC::CAABBox getBBox() const;
229 * Computes the various criteria values (associated to quantas)
231 void computeQuantas(CZoneTessellation *zoneTessel);
234 * Removes properly all links to the CSurfElement.
236 void removeLinks()
238 uint i, j;
239 for (i=0; i<3; ++i)
241 if (EdgeLinks[i] != NULL)
242 for (j=0; j<3; ++j)
243 if (EdgeLinks[i]->EdgeLinks[j] == this)
244 EdgeLinks[i]->EdgeLinks[j] = NULL;
245 EdgeLinks[i] = NULL;
251 * Get zone Id on edge
253 sint32 getZoneIdOnEdge(uint edge) const
255 return (EdgeLinks[edge] != NULL ? EdgeLinks[edge]->ZoneId : -1);
258 void serial(NLMISC::IStream &f, std::vector<CSurfElement> &tessellation)
260 f.serial(ElemId);
261 f.serial(Tri[0], Tri[1], Tri[2]);
262 f.serial(Normal);
263 f.serial(ZoneId);
265 if (f.isReading())
267 sint32 s;
268 uint i;
269 for (i=0; i<3; ++i)
271 f.serial(s);
272 EdgeLinks[i] = (s >= 0 ? &tessellation[s] : NULL);
275 else
277 sint32 s;
278 uint i;
279 for (i=0; i<3; ++i)
281 s = (EdgeLinks[i] != NULL ? EdgeLinks[i]->ElemId : -1);
282 f.serial(s);
295 * CComputableSurfaceBorder separates geometrically 2 distinct CComputableSurface objects
296 * \author Benjamin Legros
297 * \author Nevrax France
298 * \date 2001
300 class CComputableSurfaceBorder
302 public:
303 std::vector<NLMISC::CVector> Vertices;
305 sint32 Left;
306 sint32 Right;
308 float Length;
310 sint8 Edge;
312 bool DontSmooth;
314 public:
315 /// Constructor.
316 CComputableSurfaceBorder(sint32 left = 0, sint32 right = 0, sint edge=-1) : Left(left), Right(right), Edge(edge), DontSmooth(false) {}
318 /// Dump the vertices that constitue the border.
319 void dump();
321 /// Smoothes the border (and so reduces the number of vertices).
322 void smooth(float val);
324 /// Computes the length of the border
325 void computeLength()
327 sint n;
328 Length = 0.0;
329 for (n=0; n<(sint)Vertices.size()-1; ++n)
331 Length += (Vertices[n+1]-Vertices[n]).norm();
346 * CComputableSurface is a compact connex set of CSurfElement.
347 * \author Benjamin Legros
348 * \author Nevrax France
349 * \date 2001
351 class CComputableSurface
353 public:
355 public:
356 /// The Id of the surface
357 sint32 SurfaceId;
359 /// The references on the elements that belong to the surface
360 std::vector<CSurfElement *> Elements;
362 /// The object that stores all the borders used in the computed area
363 std::vector<CComputableSurfaceBorder> *BorderKeeper;
365 /// The border in the surface, by id
366 std::vector<uint16> BorderIds;
368 bool IsUnderWater;
369 bool ClusterHint;
371 float Area;
372 float WaterHeight;
373 uint8 QuantHeight;
375 /// The BBox of the whole zone (in which the surface should be contained.)
376 NLMISC::CAABBox BBox;
378 /// The height storage quad tree
379 CSurfaceQuadTree HeightQuad;
381 /// The center of the surface
382 NLMISC::CVector Center;
384 public:
386 * Constructor.
387 * Builds an empty surface.
389 CComputableSurface() : SurfaceId(UnaffectedSurfaceId), BorderKeeper(NULL), ClusterHint(false) {}
392 * Flood fills the surface elements to find iso-criteria surfaces.
393 * Every linked surface element which has the same quantas values and a surfaceid == -1
394 * are marked and recursively called.
396 template<class A>
397 void floodFill(CSurfElement *first, sint32 surfId, const A &cmp, CZoneTessellation *zoneTessel)
399 if (Verbose)
401 nldebug("flood fill surface %d", surfId);
404 std::vector<CSurfElement *> stack;
405 sint i;
407 stack.push_back(first);
408 first->SurfaceId = surfId;
410 SurfaceId = surfId;
411 ClusterHint = first->ClusterHint;
412 QuantHeight = first->QuantHeight;
413 uint waterShape = first->WaterShape;
415 IsUnderWater = first->IsUnderWater;
417 //WaterHeight = IsUnderWater ? zoneTessel->WaterShapes[first->WaterShape].Vertices[0].z : 123456.0f;
418 bool tamere;
419 WaterHeight = IsUnderWater ? PrimChecker.waterHeight(first->WaterShape, tamere)+WaterThreshold : 123456.0f;
422 uint32 currentZoneId = first->ZoneId;
424 Area = 0.0;
426 while (!stack.empty())
428 CSurfElement *pop = stack.back();
429 stack.pop_back();
430 Elements.push_back(pop);
431 Area += pop->Area;
433 for (i=0; i<3; ++i)
435 if (pop->EdgeLinks[i] != NULL && pop->EdgeLinks[i]->SurfaceId == UnaffectedSurfaceId && cmp.equal(first, pop->EdgeLinks[i]))
437 pop->EdgeLinks[i]->SurfaceId = SurfaceId;
438 stack.push_back(pop->EdgeLinks[i]);
443 if (Verbose)
445 nldebug("%d elements added", Elements.size());
448 Center = NLMISC::CVector::Null;
449 for (i=0; i<(sint)Elements.size(); ++i)
451 std::vector<NLMISC::CVector> &vertices = *Elements[i]->Vertices;
452 Center += (vertices[Elements[i]->Tri[0]]+vertices[Elements[i]->Tri[1]]+vertices[Elements[i]->Tri[2]]);
454 Center /= (float)(Elements.size()*3);
458 /// Builds the border of the CComputableSurface.
459 void buildBorders(CZoneTessellation *zoneTessel);
461 /// Check Surface Consistency
462 bool checkConsistency();
464 private:
465 void followBorder(CZoneTessellation *zoneTessel, CSurfElement *first, uint edge, uint sens, std::vector<NLMISC::CVector> &vstore, bool &loop);
482 * CZoneTessellation is the whole tessellation of a given CZone.
483 * \author Benjamin Legros
484 * \author Nevrax France
485 * \date 2001
487 class CZoneTessellation
489 private:
490 std::vector<CSurfElement> _Tessellation;
491 std::vector<NLMISC::CVector> _Vertices;
493 protected:
495 std::vector<uint16> _ZoneIds;
496 std::vector<const NL3D::CZone*> _ZonePtrs;
498 public:
499 class CMergeForceBox
501 public:
502 NLMISC::CAABBox MergeBox;
503 uint32 MergeId;
504 void serial(NLMISC::IStream &f) { f.serial(MergeBox, MergeId); }
507 public:
508 /// The zone valid tessellation elements.
509 std::vector<CSurfElement *> Elements;
512 NLMISC::CAABBox BBox;
513 NLMISC::CAABBox OriginalBBox;
514 NLMISC::CAABBox BestFittingBBox;
515 // Yoyo: if zone is empty, we must not apply the Translation delta to zone
516 bool BestFittingBBoxSetuped;
519 NLMISC::CVector Translation;
522 sint32 CentralZoneId;
524 std::vector<NLMISC::CPolygon> WaterShapes;
525 NL3D::CQuadGrid<uint32> WaterGrid;
527 /**
528 * The tessellation refinement. The size of the tessellation is equal to 2m/Refinement
529 * (say, for instance, a refinement of 2 means a 1m large tessellation.)
531 sint16 Refinement;
534 * The surfaces composing the tessellation.
536 std::vector<CComputableSurface> Surfaces;
537 std::vector<CComputableSurface> ExtSurfaces;
540 * The borders for the whole CZone.
542 std::vector<CComputableSurfaceBorder> Borders;
545 * The box that force merge into surface
547 std::vector<CMergeForceBox> ForceMerge;
550 * Flags
552 std::vector<uint8> VerticesFlags;
554 public:
556 * Constructor
557 * Creates an empty tessellation.
559 CZoneTessellation() {}
562 * Clear
564 void clear();
567 * Sets a zone tessellation up for building later.
569 bool setup(uint16 zoneId, sint16 refinement, const NLMISC::CVector &translation);
572 * Adds a zone light tessellation to the quad tree container.
574 void addToContainer(const NL3D::CZone &zone);
575 NL3D::CMesh *generateCollisionMesh();
578 * Builds the whole zone tessellation (with linkage) from the given zone.
580 void build();
583 * Sets the water polygons up.
585 void addWaterShape(const NLMISC::CPolygon &poly)
587 WaterShapes.push_back(poly);
591 * Compile the whole zone tessellation and creates surfaces
593 void compile();
596 * Generates a CMesh from the tessellation.
598 NL3D::CMesh *generateMesh();
601 * Generates borders for the whole zone tessellation.
602 * \param smooth how much to smooth the borders
604 void generateBorders(float smooth);
609 NLMISC::CAABBox computeBBox() const;
612 * Save tessellation
614 void saveTessellation(NLMISC::COFile &output);
617 * Load tessellation
619 void loadTessellation(NLMISC::CIFile &input);
621 private:
622 void checkSameLandscapeHmBinds(const NL3D::CLandscape &landscape, const NL3D::CLandscape &landscapeNoHm);
627 class CSurfElemCompareSimple
629 public:
631 bool equal(const CSurfElement *a, const CSurfElement *b) const
633 return a->IsValid == b->IsValid &&
634 a->ForceInvalid == b->ForceInvalid;
638 class CSurfElemCompareNormal
640 public:
642 bool equal(const CSurfElement *a, const CSurfElement *b) const
644 return b->IsValid &&
645 a->ClusterHint == b->ClusterHint &&
646 a->ZoneId == b->ZoneId &&
647 a->IsUnderWater == b->IsUnderWater &&
648 a->WaterShape == b->WaterShape &&
649 a->QuantHeight == b->QuantHeight;
654 }; // NLPACS
656 #endif // NL_BUILD_SURF_H
658 /* End of build_surf.h */