| 108 | } |
| 109 | |
| 110 | bool MeshData::GenerateLightmapUVs() |
| 111 | { |
| 112 | if (Positions.IsEmpty() || Indices.IsEmpty()) |
| 113 | return true; |
| 114 | PROFILE_CPU(); |
| 115 | #if PLATFORM_WINDOWS |
| 116 | // Prepare |
| 117 | HRESULT hr; |
| 118 | int32 verticesCount = Positions.Count(); |
| 119 | int32 facesCount = Indices.Count() / 3; |
| 120 | DirectX::XMFLOAT3* positions = (DirectX::XMFLOAT3*)Positions.Get(); |
| 121 | LOG(Info, "Generating lightmaps UVs ({0} vertices, {1} triangles)...", verticesCount, facesCount); |
| 122 | Stopwatch stopwatch; |
| 123 | |
| 124 | // Generate adjacency data |
| 125 | const float adjacencyEpsilon = 0.001f; |
| 126 | Array<uint32> adjacency; |
| 127 | adjacency.Resize(Indices.Count()); |
| 128 | hr = GenerateAdjacencyAndPointReps(Indices.Get(), facesCount, positions, verticesCount, adjacencyEpsilon, nullptr, adjacency.Get()); |
| 129 | if (FAILED(hr)) |
| 130 | { |
| 131 | LOG(Warning, "Cannot generate lightmap uvs. Result: {0:x}:{1}", hr, 0); |
| 132 | return true; |
| 133 | } |
| 134 | |
| 135 | // Generate UVs |
| 136 | std::vector<DirectX::UVAtlasVertex> vb; |
| 137 | std::vector<uint8_t> ib; |
| 138 | float outStretch = 0.0f; |
| 139 | size_t outCharts = 0; |
| 140 | std::vector<uint32_t> facePartitioning; |
| 141 | std::vector<uint32_t> vertexRemapArray; |
| 142 | int32 size = 1024; |
| 143 | float gutter = 1.0f; |
| 144 | hr = UVAtlasCreate( |
| 145 | positions, verticesCount, |
| 146 | Indices.Get(), DXGI_FORMAT_R32_UINT, facesCount, |
| 147 | 0, 0.1f, size, size, gutter, |
| 148 | adjacency.Get(), nullptr, nullptr, |
| 149 | UVAtlasCallback, DirectX::UVATLAS_DEFAULT_CALLBACK_FREQUENCY, |
| 150 | DirectX::UVATLAS_GEODESIC_FAST, vb, ib, |
| 151 | &facePartitioning, |
| 152 | &vertexRemapArray, |
| 153 | &outStretch, &outCharts); |
| 154 | if (FAILED(hr)) |
| 155 | { |
| 156 | LOG(Warning, "Cannot generate lightmap uvs. Result: {0:x}:{1}", hr, 1); |
| 157 | return true; |
| 158 | } |
| 159 | |
| 160 | // Log info |
| 161 | stopwatch.Stop(); |
| 162 | LOG(Info, "Lightmap UVs generated! Charts: {0}, stretching: {1}, {2} vertices. Time: {3}ms", outCharts, outStretch, (int32)vb.size(), stopwatch.GetMilliseconds()); |
| 163 | |
| 164 | // Update mesh data (remap vertices due to vertex buffer and index buffer change) |
| 165 | RemapArrayHelper(Positions, vertexRemapArray); |
| 166 | LightmapUVsIndex = Math::Min(UVs.Count(), MODEL_MAX_UV - 1); |
| 167 | for (int32 channel = 0; channel < LightmapUVsIndex; channel++) |