예제 #1
0
        public static RenderBase.OModelGroup load(string fileName)
        {
            FileStream data = new FileStream(fileName, FileMode.Open);
            BinaryReader input = new BinaryReader(data);

            RenderBase.OModelGroup models;
            RenderBase.OModel model;

            string extension = Path.GetExtension(fileName).ToLower();
            string bchFile = fileName.Replace(extension, ".bch");
            bool isBCHLoaded = false;
            if (File.Exists(bchFile))
            {
                models = BCH.load(bchFile);
                model = models.model[0];
                models.model.Clear();
                isBCHLoaded = true;
            }
            else
            {
                models = new RenderBase.OModelGroup();
                model = new RenderBase.OModel();
                model.name = "model";
                model.material.Add(new RenderBase.OMaterial());
            }

            ushort format = input.ReadUInt16();
            bool isDataWithinHeader = format == 4;
            input.ReadUInt16(); //-1?
            uint contentFlags = input.ReadUInt32();
            bool hasNameTable = (contentFlags & 2) > 0;
            uint mode = input.ReadUInt32();
            uint meshCount = input.ReadUInt32();

            List<vtxEntry> vtxDescriptors = new List<vtxEntry>();
            List<idxEntry> idxDescriptors = new List<idxEntry>();

            for (int i = 0; i < meshCount; i++)
            {
                if (mode == 1 && i == 0) vtxDescriptors.Add(getVtxDescriptor(input));

                uint facesCount = input.ReadUInt32();
                for (int j = 0; j < facesCount; j++)
                {
                    idxEntry face = new idxEntry();
                    face.meshIndex = i;
                    uint nodesCount = input.ReadUInt32();
                    for (int k = 0; k < nodesCount; k++) face.nodeList.Add(input.ReadUInt32());
                    face.primitiveCount = input.ReadUInt32();
                    if (hasNameTable) face.nameId = input.ReadUInt32();
                    if (isDataWithinHeader)
                    {
                        face.buffer = new ushort[face.primitiveCount];
                        for (int k = 0; k < face.primitiveCount; k++) face.buffer[k] = input.ReadUInt16();
                        alignWord(input);
                    }

                    idxDescriptors.Add(face);
                }

                if (mode == 0)
                {
                    if (isDataWithinHeader)
                    {
                        vtxEntry desc = getVtxDescriptor(input);
                        desc.buffer = new byte[desc.length];
                        input.Read(desc.buffer, 0, desc.buffer.Length);
                        vtxDescriptors.Add(desc);
                        alignWord(input);
                    }
                    else
                        vtxDescriptors.Add(getVtxDescriptor(input));
                }
            }

            List<string> objNameTable = new List<string>();
            
            if (hasNameTable)
            {
                for (int i = 0; i < meshCount; i++)
                {
                    byte index = input.ReadByte();
                    objNameTable.Add(IOUtils.readString(input, (uint)data.Position, true));
                }
            }

            if (!isDataWithinHeader) align(input);
            byte[] vtxBuffer = null;
            vtxEntry currVertex = null;
            int faceIndex = 0;

            for (int i = 0; i < meshCount; i++)
            {
                if (mode == 0 || i == 0)
                {
                    currVertex = vtxDescriptors[i];
                    if (!isDataWithinHeader)
                    {
                        vtxBuffer = new byte[vtxDescriptors[i].length];
                        input.Read(vtxBuffer, 0, vtxBuffer.Length);
                        align(input);
                    }
                    else
                        vtxBuffer = currVertex.buffer;
                }

                RenderBase.OMesh obj;
                if (isBCHLoaded)
                {
                    obj = model.mesh[0];
                    model.mesh.RemoveAt(0);
                }
                else
                {
                    obj = new RenderBase.OMesh();
                    obj.name = "mesh_" + i.ToString();
                }

                for (int j = 0; j < currVertex.attributes.Count; j++)
                {
                    switch (currVertex.attributes[j].type)
                    {
                        case vtxAttributeType.normal: obj.hasNormal = true; break;
                        case vtxAttributeType.color: obj.hasColor = true; break;
                        case vtxAttributeType.textureCoordinate0: obj.texUVCount = 1; break;
                        case vtxAttributeType.textureCoordinate1: obj.texUVCount = 2; break;
                        case vtxAttributeType.boneIndex: obj.hasNode = true; break;
                        case vtxAttributeType.boneWeight: obj.hasWeight = true; break;
                    }
                }

                for (;;)
                {
                    int indexBufferPos = 0;
                    for (int j = 0; j < idxDescriptors[faceIndex].primitiveCount; j++)
                    {
                        ushort index;
                        if (isDataWithinHeader)
                            index = idxDescriptors[faceIndex].buffer[indexBufferPos++];
                        else
                            index = input.ReadUInt16();

                        RenderBase.OVertex vertex = new RenderBase.OVertex();
                        vertex.diffuseColor = 0xffffffff;
                        for (int k = 0; k < currVertex.attributes.Count; k++)
                        {
                            vtxAttribute att = currVertex.attributes[k];
                            int pos = (int)(index * currVertex.stride + att.offset);
                            float scale = att.scale;
                            switch (currVertex.attributes[k].type)
                            {
                                case vtxAttributeType.position: vertex.position = getVector3(vtxBuffer, pos, att.format, scale); break;
                                case vtxAttributeType.normal: vertex.normal = getVector3(vtxBuffer, pos, att.format, scale); break;
                                case vtxAttributeType.color:
                                    RenderBase.OVector4 c = getVector4(vtxBuffer, pos, att.format, scale);
                                    uint r = MeshUtils.saturate(c.x * 0xff);
                                    uint g = MeshUtils.saturate(c.y * 0xff);
                                    uint b = MeshUtils.saturate(c.z * 0xff);
                                    uint a = MeshUtils.saturate(c.w * 0xff);
                                    vertex.diffuseColor = b | (g << 8) | (r << 16) | (a << 24);
                                    break;
                                case vtxAttributeType.textureCoordinate0: vertex.texture0 = getVector2(vtxBuffer, pos, att.format, scale); break;
                                case vtxAttributeType.textureCoordinate1: vertex.texture1 = getVector2(vtxBuffer, pos, att.format, scale); break;
                                case vtxAttributeType.boneIndex:
                                    byte n0 = vtxBuffer[pos];
                                    byte n1 = vtxBuffer[pos + 1];
                                    vertex.node.Add((int)idxDescriptors[faceIndex].nodeList[n0]);
                                    vertex.node.Add((int)idxDescriptors[faceIndex].nodeList[n1]);
                                    break;
                                case vtxAttributeType.boneWeight:
                                    RenderBase.OVector2 w = getVector2(vtxBuffer, pos, att.format, scale);
                                    vertex.weight.Add(w.x);
                                    vertex.weight.Add(w.y);
                                    break;
                            }
                        }

                        MeshUtils.calculateBounds(model, vertex);
                        obj.vertices.Add(vertex);
                    }

                    faceIndex++;
                    if (!isDataWithinHeader) align(input);
                    if (faceIndex >= idxDescriptors.Count) break;
                    if (idxDescriptors[faceIndex].meshIndex == i) continue;
                    break;
                }

                model.mesh.Add(obj);
            }

            models.model.Add(model);

            data.Close();
            return models;
        }
예제 #2
0
        public static RenderBase.OModelGroup load(string fileName)
        {
            FileStream   data  = new FileStream(fileName, FileMode.Open);
            BinaryReader input = new BinaryReader(data);

            RenderBase.OModelGroup models;
            RenderBase.OModel      model;

            string extension   = Path.GetExtension(fileName).ToLower();
            string bchFile     = fileName.Replace(extension, ".bch");
            bool   isBCHLoaded = false;

            if (File.Exists(bchFile))
            {
                models = BCH.load(bchFile);
                model  = models.model[0];
                models.model.Clear();
                isBCHLoaded = true;
            }
            else
            {
                models     = new RenderBase.OModelGroup();
                model      = new RenderBase.OModel();
                model.name = "model";
                model.material.Add(new RenderBase.OMaterial());
            }

            ushort format             = input.ReadUInt16();
            bool   isDataWithinHeader = format == 4;

            input.ReadUInt16(); //-1?
            uint contentFlags = input.ReadUInt32();
            bool hasNameTable = (contentFlags & 2) > 0;
            uint mode         = input.ReadUInt32();
            uint meshCount    = input.ReadUInt32();

            List <vtxEntry> vtxDescriptors = new List <vtxEntry>();
            List <idxEntry> idxDescriptors = new List <idxEntry>();

            for (int i = 0; i < meshCount; i++)
            {
                if (mode == 1 && i == 0)
                {
                    vtxDescriptors.Add(getVtxDescriptor(input));
                }

                uint facesCount = input.ReadUInt32();
                for (int j = 0; j < facesCount; j++)
                {
                    idxEntry face = new idxEntry();
                    face.meshIndex = i;
                    uint nodesCount = input.ReadUInt32();
                    for (int k = 0; k < nodesCount; k++)
                    {
                        face.nodeList.Add(input.ReadUInt32());
                    }
                    face.primitiveCount = input.ReadUInt32();
                    if (hasNameTable)
                    {
                        face.nameId = input.ReadUInt32();
                    }
                    if (isDataWithinHeader)
                    {
                        face.buffer = new ushort[face.primitiveCount];
                        for (int k = 0; k < face.primitiveCount; k++)
                        {
                            face.buffer[k] = input.ReadUInt16();
                        }
                        alignWord(input);
                    }

                    idxDescriptors.Add(face);
                }

                if (mode == 0)
                {
                    if (isDataWithinHeader)
                    {
                        vtxEntry desc = getVtxDescriptor(input);
                        desc.buffer = new byte[desc.length];
                        input.Read(desc.buffer, 0, desc.buffer.Length);
                        vtxDescriptors.Add(desc);
                        alignWord(input);
                    }
                    else
                    {
                        vtxDescriptors.Add(getVtxDescriptor(input));
                    }
                }
            }

            List <string> objNameTable = new List <string>();

            if (hasNameTable)
            {
                for (int i = 0; i < meshCount; i++)
                {
                    byte index = input.ReadByte();
                    objNameTable.Add(IOUtils.readString(input, (uint)data.Position, true));
                }
            }

            if (!isDataWithinHeader)
            {
                align(input);
            }
            byte[]   vtxBuffer  = null;
            vtxEntry currVertex = null;
            int      faceIndex  = 0;

            for (int i = 0; i < meshCount; i++)
            {
                if (mode == 0 || i == 0)
                {
                    currVertex = vtxDescriptors[i];
                    if (!isDataWithinHeader)
                    {
                        vtxBuffer = new byte[vtxDescriptors[i].length];
                        input.Read(vtxBuffer, 0, vtxBuffer.Length);
                        align(input);
                    }
                    else
                    {
                        vtxBuffer = currVertex.buffer;
                    }
                }

                RenderBase.OMesh obj;
                if (isBCHLoaded)
                {
                    obj = model.mesh[0];
                    model.mesh.RemoveAt(0);
                }
                else
                {
                    obj      = new RenderBase.OMesh();
                    obj.name = "mesh_" + i.ToString();
                }

                for (int j = 0; j < currVertex.attributes.Count; j++)
                {
                    switch (currVertex.attributes[j].type)
                    {
                    case vtxAttributeType.normal: obj.hasNormal = true; break;

                    case vtxAttributeType.color: obj.hasColor = true; break;

                    case vtxAttributeType.textureCoordinate0: obj.texUVCount = 1; break;

                    case vtxAttributeType.textureCoordinate1: obj.texUVCount = 2; break;

                    case vtxAttributeType.boneIndex: obj.hasNode = true; break;

                    case vtxAttributeType.boneWeight: obj.hasWeight = true; break;
                    }
                }

                for (;;)
                {
                    int indexBufferPos = 0;
                    for (int j = 0; j < idxDescriptors[faceIndex].primitiveCount; j++)
                    {
                        ushort index;
                        if (isDataWithinHeader)
                        {
                            index = idxDescriptors[faceIndex].buffer[indexBufferPos++];
                        }
                        else
                        {
                            index = input.ReadUInt16();
                        }

                        RenderBase.OVertex vertex = new RenderBase.OVertex();
                        vertex.diffuseColor = 0xffffffff;
                        for (int k = 0; k < currVertex.attributes.Count; k++)
                        {
                            vtxAttribute att   = currVertex.attributes[k];
                            int          pos   = (int)(index * currVertex.stride + att.offset);
                            float        scale = att.scale;
                            switch (currVertex.attributes[k].type)
                            {
                            case vtxAttributeType.position: vertex.position = getVector3(vtxBuffer, pos, att.format, scale); break;

                            case vtxAttributeType.normal: vertex.normal = getVector3(vtxBuffer, pos, att.format, scale); break;

                            case vtxAttributeType.color:
                                RenderBase.OVector4 c = getVector4(vtxBuffer, pos, att.format, scale);
                                uint r = MeshUtils.saturate(c.x * 0xff);
                                uint g = MeshUtils.saturate(c.y * 0xff);
                                uint b = MeshUtils.saturate(c.z * 0xff);
                                uint a = MeshUtils.saturate(c.w * 0xff);
                                vertex.diffuseColor = b | (g << 8) | (r << 16) | (a << 24);
                                break;

                            case vtxAttributeType.textureCoordinate0: vertex.texture0 = getVector2(vtxBuffer, pos, att.format, scale); break;

                            case vtxAttributeType.textureCoordinate1: vertex.texture1 = getVector2(vtxBuffer, pos, att.format, scale); break;

                            case vtxAttributeType.boneIndex:
                                byte n0 = vtxBuffer[pos];
                                byte n1 = vtxBuffer[pos + 1];
                                vertex.node.Add((int)idxDescriptors[faceIndex].nodeList[n0]);
                                vertex.node.Add((int)idxDescriptors[faceIndex].nodeList[n1]);
                                break;

                            case vtxAttributeType.boneWeight:
                                RenderBase.OVector2 w = getVector2(vtxBuffer, pos, att.format, scale);
                                vertex.weight.Add(w.x);
                                vertex.weight.Add(w.y);
                                break;
                            }
                        }

                        MeshUtils.calculateBounds(model, vertex);
                        obj.vertices.Add(vertex);
                    }

                    faceIndex++;
                    if (!isDataWithinHeader)
                    {
                        align(input);
                    }
                    if (faceIndex >= idxDescriptors.Count)
                    {
                        break;
                    }
                    if (idxDescriptors[faceIndex].meshIndex == i)
                    {
                        continue;
                    }
                    break;
                }

                model.mesh.Add(obj);
            }

            models.model.Add(model);

            data.Close();
            return(models);
        }