OBJ 파일과 BVH 를 로딩하는 샘플 코드

   1 #pragma mark Mesh Loading
   2 ModelBvh LoadObjModel(const DKString& obj, const DKString& tex, DKMaterial* material, bool genBvh, bool useCachedData)
   3 {
   4     ModelBvh result = { "", NULL, NULL };
   5     DKResourcePool pool;
   6     DKObject<DKTexture2D> texture = pool.LoadResource(tex).SafeCast<DKTexture2D>();
   7     if (texture == NULL)
   8     {
   9         DKLog("Failed to load texture: %ls\n", (const wchar_t*)tex);
  10         return result;
  11     }
  12     DKString dkMeshFile = obj + ".dkmesh";
  13     DKString dkBvhFile = obj + ".dktbvh";
  14 
  15     DKObject<DKStaticMesh> mesh = NULL;
  16     DKObject<DKTriangleMeshBvh> bvh = NULL;
  17 
  18     if (useCachedData)
  19     {
  20         mesh = pool.LoadResource(dkMeshFile).SafeCast<DKStaticMesh>();
  21         if (mesh && genBvh)
  22         {
  23             DKObject<DKData> triData = pool.LoadResourceData(dkBvhFile);
  24             if (triData && triData->Length() > 0)
  25             {
  26                 DKObject<BvhMesh> bvhMesh = DKOBJECT_NEW BvhMesh();
  27 
  28                 const DKTriangle* triangles = reinterpret_cast<const DKTriangle*>(triData->LockShared());
  29                 int numTri = (int)(triData->Length() / sizeof(DKTriangle));
  30                 bvhMesh->triangles.Add(triangles, numTri);
  31                 triData->UnlockShared();
  32 
  33                 bvh = DKOBJECT_NEW DKTriangleMeshBvh();
  34                 bvh->Build(bvhMesh);
  35             }
  36         }
  37     }
  38     if (mesh == NULL || (genBvh && bvh == NULL))
  39     {
  40         DKObject<DKData> objData = pool.LoadResourceData(obj);
  41         if (objData && objData->Length() > 0)
  42         {
  43             DKLog("Loading %ls... (%lu bytes)\n", (const wchar_t*)obj, objData->Length());
  44             DKTimer timer;
  45             timer.Reset();
  46 
  47             DKArray<DKVector3> positions;
  48             DKArray<DKVector2> texcoords;
  49             DKArray<DKVector3> normals;
  50             struct Face
  51             {
  52                 int pos, uv, normal;
  53             };
  54             DKArray<Face> faces;
  55             DKString lineString;
  56 
  57             positions.Reserve(0x10000);
  58             texcoords.Reserve(0x10000);
  59             normals.Reserve(0x10000);
  60             faces.Reserve(0x10000);
  61 
  62             DKUniChar8* p = (DKUniChar8*)objData->LockShared();
  63             size_t length = objData->Length();
  64             size_t pos = 0;
  65             for (size_t i = 0; i < length; ++i)
  66             {
  67                 if (p[i] == '\n')
  68                 {
  69                     if (pos < i)
  70                     {
  71                         DKString::StringArray words = DKString(&p[pos], (i - pos)).SplitByWhitespace();
  72                         if (words.Count() > 0)
  73                         {
  74                             if (words.Value(0).CompareNoCase("v") == 0)    // vertex
  75                             {
  76                                 if (words.Count() > 3)
  77                                 {
  78                                     DKVector3 vector(words.Value(1).ToRealNumber(),
  79                                                      words.Value(2).ToRealNumber(),
  80                                                      words.Value(3).ToRealNumber());
  81                                     positions.Add(vector);
  82                                 }
  83                             }
  84                             else if (words.Value(0).CompareNoCase("vn") == 0)    // normal
  85                             {
  86                                 if (words.Count() > 3)
  87                                 {
  88                                     DKVector3 vector(words.Value(1).ToRealNumber(),
  89                                                      words.Value(2).ToRealNumber(),
  90                                                      words.Value(3).ToRealNumber());
  91                                     normals.Add(vector);
  92                                 }
  93                             }
  94                             else if (words.Value(0).CompareNoCase("vt") == 0)    // tex-coords
  95                             {
  96                                 if (words.Count() > 2)
  97                                 {
  98                                     DKVector2 vector(words.Value(1).ToRealNumber(),
  99                                                      words.Value(2).ToRealNumber());
 100 
 101                                     texcoords.Add(vector);
 102                                 }
 103                             }
 104                             else if (words.Value(0).CompareNoCase("f") == 0) // face
 105                             {
 106                                 size_t numFaces = words.Count() - 1;
 107                                 Face f[4];
 108                                 int idx = 0;
 109                                 auto getIndex = [](int idx, int count) -> int
 110                                 {
 111                                     int v;
 112                                     if (idx > 0)
 113                                         v = idx - 1;
 114                                     else
 115                                         v = count + idx;
 116                                     return Clamp(v, 0, count - 1);
 117                                 };
 118                                 while (idx < numFaces)
 119                                 {
 120                                     DKString::IntegerArray indices = words.Value(idx + 1).ToIntegerArray("/");
 121                                     if (indices.Count() > 2)    // pos, uv, normal
 122                                     {
 123                                         f[idx].pos = getIndex(indices.Value(0), positions.Count());
 124                                         f[idx].uv = getIndex(indices.Value(1), texcoords.Count());
 125                                         f[idx].normal = getIndex(indices.Value(2), normals.Count());
 126                                         idx++;
 127                                     }
 128                                     else if (indices.Count() > 1)    // pos, uv
 129                                     {
 130                                         f[idx].pos = getIndex(indices.Value(0), positions.Count());
 131                                         f[idx].uv = getIndex(indices.Value(1), texcoords.Count());
 132                                         f[idx].normal = 0;
 133                                         idx++;
 134                                     }
 135                                     else
 136                                         break;
 137                                 }
 138                                 if (idx == 3)        // triangle
 139                                 {
 140                                     faces.Add(f, 3);
 141                                 }
 142                                 else if (idx == 4)    // quad
 143                                 {
 144                                     faces.Add({ f[1], f[2], f[0], f[0], f[2], f[3] });
 145                                 }
 146                                 else    // error??
 147                                 {
 148                                 }
 149                             }
 150                         }
 151                     }
 152                     pos = i + 1;
 153                 }
 154             }
 155             objData->UnlockShared();
 156             objData = NULL;
 157 
 158             DKLog("Num Positions: %lu\n", positions.Count());
 159             DKLog("Num TexCoords: %lu\n", texcoords.Count());
 160             DKLog("Num Normals: %lu\n", normals.Count());
 161             DKLog("Num Faces: %lu\n", faces.Count());
 162 
 163             if (faces.Count() > 0 && positions.Count() > 0 && texcoords.Count() > 0)
 164             {
 165                 struct Vertex
 166                 {
 167                     DKVector3 pos;
 168                     DKVector3 normal;
 169                     DKVector2 uv;
 170                 };
 171                 DKAabb aabb;
 172                 DKArray<Vertex> vertices;
 173                 vertices.Reserve(faces.Count());
 174                 if (normals.Count() > 0)
 175                 {
 176                     for (int i = 0; (i + 2) < faces.Count(); i += 3)
 177                     {
 178                         const Face& f1 = faces.Value(i);
 179                         const Face& f2 = faces.Value(i + 1);
 180                         const Face& f3 = faces.Value(i + 2);
 181 
 182                         Vertex v[3] = {
 183                             { positions.Value(f1.pos), normals.Value(f1.normal), texcoords.Value(f1.uv) },
 184                         { positions.Value(f2.pos), normals.Value(f2.normal), texcoords.Value(f2.uv) },
 185                         { positions.Value(f3.pos), normals.Value(f2.normal), texcoords.Value(f3.uv) },
 186                         };
 187 
 188                         vertices.Add(v, 3);
 189                         aabb.Expand(v[0].pos);
 190                         aabb.Expand(v[1].pos);
 191                         aabb.Expand(v[2].pos);
 192                     }
 193                 }
 194                 else
 195                 {
 196                     DKLog("Generating face normals...\n");
 197                     for (int i = 0; (i + 2) < faces.Count(); i += 3)
 198                     {
 199                         const Face& f1 = faces.Value(i);
 200                         const Face& f2 = faces.Value(i + 1);
 201                         const Face& f3 = faces.Value(i + 2);
 202 
 203                         const DKVector3& pos1 = positions.Value(f1.pos);
 204                         const DKVector3& pos2 = positions.Value(f2.pos);
 205                         const DKVector3& pos3 = positions.Value(f3.pos);
 206 
 207                         DKVector3 faceNormal = DKVector3::Cross(pos2 - pos1, pos3 - pos1).Normalize();
 208 
 209                         Vertex v[3] = {
 210                             { pos1, faceNormal, texcoords.Value(f1.uv) },
 211                         { pos2, faceNormal, texcoords.Value(f2.uv) },
 212                         { pos3, faceNormal, texcoords.Value(f3.uv) },
 213                         };
 214 
 215                         vertices.Add(v, 3);
 216                         aabb.Expand(v[0].pos);
 217                         aabb.Expand(v[1].pos);
 218                         aabb.Expand(v[2].pos);
 219                     }
 220                 }
 221                 DKVertexBuffer::Decl decls[3] = {
 222                     { DKVertexStream::StreamPosition, L"", DKVertexStream::TypeFloat3, false },
 223                 { DKVertexStream::StreamNormal , L"", DKVertexStream::TypeFloat3, false },
 224                 { DKVertexStream::StreamTexCoord, L"", DKVertexStream::TypeFloat2, false },
 225                 };
 226                 DKObject<DKVertexBuffer> vb = DKVertexBuffer::Create(decls, 3, vertices, sizeof(Vertex), vertices.Count(), DKVertexBuffer::MemoryLocationStatic, DKVertexBuffer::BufferUsageDraw);
 227 
 228                 mesh = DKObject<DKStaticMesh>::New();
 229                 mesh->SetDrawFace(DKMesh::DrawFaceBoth);
 230                 mesh->SetDefaultPrimitiveType(DKPrimitive::TypeTriangles);
 231                 mesh->AddVertexBuffer(vb);
 232                 mesh->SetAabb(aabb);
 233                 DKLog("Obj %ls file loaded. (%f sec)\n", (const wchar_t*)obj, timer.Elapsed());
 234 
 235                 DKObject<BvhMesh> bvhMesh = NULL;
 236                 if (genBvh)
 237                 {
 238                     // Create bvh
 239                     DKTimer bvhTimer;
 240                     bvhTimer.Reset();
 241 
 242                     bvhMesh = DKOBJECT_NEW BvhMesh();
 243                     int numTri = (int)(vertices.Count() / 3);
 244                     bvhMesh->triangles.Reserve(numTri);
 245                     for (int i = 0; i < numTri; ++i)
 246                     {
 247                         const Vertex& v1 = vertices.Value(i * 3);
 248                         const Vertex& v2 = vertices.Value(i * 3 + 1);
 249                         const Vertex& v3 = vertices.Value(i * 3 + 2);
 250 
 251                         DKTriangle t = { v1.pos, v2.pos, v3.pos };
 252                         bvhMesh->triangles.Add(t);
 253                     }
 254                     bvh = DKOBJECT_NEW DKTriangleMeshBvh();
 255                     bvh->Build(bvhMesh);
 256 
 257                     double d = bvhTimer.Elapsed();
 258                     DKLog("Generating BVH elapsed: %f\n", d);
 259                 }
 260                 if (useCachedData)
 261                 {
 262                     DKObject<DKData> data = mesh->Serialize(DKSerializer::SerializeFormCompressedBinary);
 263                     if (data)
 264                     {
 265                         DKLog("Writing DKMesh file: %ls\n", (const wchar_t*)dkMeshFile);
 266                         data->WriteToFile(dkMeshFile, true);
 267                     }
 268                     if (bvhMesh && bvhMesh->triangles.Count() > 0)
 269                     {
 270                         data = DKData::StaticData(bvhMesh->triangles, sizeof(DKTriangle) * bvhMesh->triangles.Count());
 271                         if (data)
 272                         {
 273                             DKLog("Writing DKBvh file: %ls\n", (const wchar_t*)dkBvhFile);
 274                             data->WriteToFile(dkBvhFile, true);
 275                         }
 276                     }
 277                 }
 278             }
 279         }
 280         else
 281         {
 282             // error.
 283             DKLog("Failed to load obj file: %ls\n", (const wchar_t*)obj);
 284         }
 285     }
 286     if (mesh)
 287     {
 288         DKAabb aabb = mesh->Aabb();
 289         DKLog("AABB: (%.3f, %.3f, %.3f), (%.3f, %.3f, %.3f)\n",
 290               aabb.positionMin.x, aabb.positionMin.y, aabb.positionMin.z,
 291               aabb.positionMax.x, aabb.positionMax.y, aabb.positionMax.z);
 292         DKLog("AABB width: %.3f, height: %.3f, depth: %.3f\n",
 293               aabb.positionMax.x - aabb.positionMin.x,
 294               aabb.positionMax.y - aabb.positionMin.y,
 295               aabb.positionMax.z - aabb.positionMin.z);
 296 
 297         //        DKObject<DKTextureSampler> sampler = DKOBJECT_NEW DKTextureSampler();
 298         //        sampler->magFilter = DKTextureSampler::MagFilterNearest;
 299         //        sampler->minFilter = DKTextureSampler::MinFilterNearest;
 300         mesh->SetMaterial(material);
 301         mesh->SetSampler(L"diffuseMap", DKMaterial::TextureArray(texture.SafeCast<DKTexture>(), 1), NULL);
 302         result.mesh = mesh;
 303         result.bvh = bvh;
 304     }
 305     else
 306     {
 307         DKLog("Load %ls failed.\n", (const wchar_t*)obj);
 308     }
 309     return result;
 310 }

- DKGL v1.2 버전용

ObjLoader (last edited 2019-05-03 19:00:30 by Tiff)