示例#1
0
        private BlendChunk findChunkByPtr(long ptr)
        {
            if (ptr == 0)
            {
                return(null);
            }
            BlendChunk chunk = chunks.Get(ptr);

            if (chunk == null)
            {
                return(null);
            }
            if (chunk.dup)
            {
//            Console.WriteLine("Duplicate:" + Long.toString(ptr, 16) + ",idx=" + chunk.dupidx);
                int cnt = chunk.dupidx;
                chunk.dupidx++;
                for (int a = 0; a < cnt; a++)
                {
                    chunk = chunk.nextdup;
                }
            }
            return(chunk);
        }
示例#2
0
        private void readLayer(long layers, String name)
        {
            if (layers == 0)
            {
                return;
            }
//        Console.WriteLine(name + ".layers=" + Long.toString(layers, 16));
            BlendChunk raw = findChunkByPtr(layers);

            if (raw == null)
            {
                throw new Exception("GL_BLEND:Unable to find " + name + ".layers for Mesh");
            }
            setData(raw.raw);
//        Console.WriteLine("#layers=" + raw.nr);
            for (int a = 0; a < raw.nr; a++)
            {
                BlendCustomDataLayer layer = new BlendCustomDataLayer(this);
                layer.read();
                String layer_name = layer.name;
                if (layer.data == 0)
                {
//                Console.WriteLine("layer.data == null");
                    continue;
                }
                BlendChunk layer_data = findChunkByPtr(layer.data);
                if (layer_data == null)
                {
                    throw new Exception("GL_BLEND:Unable to find " + name + ".layers.data for Mesh");
                }
                BlendContext ctx = pushData();
                setData(layer_data.raw);
//            Console.WriteLine("layer.data=" + Long.toString(layer.data, 16) + ",type==" + layer.type + ",a=" + a);
                switch (layer.type)
                {
                case CD_MTEXPOLY: {    //15
                    //NOTE:There fis a MTexPoly per face, I only read the first
                    BlendMTexPoly tex = new BlendMTexPoly(this);
                    tex.read();
                    BlendChunk imageChunk = findChunkByPtr(tex.tpage);
                    if (imageChunk == null)
                    {
                        throw new Exception("GL_BLEND:No texture found for UVMap:" + a);
                    }
                    setData(imageChunk.raw);
                    BlendImage image = new BlendImage(this);
                    image.read();
                    OpenGLUVMap map;
                    if (a < obj.GetUVMapCount())
                    {
                        map = obj.GetUVMap(a);
                    }
                    else
                    {
                        map = obj.CreateUVMap();
                    }
                    String tn = image.name;
                    //string texture path for now
                    int tnidx = tn.LastIndexOf('/');
                    if (tnidx != -1)
                    {
                        tn = tn.Substring(tnidx + 1);
                    }
                    tnidx = tn.LastIndexOf('\\');
                    if (tnidx != -1)
                    {
                        tn = tn.Substring(tnidx + 1);
                    }
                    int tidx = model.AddTexture(tn);
                    map.SetTextureIndex(tidx);
                    map.SetName(layer_name);
//                    Console.WriteLine("texpoly=" + map.name);
                    break;
                }

                case CD_MLOOPUV: { //16
                    //There fis a UV per face per vertex
                    if (a >= obj.GetUVMapCount())
                    {
                        obj.CreateUVMap();
                    }
//                    Console.WriteLine("loopuv.nr=" + layer_data.nr);
                    for (int b = 0; b < layer_data.nr; b++)
                    {
                        BlendMLoopUV uv = new BlendMLoopUV(this);
                        uv.read();
                        uv.uv[1] = 1.0f - uv.uv[1];    //invert V(y)
                        obj.AddUV(uv.uv, a);
                    }
                    break;
                }
                }
                popData(ctx);
            }
        }
示例#3
0
        private void readObject(BlendChunk chunk)
        {
            List <BlendVertex> vertexList = new List <BlendVertex>();
            List <int>         loopList   = new List <int>();

            setData(chunk.raw);
            BlendObject bObj = new BlendObject(this);

            bObj.read();
//                Console.WriteLine("bobject.type=" + bObj.type);
            if (bObj.type != 1)
            {
                return;                //not a mesh bobject (could be camera, light, etc.)
            }
            obj = new OpenGLObject();
            model.AddObject(obj);
            obj.SetName(bObj.id.name.Substring(2));
//        Console.WriteLine("bobject=" + obj.name);
            chunk = findChunkByPtr(bObj.data);
            if (chunk == null)
            {
                throw new Exception("GL_BLEND:Unable to find Mesh for Object");
            }
            BlendMesh mesh = new BlendMesh(this);

            setData(chunk.raw);
//                Console.WriteLine("Mesh@" + Int32.toString(raw.fileOffset, 16));
            mesh.read();
            obj.GetOrigin().x = bObj.loc[0];
            org[0] = bObj.loc[0];
            obj.GetOrigin().y = bObj.loc[1];
            org[1] = bObj.loc[1];
            obj.GetOrigin().z = bObj.loc[2];
            org[2] = bObj.loc[2];
            //find mvert
            chunk = findChunkByPtr(mesh.mvert);
            if (chunk == null)
            {
                throw new Exception("GL_BLEND:Unable to find MVert for Mesh");
            }
            setData(chunk.raw);
            for (int a = 0; a < chunk.nr; a++)
            {
                BlendMVert mvert = new BlendMVert(this);
                mvert.read();
//                    obj.AddVertex(mvert.co);
                BlendVertex v = new BlendVertex();
                v.xyz = mvert.v;
                vertexList.Add(v);
            }
            //find mloop
            chunk = findChunkByPtr(mesh.mloop);
            if (chunk == null)
            {
                throw new Exception("GL_BLEND:Unable to find MLoop for Mesh");
            }
            setData(chunk.raw);
            for (int a = 0; a < chunk.nr; a++)
            {
                BlendMLoop mloop = new BlendMLoop(this);
                mloop.read();
                loopList.Add(mloop.v);
            }
            //find mloopuv

/*    //use the UVMaps _in the CustomData instead - this fis only the active one
 *      raw = findChunkByPtr(mesh.mloopuv);
 *      if (raw == null) {
 *          throw new Exception("GL_BLEND:Unable to find MLoopUV for Mesh");
 *      }
 *      setData(raw.raw);
 *      Console.WriteLine("MLoopUV:nr=" + raw.nr);
 *      for(int a=0;a<raw.nr;a++) {
 *          MLoopUV mloopuv = new MLoopUV();
 *          mloopuv.read();
 *      }
 */
            //find mpoly
            chunk = findChunkByPtr(mesh.mpoly);
            if (chunk == null)
            {
                throw new Exception("GL_BLEND:Unable to find MPoly for Mesh");
            }
            setData(chunk.raw);
//TODO : calc which vertex needed to be dup'ed for each unique uv value (Blender does this _in their 3ds export script)
            int type = -1;
            int pcnt = -1;
            int vidx = 0;

            //MPoly = faces
            for (int a = 0; a < chunk.nr; a++)
            {
                BlendMPoly mpoly = new BlendMPoly(this);
                mpoly.read();
                switch (mpoly.totloop)
                {
                case 3:
                    if (type == GL_QUADS)
                    {
                        throw new Exception("GL_BLEND:Mixed QUADS/TRIANGLES not supported");
                    }
                    type = GL_TRIANGLES;
                    pcnt = 3;
                    break;

                case 4:
                    if (type == GL_TRIANGLES)
                    {
                        throw new Exception("GL_BLEND:Mixed QUADS/TRIANGLES not supported");
                    }
                    type = GL_QUADS;
                    pcnt = 4;
                    break;

                default:
                    throw new Exception("GL_BLEND:Polygon not supported:nr=" + mpoly.totloop);
                }
                int loopidx = mpoly.loopstart;
                for (int p = 0; p < pcnt; p++)
                {
                    int idx = loopList.Get(loopidx++);
                    obj.AddVertex(vertexList.Get(idx).xyz);
                    obj.AddPoly(new int[] { vidx++ });
                }
            }
            obj.SetType(type);
            //find customdata types
            readLayer(mesh.vdata.layers, "vdata");
            readLayer(mesh.edata.layers, "edata");
            readLayer(mesh.fdata.layers, "fdata");
            readLayer(mesh.pdata.layers, "pdata");
            readLayer(mesh.ldata.layers, "ldata");
        }
示例#4
0
        private OpenGLModel loadBlend(IOStream fis)
        {
            setData(fis.ReadAll().ToArray());

            if (data.Length < 12)
            {
                throw new Exception("GL_BLEND:File too small");
            }

            model = new OpenGLModel();

            //load signature (12 bytes) "BLENDER_V100"
            if (!new String(data, 0, 7).Equals("BLENDER"))
            {
                throw new Exception("Not a blender file");
            }
            switch ((char)data[7])
            {
            case '-': x64 = true; break;

            case '_': x64 = false; break;

            default:
                throw new Exception("GL_BLEND:Unknown bit size");
            }

            switch ((char)data[8])
            {
            case 'v': le = true; break;

            case 'V': le = false; break;

            default:
                throw new Exception("GL_BLEND:Unknown Endianness");
            }

            String version = new String(data, 9, 3);
//        Console.WriteLine("Blender file version:" + version);
            int ver = Int32.ValueOf(version);

            if (ver < 263)
            {
                throw new Exception("Error:Blender file too old, can not read.");
            }

            datapos = 12; //skip main header

            //first phase - read raw chunks
            while (!eof())
            {
                BlendChunk chunk = new BlendChunk(this);
                chunk.filepos = datapos;
                chunk.read();
                BlendChunk ochunk = chunks.Get(chunk.ptr);
                if (ochunk != null)
                {
                    if (!haveDups)
                    {
                        Console.WriteLine("Warning:This file contains duplicate BHeads.");
                        haveDups = true;
                    }
                    ochunk.dup = true;
                    while (ochunk.nextdup != null)
                    {
                        ochunk = ochunk.nextdup;
                    }
                    ochunk.nextdup = chunk;
                }
                else
                {
                    chunks.Set(chunk.ptr, chunk);
                }
            }

            int chunkCnt = chunks.Size();

            BlendChunk[] chunkArray = chunks.Values();
            BlendChunk   raw;

            //2nd phase - parse DNA chunk
            for (int i = 0; i < chunkCnt; i++)
            {
                if (chunkArray[i].id == ID_DNA1)
                {
                    raw = chunkArray[i];
                    setData(raw.raw);
                    //SDNA
                    String SDNA = readString(4);
                    if (!SDNA.Equals("SDNA"))
                    {
                        throw new Exception("Bad DNA Struct:SDNA");
                    }
                    //NAME
                    String NAME = readString(4);
                    if (!NAME.Equals("NAME"))
                    {
                        throw new Exception("Bad DNA Struct:NAME");
                    }
                    int nr_names = readuint32();
                    for (int a = 0; a < nr_names; a++)
                    {
                        String str = readString();
//                    Console.WriteLine("name=" + str);
                        names.Add(str);
                    }
                    //align pointer
                    datapos += 3;
                    datapos &= 0x7ffffffc;
                    //TYPE
                    String TYPE = readString(4);
                    if (!TYPE.Equals("TYPE"))
                    {
                        throw new Exception("Bad DNA Struct:TYPE");
                    }
                    int nr_types = readuint32();
                    for (int a = 0; a < nr_types; a++)
                    {
                        String str = readString();
//                    Console.WriteLine("type=" + str);
                        types.Add(str);
                    }
                    //align pointer
                    datapos += 3;
                    datapos &= 0x7ffffffc;
                    //TLEN
                    String TLEN = readString(4);
                    if (!TLEN.Equals("TLEN"))
                    {
                        throw new Exception("Bad DNA Struct:TLEN");
                    }
                    for (int a = 0; a < nr_types; a++)
                    {
                        typelen.Add(readuint16());
                    }
                    //align pointer
                    datapos += 3;
                    datapos &= 0x7ffffffc;
                    //STRC
                    String STRC = readString(4);
                    if (!STRC.Equals("STRC"))
                    {
                        throw new Exception("Bad DNA Struct:STRC");
                    }
                    int nr_structs = readuint32();
                    for (int a = 0; a < nr_structs; a++)
                    {
                        BlendStruct s = new BlendStruct();
                        s.typeidx = readuint16();
                        s.nr      = readuint16();
                        s.name    = types.Get(s.typeidx);
//                    Console.WriteLine("Struct:" + s.name + "==" + a);
                        for (int b = 0; b < s.nr; b++)
                        {
                            BlendMember m = new BlendMember();
                            m.typelenidx = readuint16();
                            m.nameidx    = readuint16();
                            m.name       = names.Get(m.nameidx);
                            m.typelen    = typelen.Get(m.typelenidx);
                            m.size       = calcMemberSize(m);
//                        Console.WriteLine("    Member:" + m.name + "=" + m.Length);
                            s.members.Add(m);
                        }
                        structs.Add(s);
                    }
                    break;
                }
            }

            //3nd phase - now look for objects and piece together chunks
            for (int i = 0; i < chunkCnt; i++)
            {
                if (chunkArray[i].id == ID_SC)
                {
                    setData(chunkArray[i].raw);
                    BlendScene OpenGLScene = new BlendScene(this);
                    OpenGLScene.read();
                    long ptr = OpenGLScene.last;
                    while (ptr != 0)
                    {
                        BlendChunk chunk = findChunkByPtr(ptr);
                        if (chunk == null)
                        {
                            break;
                        }
                        setData(chunk.raw);
                        BlendBase _base = new BlendBase(this);
                        _base.read();
                        chunk = findChunkByPtr(_base.bobject);
                        if (chunk.id == ID_OB)
                        {
                            readObject(chunk);
                        }
                        ptr = _base.prev;
                    }
                }
            }

            return(model);
        }