Esempio n. 1
0
void FW::loadObj(ImportState& s, BufferedInputStream& objIn, const String& dirName)
{
    int submesh = -1;
    int defaultSubmesh = -1;

    for (int lineNum = 1;; lineNum++)
    {
        const char* line = objIn.readLine(true, true);
        if (!line || ((lineNum & 0xFF) == 0 && hasError()))
            break;

        const char* ptr = line;
        parseSpace(ptr);
        bool valid = false;

        if (!*ptr || parseLiteral(ptr, "#"))
        {
            valid = true;
        }
        else if (parseLiteral(ptr, "v ") && parseSpace(ptr)) // position vertex
        {
            Vec3f v;
            if (parseFloats(ptr, v.getPtr(), 3) && parseSpace(ptr) && !*ptr)
            {
                s.positions.add(v);
                valid = true;
            }
        }
        else if (parseLiteral(ptr, "vt ") && parseSpace(ptr)) // texture vertex
        {
            Vec2f v;
            if (parseFloats(ptr, v.getPtr(), 2) && parseSpace(ptr))
            {
                F32 dummy;
                while (parseFloat(ptr, dummy) && parseSpace(ptr));

                if (!*ptr)
                {
                    s.texCoords.add(Vec2f(v.x, 1.0f - v.y));
                    valid = true;
                }
            }
        }
        else if (parseLiteral(ptr, "vn ") && parseSpace(ptr)) // normal vertex
        {
            Vec3f v;
            if (parseFloats(ptr, v.getPtr(), 3) && parseSpace(ptr) && !*ptr)
            {
                s.normals.add(v);
                valid = true;
            }
        }
        else if (parseLiteral(ptr, "f ") && parseSpace(ptr)) // face
        {
            s.vertexTmp.clear();
            while (*ptr)
            {
                Vec3i ptn;
                if (!parseInt(ptr, ptn.x))
                    break;
                for (int i = 1; i < 4 && parseLiteral(ptr, "/"); i++)
                {
                    S32 tmp = 0;
                    parseInt(ptr, tmp);
                    if (i < 3)
                        ptn[i] = tmp;
                }
                parseSpace(ptr);

                Vec3i size(s.positions.getSize(), s.texCoords.getSize(), s.normals.getSize());
                for (int i = 0; i < 3; i++)
                {
                    if (ptn[i] < 0)
                        ptn[i] += size[i];
                    else
                        ptn[i]--;

                    if (ptn[i] < 0 || ptn[i] >= size[i])
                        ptn[i] = -1;
                }

                S32* idx = s.vertexHash.search(ptn);
                if (idx)
                    s.vertexTmp.add(*idx);
                else
                {
                    s.vertexTmp.add(s.vertexHash.add(ptn, s.mesh->numVertices()));
                    VertexPNT& v = s.mesh->addVertex();
                v.p = (ptn.x == -1) ? Vec3f(0.0f) : s.positions[ptn.x];
                v.t = (ptn.y == -1) ? Vec2f(0.0f) : s.texCoords[ptn.y];
                v.n = (ptn.z == -1) ? Vec3f(0.0f) : s.normals[ptn.z];
                }
            }
            if (!*ptr)
            {
                if (submesh == -1)
                {
                    if (defaultSubmesh == -1)
                        defaultSubmesh = s.mesh->addSubmesh();
                    submesh = defaultSubmesh;
                }
                for (int i = 2; i < s.vertexTmp.getSize(); i++)
                    s.indexTmp.add(Vec3i(s.vertexTmp[0], s.vertexTmp[i - 1], s.vertexTmp[i]));
                valid = true;
            }
        }
        else if (parseLiteral(ptr, "usemtl ") && parseSpace(ptr)) // material name
        {
            Material* mat = s.materialHash.search(ptr);
            if (submesh != -1)
            {
                s.mesh->mutableIndices(submesh).add(s.indexTmp);
                s.indexTmp.clear();
            submesh = -1;
            }
            if (mat)
            {
                if (mat->submesh == -1)
                {
                    mat->submesh = s.mesh->addSubmesh();
                    s.mesh->material(mat->submesh) = *mat;
                }
                submesh = mat->submesh;
                s.indexTmp.clear();
            }
            valid = true;
        }
        else if (parseLiteral(ptr, "mtllib ") && parseSpace(ptr) && *ptr) // material library
        {
            if (dirName.getLength())
            {
                if (hasError())
                    break;

                String fileName = dirName + "/" + ptr;
                File file(fileName, File::Read);
                BufferedInputStream mtlIn(file);
                loadMtl(s, mtlIn, fileName.getDirName());

#if (!WAVEFRONT_DEBUG)
                clearError();
#endif
            }
            valid = true;
        }
        else if (
            parseLiteral(ptr, "vp ") ||         // parameter space vertex
            parseLiteral(ptr, "deg ") ||        // degree
            parseLiteral(ptr, "bmat ") ||       // basis matrix
            parseLiteral(ptr, "step ") ||       // step size
            parseLiteral(ptr, "cstype ") ||     // curve/surface type
            parseLiteral(ptr, "p ") ||          // point
            parseLiteral(ptr, "l ") ||          // line
            parseLiteral(ptr, "curv ") ||       // curve
            parseLiteral(ptr, "curv2 ") ||      // 2d curve
            parseLiteral(ptr, "surf ") ||       // surface
            parseLiteral(ptr, "parm ") ||       // curve/surface parameters
            parseLiteral(ptr, "trim ") ||       // curve/surface outer trimming loop
            parseLiteral(ptr, "hole ") ||       // curve/surface inner trimming loop
            parseLiteral(ptr, "scrv ") ||       // curve/surface special curve
            parseLiteral(ptr, "sp ") ||         // curve/surface special point
            parseLiteral(ptr, "end ") ||        // curve/surface end statement
            parseLiteral(ptr, "con ") ||        // surface connect
            parseLiteral(ptr, "g ") ||          // group name
            parseLiteral(ptr, "s ") ||          // smoothing group
            parseLiteral(ptr, "mg ") ||         // merging group
            parseLiteral(ptr, "o ") ||          // object name
            parseLiteral(ptr, "bevel ") ||      // bevel interpolation
            parseLiteral(ptr, "c_interp ") ||   // color interpolation
            parseLiteral(ptr, "d_interp ") ||   // dissolve interpolation
            parseLiteral(ptr, "lod ") ||        // level of detail
            parseLiteral(ptr, "shadow_obj ") || // shadow casting
            parseLiteral(ptr, "trace_obj ") ||  // ray tracing
            parseLiteral(ptr, "ctech ") ||      // curve approximation technique
            parseLiteral(ptr, "stech ") ||      // surface approximation technique
            parseLiteral(ptr, "g"))             // ???
        {
            valid = true;
        }

#if WAVEFRONT_DEBUG
        if (!valid)
            setError("Invalid line %d in Wavefront OBJ: '%s'!", lineNum, line);
#endif
    }

    // Flush remaining indices.

    if (submesh != -1)
        s.mesh->mutableIndices(submesh).add(s.indexTmp);
}