592 {
593
594 char tileString[20];
595 sprintf(tileString, "[Map %03i] [%02i,%02i]: ", mapID, tileX, tileY);
596 printf("%s Building movemap tiles...\n", tileString);
597
598 IntermediateValues iv;
599
600 float* tVerts = meshData.solidVerts.getCArray();
601 int tVertCount = meshData.solidVerts.size() / 3;
602 int* tTris = meshData.solidTris.getCArray();
603 int tTriCount = meshData.solidTris.size() / 3;
604
605 float* lVerts = meshData.liquidVerts.getCArray();
606 int lVertCount = meshData.liquidVerts.size() / 3;
607 int* lTris = meshData.liquidTris.getCArray();
608 int lTriCount = meshData.liquidTris.size() / 3;
609 uint8* lTriFlags = meshData.liquidType.getCArray();
610
612 int TILES_PER_MAP = tileConfig.TILES_PER_MAP;
613 float BASE_UNIT_DIM = tileConfig.BASE_UNIT_DIM;
615
616
617 rcCalcGridSize(config.bmin, config.bmax, config.cs, &config.width, &config.height);
618
619
620 Tile* tiles = new Tile[TILES_PER_MAP * TILES_PER_MAP];
621
622
623 rcConfig tileCfg = config;
624 tileCfg.width = config.tileSize + config.borderSize * 2;
625 tileCfg.height = config.tileSize + config.borderSize * 2;
626
627
628 rcPolyMesh** pmmerge = new rcPolyMesh*[TILES_PER_MAP * TILES_PER_MAP];
629 rcPolyMeshDetail** dmmerge = new rcPolyMeshDetail*[TILES_PER_MAP * TILES_PER_MAP];
630 int nmerge = 0;
631
632 for (int y = 0; y < TILES_PER_MAP; ++y)
633 {
634 for (int x = 0; x < TILES_PER_MAP; ++x)
635 {
636 Tile& tile = tiles[x + y * TILES_PER_MAP];
637
638
639 tileCfg.bmin[0] = config.bmin[0] + x * float(config.tileSize * config.cs);
640 tileCfg.bmin[2] = config.bmin[2] + y * float(config.tileSize * config.cs);
641 tileCfg.bmax[0] = config.bmin[0] + (x + 1) * float(config.tileSize * config.cs);
642 tileCfg.bmax[2] = config.bmin[2] + (y + 1) * float(config.tileSize * config.cs);
643
644 tileCfg.bmin[0] -= tileCfg.borderSize * tileCfg.cs;
645 tileCfg.bmin[2] -= tileCfg.borderSize * tileCfg.cs;
646 tileCfg.bmax[0] += tileCfg.borderSize * tileCfg.cs;
647 tileCfg.bmax[2] += tileCfg.borderSize * tileCfg.cs;
648
649
650 tile.solid = rcAllocHeightfield();
651 if (!tile.solid || !rcCreateHeightfield(
m_rcContext, *tile.solid, tileCfg.width, tileCfg.height, tileCfg.bmin, tileCfg.bmax, tileCfg.cs, tileCfg.ch))
652 {
653 printf("%s Failed building heightfield! \n", tileString);
654 continue;
655 }
656
657
658
659 unsigned char* triFlags = new unsigned char[tTriCount];
660 memset(triFlags,
NAV_GROUND, tTriCount *
sizeof(
unsigned char));
661 rcClearUnwalkableTriangles(
m_rcContext, tileCfg.walkableSlopeAngle, tVerts, tVertCount, tTris, tTriCount, triFlags);
662 rcRasterizeTriangles(
m_rcContext, tVerts, tVertCount, tTris, triFlags, tTriCount, *tile.solid, config.walkableClimb);
663 delete[] triFlags;
664
665 rcFilterLowHangingWalkableObstacles(
m_rcContext, config.walkableClimb, *tile.solid);
666 rcFilterLedgeSpans(
m_rcContext, tileCfg.walkableHeight, tileCfg.walkableClimb, *tile.solid);
667 rcFilterWalkableLowHeightSpans(
m_rcContext, tileCfg.walkableHeight, *tile.solid);
668
669
670 rcRasterizeTriangles(
m_rcContext, lVerts, lVertCount, lTris, lTriFlags, lTriCount, *tile.solid, config.walkableClimb);
671
672
673 tile.chf = rcAllocCompactHeightfield();
674 if (!tile.chf || !rcBuildCompactHeightfield(
m_rcContext, tileCfg.walkableHeight, tileCfg.walkableClimb, *tile.solid, *tile.chf))
675 {
676 printf("%s Failed compacting heightfield! \n", tileString);
677 continue;
678 }
679
680
681 if (!rcErodeWalkableArea(
m_rcContext, config.walkableRadius, *tile.chf))
682 {
683 printf("%s Failed eroding area! \n", tileString);
684 continue;
685 }
686
688 {
689 printf("%s Failed building distance field! \n", tileString);
690 continue;
691 }
692
693 if (!rcBuildRegions(
m_rcContext, *tile.chf, tileCfg.borderSize, tileCfg.minRegionArea, tileCfg.mergeRegionArea))
694 {
695 printf("%s Failed building regions! \n", tileString);
696 continue;
697 }
698
699 tile.cset = rcAllocContourSet();
700 if (!tile.cset || !rcBuildContours(
m_rcContext, *tile.chf, tileCfg.maxSimplificationError, tileCfg.maxEdgeLen, *tile.cset))
701 {
702 printf("%s Failed building contours! \n", tileString);
703 continue;
704 }
705
706
707 tile.pmesh = rcAllocPolyMesh();
708 if (!tile.pmesh || !rcBuildPolyMesh(
m_rcContext, *tile.cset, tileCfg.maxVertsPerPoly, *tile.pmesh))
709 {
710 printf("%s Failed building polymesh! \n", tileString);
711 continue;
712 }
713
714 tile.dmesh = rcAllocPolyMeshDetail();
715 if (!tile.dmesh || !rcBuildPolyMeshDetail(
m_rcContext, *tile.pmesh, *tile.chf, tileCfg.detailSampleDist, tileCfg.detailSampleMaxError, *tile.dmesh))
716 {
717 printf("%s Failed building polymesh detail! \n", tileString);
718 continue;
719 }
720
721
722
723
724 rcFreeHeightField(tile.solid);
725 tile.solid = nullptr;
726 rcFreeCompactHeightfield(tile.chf);
727 tile.chf = nullptr;
728 rcFreeContourSet(tile.cset);
729 tile.cset = nullptr;
730
731 pmmerge[nmerge] = tile.pmesh;
732 dmmerge[nmerge] = tile.dmesh;
733 nmerge++;
734 }
735 }
736
737 iv.polyMesh = rcAllocPolyMesh();
738 if (!iv.polyMesh)
739 {
740 printf("%s alloc iv.polyMesh FAILED!\n", tileString);
741 delete[] pmmerge;
742 delete[] dmmerge;
743 delete[] tiles;
744 return;
745 }
746 rcMergePolyMeshes(
m_rcContext, pmmerge, nmerge, *iv.polyMesh);
747
748 iv.polyMeshDetail = rcAllocPolyMeshDetail();
749 if (!iv.polyMeshDetail)
750 {
751 printf("%s alloc m_dmesh FAILED!\n", tileString);
752 delete[] pmmerge;
753 delete[] dmmerge;
754 delete[] tiles;
755 return;
756 }
757 rcMergePolyMeshDetails(
m_rcContext, dmmerge, nmerge, *iv.polyMeshDetail);
758
759
760 delete[] pmmerge;
761 delete[] dmmerge;
762 delete[] tiles;
763
764
766 for (int i = 0; i < iv.polyMesh->npolys; ++i)
767 if (iv.polyMesh->areas[i] & RC_WALKABLE_AREA)
768 iv.polyMesh->flags[i] = iv.polyMesh->areas[i];
769
770
771 dtNavMeshCreateParams params;
772 memset(¶ms, 0, sizeof(params));
773 params.verts = iv.polyMesh->verts;
774 params.vertCount = iv.polyMesh->nverts;
775 params.polys = iv.polyMesh->polys;
776 params.polyAreas = iv.polyMesh->areas;
777 params.polyFlags = iv.polyMesh->flags;
778 params.polyCount = iv.polyMesh->npolys;
779 params.nvp = iv.polyMesh->nvp;
780 params.detailMeshes = iv.polyMeshDetail->meshes;
781 params.detailVerts = iv.polyMeshDetail->verts;
782 params.detailVertsCount = iv.polyMeshDetail->nverts;
783 params.detailTris = iv.polyMeshDetail->tris;
784 params.detailTriCount = iv.polyMeshDetail->ntris;
785
786 params.offMeshConVerts = meshData.offMeshConnections.getCArray();
787 params.offMeshConCount = meshData.offMeshConnections.size() / 6;
788 params.offMeshConRad = meshData.offMeshConnectionRads.getCArray();
789 params.offMeshConDir = meshData.offMeshConnectionDirs.getCArray();
790 params.offMeshConAreas = meshData.offMeshConnectionsAreas.getCArray();
791 params.offMeshConFlags = meshData.offMeshConnectionsFlags.getCArray();
792
793 params.walkableHeight = BASE_UNIT_DIM * config.walkableHeight;
794 params.walkableRadius = BASE_UNIT_DIM * config.walkableRadius;
795 params.walkableClimb = BASE_UNIT_DIM * config.walkableClimb;
796 params.tileX = (((bmin[0] + bmax[0]) / 2) - navMesh->getParams()->orig[0]) /
GRID_SIZE;
797 params.tileY = (((bmin[2] + bmax[2]) / 2) - navMesh->getParams()->orig[2]) /
GRID_SIZE;
798 rcVcopy(params.bmin, bmin);
799 rcVcopy(params.bmax, bmax);
800 params.cs = config.cs;
801 params.ch = config.ch;
802 params.tileLayer = 0;
803 params.buildBvTree = true;
804
805
806 unsigned char* navData = nullptr;
807 int navDataSize = 0;
808
809 do
810 {
811
812
813 if (params.nvp > DT_VERTS_PER_POLYGON)
814 {
815 printf("%s Invalid verts-per-polygon value! \n", tileString);
816 break;
817 }
818 if (params.vertCount >= 0xffff)
819 {
820 printf("%s Too many vertices! \n", tileString);
821 break;
822 }
823 if (!params.vertCount || !params.verts)
824 {
825
826
827
828
829 printf("%sNo vertices to build tile! \n", tileString);
830 break;
831 }
832 if (!params.polyCount || !params.polys)
833 {
834
835
836 printf("%s No polygons to build on tile! \n", tileString);
837 break;
838 }
839 if (!params.detailMeshes || !params.detailVerts || !params.detailTris)
840 {
841 printf("%s No detail mesh to build tile! \n", tileString);
842 break;
843 }
844
845 printf("%s Building navmesh tile...\n", tileString);
846 if (!dtCreateNavMeshData(¶ms, &navData, &navDataSize))
847 {
848 printf("%s Failed building navmesh tile! \n", tileString);
849 break;
850 }
851
852 dtTileRef tileRef = 0;
853 printf("%s Adding tile to navmesh...\n", tileString);
854
855
856 dtStatus dtResult = navMesh->addTile(navData, navDataSize, DT_TILE_FREE_DATA, 0, &tileRef);
857 if (!tileRef || dtResult != DT_SUCCESS)
858 {
859 printf("%s Failed adding tile to navmesh! \n", tileString);
860 break;
861 }
862
863
864 char fileName[255];
865 sprintf(fileName, "mmaps/%03u%02i%02i.mmtile", mapID, tileY, tileX);
866 FILE* file = fopen(fileName, "wb");
867 if (!file)
868 {
869 char message[1024];
870 sprintf(message, "[Map %03i] Failed to open %s for writing!\n", mapID, fileName);
871 perror(message);
872 navMesh->removeTile(tileRef, nullptr, nullptr);
873 break;
874 }
875
876 printf("%s Writing to file...\n", tileString);
877
878
883
884
885 fwrite(navData, sizeof(unsigned char), navDataSize, file);
886 fclose(file);
887
888
889 navMesh->removeTile(tileRef, nullptr, nullptr);
890 } while (false);
891
893 {
894
895 for (int i = 0; i < iv.polyMesh->nverts; ++i)
896 {
897 unsigned short* v = &iv.polyMesh->verts[i * 3];
898 v[0] += (unsigned short)config.borderSize;
899 v[2] += (unsigned short)config.borderSize;
900 }
901
902 iv.generateObjFile(mapID, tileX, tileY, meshData);
903 iv.writeIV(mapID, tileX, tileY);
904 }
905 }
std::uint8_t uint8
Definition Define.h:109
std::uint32_t uint32
Definition Define.h:107
@ NAV_GROUND
Definition MapDefines.h:55
rcConfig GetMapSpecificConfig(uint32 mapID, float bmin[3], float bmax[3], const TileConfig &tileConfig) const
Definition MapBuilder.cpp:1052
bool usesLiquids() const
Definition TerrainBuilder.h:88
static const float GRID_SIZE
Definition TerrainBuilder.h:48