Fix game:addSpawnShapesByZone
[ryzomcore.git] / nel / tools / 3d / zone_welder / zone_welder.cpp
blobe33dd6862f7263f228436971b469832592f3041a
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) 2019 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/>.
21 #include "../zone_lib/zone_utility.h"
23 #include <iostream>
24 #include <sstream>
25 #include <vector>
26 #include <set>
28 #include "nel/misc/types_nl.h"
29 #include "nel/misc/file.h"
30 #include "nel/misc/common.h"
31 #include "nel/3d/quad_tree.h"
32 #include "nel/3d/zone.h"
33 #include "nel/3d/landscape.h"
34 #include "nel/3d/zone_smoother.h"
35 #include "nel/3d/zone_tgt_smoother.h"
36 #include "nel/3d/zone_corner_smoother.h"
39 using namespace NL3D;
40 using namespace NLMISC;
41 using namespace std;
44 #define WELD_LOG 1
46 FILE *fdbg;
48 std::string inputDir;
49 std::string inputExt;
50 std::string outputDir;
51 std::string outputExt;
53 float weldRadius = 1.1f;
55 /* Zone ID
56 0 1 2
57 3 4
58 5 6 7
61 // Define this to stop the welder on a source edge
62 // #define NL_DEBUG_WELD
63 #define NL_DEBUG_WELD_V0 (CVector(16320,-24064,0))
64 #define NL_DEBUG_WELD_V1 (CVector(16352,-24065,0))
65 #define NL_DEBUG_WELD_THRESHOLD 1.f
67 #ifdef NL_DEBUG_WELD
68 bool isTheSame (const CVector &v0, const CVector &v1)
70 CVector delta = v0 - v1;
71 delta.z = 0;
72 return delta.norm() < NL_DEBUG_WELD_THRESHOLD;
74 #endif // NL_DEBUG_WELD
76 /**
77 * CWeldableVertexInfos
79 struct CWeldableVertexInfos
81 uint16 IndexInZone; // base vertex
82 sint PatchIndex; // patch
83 uint8 PatchVertex; // 0,1,2,3
85 CWeldableVertexInfos()
87 IndexInZone = 0;
88 PatchIndex = 0;
89 PatchVertex = 0;
92 bool operator< (const CWeldableVertexInfos& wvinf) const
94 if(IndexInZone<wvinf.IndexInZone)
95 return true;
96 if(IndexInZone>wvinf.IndexInZone)
97 return false;
98 if(PatchIndex<wvinf.PatchIndex)
99 return true;
100 if(PatchIndex>wvinf.PatchIndex)
101 return false;
102 return PatchVertex<wvinf.PatchVertex;
107 struct CVectorInfluence
109 CVector Vertex;
110 float Inf;
111 bool OnBorder;
115 struct CAdjacentVertex
117 CVector Vertex;
118 uint IdOnCenterZone;
119 bool OnBorder;
123 /*******************************************************************\
124 writeInstructions()
125 \*******************************************************************/
126 void writeInstructions()
128 printf("zone_welder <input.zone><output.zone>[<weld threshold>]\n");
129 printf("\t/? for this help\n");
133 /*******************************************************************\
134 findPatchIndex()
135 \*******************************************************************/
136 bool getPatchAndEdge(const std::vector<CPatchInfo>& patchs,
137 uint16 baseVertex1, uint16 baseVertex2,
138 uint16& patchIndex,
139 uint8& edgeIndex)
141 uint ptch;
143 for(ptch=0; ptch<patchs.size(); ptch++)
145 uint i;
146 for(i=0; i<4; i++)
148 if(patchs[ptch].BaseVertices[i] == baseVertex1)
150 #if WELD_LOG
151 fprintf(fdbg,"patch %d continent bv %d : %d %d %d %d\n",
152 ptch,
153 baseVertex1,
154 patchs[ptch].BaseVertices[0],
155 patchs[ptch].BaseVertices[1],
156 patchs[ptch].BaseVertices[2],
157 patchs[ptch].BaseVertices[3]);
158 #endif
160 if(patchs[ptch].BaseVertices[(i+1)%4] == baseVertex2)
162 edgeIndex = i;
163 patchIndex = ptch;
164 return true;
166 if(patchs[ptch].BaseVertices[(i-1)%4] == baseVertex2)
168 edgeIndex = (i-1)%4;
169 patchIndex = ptch;
170 return true;
175 return false;
178 void CleanZone ( std::vector<CPatchInfo> &zoneInfos, uint zoneId, const CAABBoxExt &zoneBBox, float weldThreshold);
180 /*******************************************************************\
181 weldZones()
182 \*******************************************************************/
183 void weldZones(const char *center)
185 uint i,j;
187 // load zone in the center
188 CIFile zoneFile(inputDir+center+inputExt);
189 CZone zone;
190 zone.serial(zoneFile);
191 zoneFile.close();
193 // retrieving infos from the center zone
194 uint16 centerZoneId = zone.getZoneId();
195 std::vector<CPatchInfo> centerZonePatchs;
196 std::vector<CBorderVertex> centerZoneBorderVertices;
197 zone.retrieve(centerZonePatchs, centerZoneBorderVertices);
199 std::vector<CPatchInfo>::iterator itptch;
200 std::vector<CBorderVertex>::iterator itbv;
202 // if no id yet, we add a correct id
203 if(centerZoneId==0)
205 centerZoneId = createZoneId(center);
207 // edge neighbour : current zone
208 for(itptch = centerZonePatchs.begin(); itptch!=centerZonePatchs.end(); itptch++)
210 for(j=0; j<4; j++)
212 (*itptch).BindEdges[j].ZoneId = centerZoneId;
216 // border vertices neighbour : current zone
217 for(itbv = centerZoneBorderVertices.begin(); itbv<centerZoneBorderVertices.end(); itbv++)
219 (*itbv).NeighborZoneId = centerZoneId;
223 #if WELD_LOG
224 fprintf(fdbg,"id(center) = %d\n",centerZoneId);
225 #endif
227 // *** Clean internal zone
228 // * Bind 1-1 1-2 1-4 internal patches that are not binded
229 // * Make a global welded on vertices
230 // * Force tangents position
231 CleanZone ( centerZonePatchs, centerZoneId, zone.getZoneBB(), weldRadius);
233 // Yoyo was here: Smooth the tangents of the zone.
234 //================================================
235 // NB: do it only for edges sharing 2 patchs of centerZone. (don't care adjacent zones).
236 // smoothing with adjacent zones is done with a better smoothing tool: CZoneTgtSmoother, see below,
237 // after the weld of the zone.
239 CZoneSmoother zonesmoother;
240 CZoneSmoother::CZoneInfo smoothZones[5];
241 smoothZones[0].ZoneId= centerZoneId;
242 smoothZones[0].Patchs= &centerZonePatchs;
243 // 30deg ???
244 zonesmoother.smoothTangents(smoothZones, (float)(Pi/6));
249 // load 8 adjacent adjZones
250 bool adjZoneFileFound[8];
251 CZone adjZones[8];
252 CZoneInfo adjZoneInfos[8];
253 uint16 adjZonesId[8];
254 std::vector<std::string> adjZonesName;
255 getAdjacentZonesName(center, adjZonesName);
256 for(i=0; i<8; i++)
258 if(adjZonesName[i]=="empty") continue;
260 adjZoneFileFound[i] = true;
261 CIFile f;
264 std::string ss(outputDir+adjZonesName[i]+outputExt);
265 if (f.open(ss))
267 printf("reading file %s\n", ss.c_str());
268 adjZones[i].serial(f);
269 adjZones[i].retrieve(adjZoneInfos[i].Patchs, adjZoneInfos[i].BorderVertices);
270 adjZoneInfos[i].ZoneId= adjZonesId[i] = adjZones[i].getZoneId();
271 f.close();
273 else
275 // nlwarning ("WARNING File not found: %s\n", ss.c_str());
276 adjZonesName[i]="empty";
279 catch(const exception &e)
281 nlwarning ("ERROR %s\n", e.what ());
282 adjZoneFileFound[i] = false;
286 // QuadTree for storing adjZones points
287 CQuadTree<CWeldableVertexInfos> quadTrees[8];
289 // new base, to change from XZ to XY (Nel speaking)
290 CMatrix base;
291 CVector I(1,0,0);
292 CVector J(0,0,-1);
293 CVector K(0,1,0);
294 base.setRot(I,J,K, true);
298 uint ptch;
300 uint16 weldCount = 0;
302 // Error messages
303 vector<string> errorMessage;
305 for(i=0; i<8; i++)
307 if(adjZonesName[i]=="empty") continue;
308 if(!adjZoneFileFound[i]) continue;
310 // setting quad tree
311 uint qTreeDepth = 5;
312 CAABBoxExt bb = adjZones[i].getZoneBB();
313 quadTrees[i].create (5, bb.getCenter(), 2*bb.getRadius());
314 quadTrees[i].changeBase(base);
316 // retrieving infos from the current adjacent zone
317 std::vector<CPatchInfo> &adjZonePatchs= adjZoneInfos[i].Patchs;
318 std::vector<CBorderVertex> &adjZoneBorderVertices= adjZoneInfos[i].BorderVertices;
321 // if no id yet, we add a correct id
322 nlassert(adjZonesId[i]!=0);
323 if(adjZonesId[i]==0)
325 adjZonesId[i] = createZoneId(getName (adjZonesName[i]));
326 adjZoneInfos[i].ZoneId= adjZonesId[i];
328 // edge neighbour : current zone
329 for(itptch = adjZonePatchs.begin(); itptch!=adjZonePatchs.end(); itptch++)
331 for(j=0; j<4; j++)
333 (*itptch).BindEdges[j].ZoneId = adjZonesId[i];
337 // border vertices neighbour : current zone
338 for(itbv = adjZoneBorderVertices.begin(); itbv!=adjZoneBorderVertices.end(); itbv++)
340 (*itbv).NeighborZoneId = adjZonesId[i];
344 #if WELD_LOG
345 fprintf(fdbg,"------------------------------------------\n");
346 fprintf(fdbg,"id(%d) = %d\n",i,adjZonesId[i]);
347 #endif
349 // an edge of current adjacent patch with neighbour zoneId==center zoneId is
350 // set to no neighbour.
351 for(ptch = 0; ptch<adjZonePatchs.size(); ptch++)
353 for(j=0; j<4; j++)
355 if(adjZonePatchs[ptch].BindEdges[j].ZoneId == centerZoneId)
357 adjZonePatchs[ptch].BindEdges[j].NPatchs = 0;
362 fprintf(fdbg,"(before) zone %u bordervertices size : %u\n",i,(uint)adjZoneBorderVertices.size());
364 // delete border vertices of the adjacent zone if their neighbour zoneId
365 // is equal to current zone zoneId
366 std::vector<CBorderVertex>::iterator itborder = adjZoneBorderVertices.begin();
367 while(itborder != adjZoneBorderVertices.end())
369 if((*itborder).NeighborZoneId == centerZoneId)
371 itborder = adjZoneBorderVertices.erase(itborder);
373 else
374 itborder++;
376 fprintf(fdbg,"(after) zone %u bordervertices size : %u\n",i,(uint)adjZoneBorderVertices.size());
378 // A set for storing base vertex index already added in the quad tree
379 std::set<uint16> adjBaseVertexIndexSet;
381 // if point in adjacent zone is not in the set :
382 // -> add it in the set
383 // -> add it in the quad
384 for(ptch = 0; ptch<adjZonePatchs.size(); ptch++)
386 for(j=0; j<4; j++)
388 CWeldableVertexInfos wvinf;
389 wvinf.IndexInZone = adjZonePatchs[ptch].BaseVertices[j]; // useful ????
390 wvinf.PatchIndex = ptch;
391 wvinf.PatchVertex = j;
392 if(adjBaseVertexIndexSet.find(wvinf.IndexInZone) == adjBaseVertexIndexSet.end())
394 adjBaseVertexIndexSet.insert(wvinf.IndexInZone);
395 CVector bboxmin;
396 CVector bboxmax;
397 bboxmin.x = adjZonePatchs[ptch].Patch.Vertices[j].x;
398 bboxmin.y = adjZonePatchs[ptch].Patch.Vertices[j].y;
399 bboxmin.z = adjZonePatchs[ptch].Patch.Vertices[j].z;
400 bboxmax = bboxmin;
401 quadTrees[i].insert(bboxmin,bboxmax,wvinf);
406 quadTrees[i].clearSelection();
409 float bboxRadius = 10; //TEMP !!
411 std::set<uint16> centerBaseVertexIndexSet;
412 std::set<uint16> currentAdjBaseVertexIndexSet;
414 for(ptch=0; ptch<centerZonePatchs.size(); ptch++) // for all patchs in center zone
416 // stores infos for edge part
417 CWeldableVertexInfos nearVertexInfos[4];
419 bool toWeld[4];
421 CVector bboxmin;
422 CVector bboxmax;
425 // for every points in center patch we look for close points in adjacent patch
426 for(j=0; j<4; j++) // 4 patch vertices (in center zone)
428 toWeld[j] = false;
431 // already 'checked for welding' vertices are stored in a set
432 centerBaseVertexIndexSet.insert(centerZonePatchs[ptch].BaseVertices[j]);
434 //fprintf(fdbg,"%d - %d) CZBV(%d)\n",i,baseVertexIndexSet.size(),centerZonePatchs[ptch].BaseVertices[j]);
436 bboxmin.x = centerZonePatchs[ptch].Patch.Vertices[j].x - bboxRadius;
437 bboxmin.y = centerZonePatchs[ptch].Patch.Vertices[j].y - bboxRadius;
438 bboxmin.z = centerZonePatchs[ptch].Patch.Vertices[j].z - bboxRadius;
440 bboxmax.x = centerZonePatchs[ptch].Patch.Vertices[j].x + bboxRadius;
441 bboxmax.y = centerZonePatchs[ptch].Patch.Vertices[j].y + bboxRadius;
442 bboxmax.z = centerZonePatchs[ptch].Patch.Vertices[j].z + bboxRadius;
444 //quadTrees[i].select(bboxmin,bboxmax);
445 quadTrees[i].selectAll(); // TEMP !!!
447 // current vertex coordinates in center zone
448 CVector vctr;
449 vctr.x = centerZonePatchs[ptch].Patch.Vertices[j].x;
450 vctr.y = centerZonePatchs[ptch].Patch.Vertices[j].y;
451 vctr.z = centerZonePatchs[ptch].Patch.Vertices[j].z;
453 CWeldableVertexInfos wvinf;
454 float minDistance = weldRadius + 1; // rq: we weld only if we found a distance
455 // inferior to weldRadius
457 CQuadTree<CWeldableVertexInfos>::CIterator itqdt = quadTrees[i].begin();
458 // for all points near of current vertex in adjacent zone..
459 while (itqdt != quadTrees[i].end())
461 CVector vadj;
462 vadj.x = adjZonePatchs[(*itqdt).PatchIndex].Patch.Vertices[(*itqdt).PatchVertex].x;
463 vadj.y = adjZonePatchs[(*itqdt).PatchIndex].Patch.Vertices[(*itqdt).PatchVertex].y;
464 vadj.z = adjZonePatchs[(*itqdt).PatchIndex].Patch.Vertices[(*itqdt).PatchVertex].z;
466 CVector adjToCenter;
467 adjToCenter.x = vctr.x - vadj.x;
468 adjToCenter.y = vctr.y - vadj.y;
469 adjToCenter.z = vctr.z - vadj.z;
470 float dist = adjToCenter.norm();
472 // if dist min we keep infos on this vertex(adj zone)
473 // we keep the closest.
474 if(dist<weldRadius && dist<minDistance)
476 #ifdef NL_DEBUG_WELD
477 nlverify (!isTheSame (centerZonePatchs[ptch].Patch.Vertices[j], NL_DEBUG_WELD_V0));
478 nlverify (!isTheSame (centerZonePatchs[ptch].Patch.Vertices[j], NL_DEBUG_WELD_V1));
479 #endif // NL_DEBUG_WELD
480 minDistance = dist;
481 wvinf = (*itqdt);
483 itqdt++;
486 quadTrees[i].clearSelection();
488 if(minDistance<weldRadius) // i.e if we have found 2 vertices to weld
490 // we save CBorderVertex info, and add it into the adjacent zone
491 CBorderVertex adjBorderV;
492 adjBorderV.CurrentVertex = wvinf.IndexInZone;
493 adjBorderV.NeighborZoneId = centerZoneId;
494 adjBorderV.NeighborVertex = centerZonePatchs[ptch].BaseVertices[j];
495 nearVertexInfos[j] = wvinf;
497 // we save CBorderVertex info, and add it into the center zone
498 CBorderVertex centerBorderV;
499 centerBorderV.CurrentVertex = centerZonePatchs[ptch].BaseVertices[j];
500 centerBorderV.NeighborZoneId = adjZonesId[i];
501 centerBorderV.NeighborVertex = wvinf.IndexInZone;
503 toWeld[j] = true;
505 if(centerBaseVertexIndexSet.find(centerZonePatchs[ptch].BaseVertices[j]) != centerBaseVertexIndexSet.end())
507 if(currentAdjBaseVertexIndexSet.find(wvinf.IndexInZone) == currentAdjBaseVertexIndexSet.end())
509 currentAdjBaseVertexIndexSet.insert(wvinf.IndexInZone);
510 adjZoneBorderVertices.push_back(adjBorderV);
511 centerZoneBorderVertices.push_back(centerBorderV);
513 weldCount++;
514 #if WELD_LOG
515 fprintf(fdbg,"%d) weld vertices : zone%d.(patch%d.vertex%d).baseVertex%d to centerZone.(patch%d.vertex%d).baseVertex%d\n",
516 weldCount,i,wvinf.PatchIndex,wvinf.PatchVertex,wvinf.IndexInZone,ptch,j,centerZonePatchs[ptch].BaseVertices[j]);
517 #endif
525 // then we bind edges (made of weldable vertices) and modify tangents
527 for(j=0; j<4; j++)
529 #ifdef NL_DEBUG_WELD
530 if (
531 (isTheSame (centerZonePatchs[ptch].Patch.Vertices[j], NL_DEBUG_WELD_V0) ||
532 isTheSame (centerZonePatchs[ptch].Patch.Vertices[(j+1)%4], NL_DEBUG_WELD_V0) ) &&
533 (isTheSame (centerZonePatchs[ptch].Patch.Vertices[j], NL_DEBUG_WELD_V1) ||
534 isTheSame (centerZonePatchs[ptch].Patch.Vertices[(j+1)%4], NL_DEBUG_WELD_V1) )
536 nlstop;
537 #endif // NL_DEBUG_WELD
538 // if vertex has been welded...
539 if(toWeld[j] == false) continue;
540 // ...we look if next vertex(i.e if the edge) in center zone has to be welded
541 if(toWeld[(j+1)%4] == false) continue;
543 // We know the two adjacent base vertices
544 // we look for the adjacent patch and the edge containing these vertices
545 uint8 edgeIndex;
546 uint16 patchIndex;
547 if(! getPatchAndEdge(adjZonePatchs,
548 nearVertexInfos[j].IndexInZone,
549 nearVertexInfos[(j+1)%4].IndexInZone,
550 patchIndex,
551 edgeIndex))
553 #if WELD_LOG
554 fprintf(fdbg,"* Error * : Can't find patch containing the following edge : %d - %d\n",
555 nearVertexInfos[j].IndexInZone,
556 nearVertexInfos[(j+1)%4].IndexInZone);
557 #endif
558 nlwarning ("ERROR : zone_welder : Can't find patch containing the following edge : %d - %d\n",
559 nearVertexInfos[j].IndexInZone,
560 nearVertexInfos[(j+1)%4].IndexInZone);
561 continue;
564 #if WELD_LOG
565 fprintf(fdbg,"weld edges : zone%d.patch%d.edge%d(%d-%d) to centerZone.patch%d.edge%d(%d-%d)\n",
567 patchIndex,
568 edgeIndex,
569 nearVertexInfos[j].IndexInZone,
570 nearVertexInfos[(j+1)%4].IndexInZone,
571 ptch,
573 centerZonePatchs[ptch].BaseVertices[j],
574 centerZonePatchs[ptch].BaseVertices[(j+1)%4] );
575 fprintf(fdbg,"center patch %d : %d %d %d %d\n\n",
576 ptch,
577 centerZonePatchs[ptch].BaseVertices[0],
578 centerZonePatchs[ptch].BaseVertices[1],
579 centerZonePatchs[ptch].BaseVertices[2],
580 centerZonePatchs[ptch].BaseVertices[3]);
581 #endif
583 // Check the edge find is not binded
584 if (adjZonePatchs[patchIndex].BindEdges[edgeIndex].NPatchs!=0)
586 // Build an error message
587 char buf[2048];
588 stringstream sserror;
590 // Zone name
591 string nameCenter, nameAdj;
592 getZoneNameByCoord (centerZoneId&0xff, (centerZoneId>>8)+1, nameCenter);
593 getZoneNameByCoord (adjZonesId[i]&0xff, (adjZonesId[i]>>8)+1, nameAdj);
595 // Main message
596 smprintf(buf, 2048,
597 "Bind Error: try to bind the patch n %d in zone n %s with patch n %d in zone %s\n"
598 "This patch is already binded with the following patches : ", ptch+1, nameAdj.c_str(),
599 patchIndex+1, nameCenter.c_str() );
600 sserror << buf;
602 // Sub message
603 for (uint i=0; i<adjZonePatchs[patchIndex].BindEdges[edgeIndex].NPatchs; i++)
605 // Last patch ?
606 bool last=(i==(uint)(adjZonePatchs[patchIndex].BindEdges[edgeIndex].NPatchs-1));
608 // Sub message
609 smprintf(buf, 2048,
610 "patch n %d%s", adjZonePatchs[patchIndex].BindEdges[edgeIndex].Next[i]+1, last?"\n":",");
612 // Concat the message
613 sserror << buf;
616 // Add an error message
617 errorMessage.push_back(sserror.str());
619 else
621 #ifdef NL_DEBUG_WELD
622 if (
623 (isTheSame (centerZonePatchs[ptch].Patch.Vertices[j], NL_DEBUG_WELD_V0) ||
624 isTheSame (centerZonePatchs[ptch].Patch.Vertices[(j+1)%4], NL_DEBUG_WELD_V0) ) &&
625 (isTheSame (centerZonePatchs[ptch].Patch.Vertices[j], NL_DEBUG_WELD_V1) ||
626 isTheSame (centerZonePatchs[ptch].Patch.Vertices[(j+1)%4], NL_DEBUG_WELD_V1) )
628 nlstop;
629 #endif // NL_DEBUG_WELD
630 centerZonePatchs[ptch].BindEdges[j].NPatchs = 1;
631 centerZonePatchs[ptch].BindEdges[j].ZoneId = adjZonesId[i];
632 centerZonePatchs[ptch].BindEdges[j].Next[0] = patchIndex;
633 centerZonePatchs[ptch].BindEdges[j].Edge[0] = edgeIndex;
635 // adjacent zone edge
636 adjZonePatchs[patchIndex].BindEdges[edgeIndex].NPatchs = 1;
637 adjZonePatchs[patchIndex].BindEdges[edgeIndex].ZoneId = centerZoneId;
638 adjZonePatchs[patchIndex].BindEdges[edgeIndex].Next[0] = ptch;
639 adjZonePatchs[patchIndex].BindEdges[edgeIndex].Edge[0] = j;
641 // force the same smooth flag
642 bool smoothFlag = centerZonePatchs[ptch].getSmoothFlag (j);
643 smoothFlag &= adjZonePatchs[patchIndex].getSmoothFlag (edgeIndex);
644 centerZonePatchs[ptch].setSmoothFlag (j, smoothFlag);
645 adjZonePatchs[patchIndex].setSmoothFlag (edgeIndex, smoothFlag);
647 // tangent become the mean or both tangents (adj and center)
648 // Here we cross the mean because adjacent edges are counter-oriented
649 // due to the patchs constant orientation.
650 CVector middle0= (centerZonePatchs[ptch].Patch.Tangents[2*j]+
651 adjZonePatchs[patchIndex].Patch.Tangents[2*edgeIndex+1])/2;
652 CVector middle1= (centerZonePatchs[ptch].Patch.Tangents[2*j+1]+
653 adjZonePatchs[patchIndex].Patch.Tangents[2*edgeIndex])/2;
655 centerZonePatchs[ptch].Patch.Tangents[2*j] =
656 adjZonePatchs[patchIndex].Patch.Tangents[2*edgeIndex+1] = middle0;
658 centerZonePatchs[ptch].Patch.Tangents[2*j+1] =
659 adjZonePatchs[patchIndex].Patch.Tangents[2*edgeIndex] = middle1;
668 // Yoyo: compute the mean on vertices beetween zones.
669 //====================================
670 // do it before "make coplanar beetween zones", because CZoneTgtSmoother use tangents and vertices to smooth.
672 // build all input vertices for center and adjacents zones
673 //------------------
675 // For center zone rebuild vertices.
676 vector<CVector> centerVertices;
677 // for all patch, fill the array of vertices.
678 for(ptch=0; ptch<centerZonePatchs.size(); ptch++)
680 CPatchInfo &pa= centerZonePatchs[ptch];
681 for(uint corner= 0; corner<4; corner++)
683 uint idVert= pa.BaseVertices[corner];
685 // write this vertex in array.
686 centerVertices.resize( max((uint)centerVertices.size(), idVert+1) );
687 centerVertices[idVert]= pa.Patch.Vertices[corner];
691 // For all adjacent zone rebuild vertices.
692 map<uint16, vector<CAdjacentVertex> > adjVertices;
693 for(i=0;i<8;i++)
695 if(adjZonesName[i]=="empty") continue;
696 if(!adjZoneFileFound[i]) continue;
698 // create the entry in the map.
699 vector<CAdjacentVertex> &verts= adjVertices[adjZonesId[i]];
701 // for all patch, fill the array of vertices.
702 std::vector<CPatchInfo> &adjZonePatchs= adjZoneInfos[i].Patchs;
703 for(ptch=0; ptch<adjZonePatchs.size(); ptch++)
705 CPatchInfo &pa= adjZonePatchs[ptch];
706 for(uint corner= 0; corner<4; corner++)
708 uint idVert= pa.BaseVertices[corner];
710 // write this vertex in array.
711 verts.resize( max((uint)verts.size(), idVert+1) );
712 verts[idVert].Vertex= pa.Patch.Vertices[corner];
713 verts[idVert].OnBorder= false;
717 // for all borderVertices with centerZoneId, fill verts neighbor info.
718 std::vector<CBorderVertex> &adjZoneBorderVertices= adjZoneInfos[i].BorderVertices;
719 uint bv;
720 for(bv=0; bv<adjZoneBorderVertices.size(); bv++)
722 CBorderVertex &adjBV= adjZoneBorderVertices[bv];
723 if(adjBV.NeighborZoneId == centerZoneId)
725 verts[adjBV.CurrentVertex].OnBorder= true;
726 verts[adjBV.CurrentVertex].IdOnCenterZone= adjBV.NeighborVertex;
732 // compute the mean on border vertices
733 //------------------
736 // create / reset the result vertices.
737 vector<CVectorInfluence> outVertices;
738 outVertices.resize(centerVertices.size());
739 for(i=0; i<outVertices.size(); i++)
741 outVertices[i].Vertex= centerVertices[i];
742 outVertices[i].Inf= 1;
743 outVertices[i].OnBorder= false;
747 // For all borderVertices of centerZone, choose the good vertex, add neighbor influence
748 uint bv;
749 for(bv=0; bv<centerZoneBorderVertices.size(); bv++)
751 CBorderVertex &centerBV= centerZoneBorderVertices[bv];
752 uint centerVert= centerBV.CurrentVertex;
753 if( adjVertices.find(centerBV.NeighborZoneId) != adjVertices.end() )
755 outVertices[centerVert].Vertex+= adjVertices[centerBV.NeighborZoneId][centerBV.NeighborVertex].Vertex;
756 outVertices[centerVert].Inf++;
757 outVertices[centerVert].OnBorder= true;
760 // normalize influence.
761 for(i=0; i<outVertices.size(); i++)
763 if(outVertices[i].Inf!=1)
765 outVertices[i].Vertex/= outVertices[i].Inf;
766 outVertices[i].Inf= 1;
771 // for all zones, get the new vertices.
772 //------------------
774 // For center zone, for all patchs, copy from outVertices.
775 for(ptch=0; ptch<centerZonePatchs.size(); ptch++)
777 CPatchInfo &pa= centerZonePatchs[ptch];
778 for(uint corner= 0; corner<4; corner++)
780 uint idVert= pa.BaseVertices[corner];
782 if(outVertices[idVert].OnBorder)
784 // copy the vertex.
785 pa.Patch.Vertices[corner]= outVertices[idVert].Vertex;
791 // For all borderVertices of adjacentZone, copy from outVertices.
792 for(i=0;i<8;i++)
794 if(adjZonesName[i]=="empty") continue;
795 if(!adjZoneFileFound[i]) continue;
797 // get the entry in the map.
798 vector<CAdjacentVertex> &verts= adjVertices[adjZonesId[i]];
800 // for all patch, get vertices which are n Border of the cetnerZone.
801 std::vector<CPatchInfo> &adjZonePatchs= adjZoneInfos[i].Patchs;
802 for(ptch=0; ptch<adjZonePatchs.size(); ptch++)
804 CPatchInfo &pa= adjZonePatchs[ptch];
805 for(uint corner= 0; corner<4; corner++)
807 uint idVert= pa.BaseVertices[corner];
809 if(verts[idVert].OnBorder)
811 pa.Patch.Vertices[corner]= outVertices[verts[idVert].IdOnCenterZone].Vertex;
822 // Yoyo: make coplanar beetween zones.
823 //====================================
825 std::vector<CZoneInfo> zones;
826 CZoneInfo zinf;
828 // center.
829 zinf.ZoneId= centerZoneId;
830 zinf.Patchs= centerZonePatchs;
831 zinf.BorderVertices= centerZoneBorderVertices;
832 zones.push_back(zinf);
834 // adjs.
835 for(i=0;i<8;i++)
837 if(adjZonesName[i]=="empty") continue;
838 if(!adjZoneFileFound[i]) continue;
839 zones.push_back(adjZoneInfos[i]);
842 CZoneTgtSmoother tgtsmoother;
843 tgtsmoother.makeVerticesCoplanar(zones);
845 // retrieve center zone result.
846 centerZonePatchs= zones[0].Patchs;
847 centerZoneBorderVertices= zones[0].BorderVertices;
849 // retrieve adj zone result.
850 sint numZone= 1;
851 for(i=0;i<8;i++)
853 if(adjZonesName[i]=="empty") continue;
854 if(!adjZoneFileFound[i]) continue;
856 adjZoneInfos[i]= zones[numZone];
857 numZone++;
862 // Yoyo: compute corner smooth info.
863 //====================================
864 // CANNOT DO IT HERE, BECAUSE THE CURRENT ZONE MAY NOT BE CORRECLTY WELDED.
865 // MUST DO IT IN ZONE_LIGHTER.
867 // build a landscape, because CZoneCornerSmooth use compiled zones.
868 CLandscape land;
869 CZoneCornerSmoother zcs;
871 land.init();
873 // add center zone.
874 zone.build(centerZoneId, centerZonePatchs, centerZoneBorderVertices);
875 land.addZone(zone);
876 CZone *centerZone= land.getZone(centerZoneId);
878 // add adjacent zones.
879 vector<CZone*> nbZones;
880 for(i=0;i<8;i++)
882 if(adjZonesName[i]=="empty") continue;
883 if(!adjZoneFileFound[i]) continue;
885 std::vector<CPatchInfo> &adjZonePatchs= adjZoneInfos[i].Patchs;
886 std::vector<CBorderVertex> &adjZoneBorderVertices= adjZoneInfos[i].BorderVertices;
888 adjZones[i].build(adjZonesId[i], adjZonePatchs, adjZoneBorderVertices);
889 land.addZone(adjZones[i]);
891 CZone *nbZone= land.getZone(adjZonesId[i]);
892 if(nbZone)
893 nbZones.push_back(nbZone);
896 // now, do the zoneCornerSmoother.
897 if(centerZone)
899 // go.
900 zcs.computeAllCornerSmoothFlags(centerZone, nbZones);
902 // get result from the compiled zone, and copy in the uncompiled one (ie in centerZonePatchs).
903 for(i=0;i<centerZonePatchs.size();i++)
905 const CPatch &paSrc= *((const CZone*)centerZone)->getPatch(i);
906 CPatchInfo &paDst= centerZonePatchs[i];
907 for(uint corner=0; corner<4; corner++)
908 paDst.setCornerSmoothFlag(corner, paSrc.getCornerSmoothFlag(corner));
913 // Some errors ?
914 if (errorMessage.empty())
916 // Save adjacent zones.
917 //=====================
918 for(i=0;i<8;i++)
920 if(adjZonesName[i]=="empty") continue;
921 if(!adjZoneFileFound[i]) continue;
923 std::vector<CPatchInfo> &adjZonePatchs= adjZoneInfos[i].Patchs;
924 std::vector<CBorderVertex> &adjZoneBorderVertices= adjZoneInfos[i].BorderVertices;
926 adjZones[i].build(adjZonesId[i], adjZonePatchs, adjZoneBorderVertices);
927 #if WELD_LOG
928 fprintf(fdbg,"[%d] binds :\n", i);
929 adjZones[i].debugBinds(fdbg);
930 #endif
931 std::string strtmp;
933 //strtmp = outputPath;
934 strtmp = outputDir+adjZonesName[i]+outputExt;
935 COFile adjSave(strtmp);
936 printf("writing file %s\n",strtmp.c_str());
937 adjZones[i].serial(adjSave);
941 // Save center zone.
942 //==================
943 zone.build(centerZoneId, centerZonePatchs, centerZoneBorderVertices);
944 std::string strtmp;
945 strtmp = outputDir+center+outputExt;
947 COFile centerSave(strtmp);
948 printf("writing file %s\n",strtmp.c_str());
949 zone.serial(centerSave);
951 else
953 // Main message
954 nlwarning ("ERROR weld failed. Correct errors below: (indices are MAX indices (+1))\n");
956 // For each message
957 for (uint i=0; i<errorMessage.size(); i++)
959 // Message
960 nlwarning ("%s", errorMessage[i].c_str());
968 /*******************************************************************\
969 main()
970 \*******************************************************************/
971 int main(sint argc, char **argv)
973 // no zone file in argument
974 if(argc<3)
976 writeInstructions();
977 return 0;
980 // help
981 if(strcmp(argv[1],"/?")==0)
983 writeInstructions();
984 return 0;
987 #if WELD_LOG
988 fdbg = nlfopen("log.txt","wt");
989 fprintf(fdbg,"Center zone : %s\n",argv[1]);
990 #endif
992 printf("Center zone : %s\n",argv[1]);
994 inputDir = getDir (argv[1]);
995 inputExt = getExt (argv[1]);
996 outputDir = getDir (argv[2]);
997 outputExt = getExt (argv[2]);
999 if(argc == 4)
1001 NLMISC::fromString(argv[3], weldRadius);
1004 std::string center=getName(argv[1]).c_str();
1005 weldZones(center.c_str());
1007 #if WELD_LOG
1008 fclose(fdbg);
1009 #endif
1011 return 0;