------------------------------------------------------------------------------------------------ Note - this is an implementation of the standard (recursive) Cm-Cl algorithm without further optimizations (except we're using some nice LUTs). A description of the algorithm can be found here: http://en.wikipedia.org/wiki/Catmull-Clark_subdivision_surface The code is mostly O(n), however parts are O(
| 223 | // Previous data is replaced/deleted then. |
| 224 | // ------------------------------------------------------------------------------------------------ |
| 225 | void CatmullClarkSubdivider::InternSubdivide( |
| 226 | const aiMesh *const *smesh, |
| 227 | size_t nmesh, |
| 228 | aiMesh **out, |
| 229 | unsigned int num) { |
| 230 | ai_assert(nullptr != smesh); |
| 231 | ai_assert(nullptr != out); |
| 232 | |
| 233 | INIT_EDGE_HASH_TEMPORARIES(); |
| 234 | |
| 235 | // no subdivision requested or end of recursive refinement |
| 236 | if (!num) { |
| 237 | return; |
| 238 | } |
| 239 | |
| 240 | UIntVector maptbl; |
| 241 | SpatialSort spatial; |
| 242 | |
| 243 | // --------------------------------------------------------------------- |
| 244 | // 0. Offset table to index all meshes continuously, generate a spatially |
| 245 | // sorted representation of all vertices in all meshes. |
| 246 | // --------------------------------------------------------------------- |
| 247 | typedef std::pair<unsigned int, unsigned int> IntPair; |
| 248 | std::vector<IntPair> moffsets(nmesh); |
| 249 | unsigned int totfaces = 0, totvert = 0; |
| 250 | for (size_t t = 0; t < nmesh; ++t) { |
| 251 | const aiMesh *mesh = smesh[t]; |
| 252 | |
| 253 | spatial.Append(mesh->mVertices, mesh->mNumVertices, sizeof(aiVector3D), false); |
| 254 | moffsets[t] = IntPair(totfaces, totvert); |
| 255 | |
| 256 | totfaces += mesh->mNumFaces; |
| 257 | totvert += mesh->mNumVertices; |
| 258 | } |
| 259 | |
| 260 | spatial.Finalize(); |
| 261 | const unsigned int num_unique = spatial.GenerateMappingTable(maptbl, ComputePositionEpsilon(smesh, nmesh)); |
| 262 | |
| 263 | #define FLATTEN_VERTEX_IDX(mesh_idx, vert_idx) (moffsets[mesh_idx].second + vert_idx) |
| 264 | #define FLATTEN_FACE_IDX(mesh_idx, face_idx) (moffsets[mesh_idx].first + face_idx) |
| 265 | |
| 266 | // --------------------------------------------------------------------- |
| 267 | // 1. Compute the centroid point for all faces |
| 268 | // --------------------------------------------------------------------- |
| 269 | std::vector<Vertex> centroids(totfaces); |
| 270 | unsigned int nfacesout = 0; |
| 271 | for (size_t t = 0, n = 0; t < nmesh; ++t) { |
| 272 | const aiMesh *mesh = smesh[t]; |
| 273 | for (unsigned int i = 0; i < mesh->mNumFaces; ++i, ++n) { |
| 274 | const aiFace &face = mesh->mFaces[i]; |
| 275 | Vertex &c = centroids[n]; |
| 276 | |
| 277 | for (unsigned int a = 0; a < face.mNumIndices; ++a) { |
| 278 | c += Vertex(mesh, face.mIndices[a]); |
| 279 | } |
| 280 | |
| 281 | c /= static_cast<float>(face.mNumIndices); |
| 282 | nfacesout += face.mNumIndices; |
nothing calls this directly
no test coverage detected