Changes between Initial Version and Version 1 of SampleCodes/ObjLoader


Ignore:
Timestamp:
07/03/18 19:59:47 (6 years ago)
Author:
Hongtae Kim
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • SampleCodes/ObjLoader

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