1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2010 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
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
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
;
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));
97 class CComputableSurfaceBorder
;
98 class CComputableSurface
;
99 class CPatchTessellation
;
100 class CZoneTessellation
;
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
134 * The support of the surface element.
135 * The index to the 3 vertices of the triangle.
140 * The element normal vector
142 NLMISC::CVector Normal
;
145 * The area of the element
155 * The tessellation vertices
157 std::vector
<NLMISC::CVector
> *Vertices
;
160 /* Here the surface criteria.
161 Probably some normal quantization, material, flags ... */
176 NumNormalQuantas
= 4,
177 NumOrientationQuantas
= 4
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.
193 * The Id of the surface container.
200 * Creates a simple CSurfElement.
211 SurfaceId
= UnaffectedSurfaceId
;
216 ForceInvalid
= false;
217 IsUnderWater
= false;
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.
241 if (EdgeLinks
[i
] != NULL
)
243 if (EdgeLinks
[i
]->EdgeLinks
[j
] == this)
244 EdgeLinks
[i
]->EdgeLinks
[j
] = 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
)
261 f
.serial(Tri
[0], Tri
[1], Tri
[2]);
272 EdgeLinks
[i
] = (s
>= 0 ? &tessellation
[s
] : NULL
);
281 s
= (EdgeLinks
[i
] != NULL
? EdgeLinks
[i
]->ElemId
: -1);
295 * CComputableSurfaceBorder separates geometrically 2 distinct CComputableSurface objects
296 * \author Benjamin Legros
297 * \author Nevrax France
300 class CComputableSurfaceBorder
303 std::vector
<NLMISC::CVector
> Vertices
;
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.
321 /// Smoothes the border (and so reduces the number of vertices).
322 void smooth(float val
);
324 /// Computes the length of the border
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
351 class CComputableSurface
356 /// The Id of the surface
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
;
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
;
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.
397 void floodFill(CSurfElement
*first
, sint32 surfId
, const A
&cmp
, CZoneTessellation
*zoneTessel
)
401 nldebug("flood fill surface %d", surfId
);
404 std::vector
<CSurfElement
*> stack
;
407 stack
.push_back(first
);
408 first
->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;
419 WaterHeight
= IsUnderWater
? PrimChecker
.waterHeight(first
->WaterShape
, tamere
)+WaterThreshold
: 123456.0f
;
422 uint32 currentZoneId
= first
->ZoneId
;
426 while (!stack
.empty())
428 CSurfElement
*pop
= stack
.back();
430 Elements
.push_back(pop
);
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
]);
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();
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
487 class CZoneTessellation
490 std::vector
<CSurfElement
> _Tessellation
;
491 std::vector
<NLMISC::CVector
> _Vertices
;
495 std::vector
<uint16
> _ZoneIds
;
496 std::vector
<const NL3D::CZone
*> _ZonePtrs
;
502 NLMISC::CAABBox MergeBox
;
504 void serial(NLMISC::IStream
&f
) { f
.serial(MergeBox
, MergeId
); }
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
;
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.)
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
;
552 std::vector
<uint8
> VerticesFlags
;
557 * Creates an empty tessellation.
559 CZoneTessellation() {}
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.
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
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;
614 void saveTessellation(NLMISC::COFile
&output
);
619 void loadTessellation(NLMISC::CIFile
&input
);
622 void checkSameLandscapeHmBinds(const NL3D::CLandscape
&landscape
, const NL3D::CLandscape
&landscapeNoHm
);
627 class CSurfElemCompareSimple
631 bool equal(const CSurfElement
*a
, const CSurfElement
*b
) const
633 return a
->IsValid
== b
->IsValid
&&
634 a
->ForceInvalid
== b
->ForceInvalid
;
638 class CSurfElemCompareNormal
642 bool equal(const CSurfElement
*a
, const CSurfElement
*b
) const
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
;
656 #endif // NL_BUILD_SURF_H
658 /* End of build_surf.h */