public CMDLViewer(CGFX Resource, CMDL Model)
 {
     this.Resource = Resource;
     this.Model    = Model;
     InitializeComponent();
     simpleOpenGlControl1.MouseWheel += new MouseEventHandler(simpleOpenGlControl1_MouseWheel);
 }
Exemple #2
0
        public static void N3DS_NW4C_GFX_ToOBJ(String BCMDLPath, int ModelIdx, String OBJPath)
        {
            CGFX c = new CGFX(File.ReadAllBytes(BCMDLPath));

            if (c.Data.Models == null || c.Data.Models.Length <= ModelIdx)
            {
                throw new Exception("Model does not exist in the specified CGFX file!");
            }
            CMDL Model = c.Data.Models[ModelIdx];
            OBJ  o     = Model.ToOBJ();

            o.MTLPath = Path.GetFileNameWithoutExtension(OBJPath) + ".mtl";
            MTL m = Model.ToMTL(Path.GetFileNameWithoutExtension(OBJPath) + "_Tex");

            byte[] d  = o.Write();
            byte[] d2 = m.Write();
            File.Create(OBJPath).Close();
            File.WriteAllBytes(OBJPath, d);
            File.Create(Path.ChangeExtension(OBJPath, "mtl")).Close();
            File.WriteAllBytes(Path.ChangeExtension(OBJPath, "mtl"), d2);
            Directory.CreateDirectory(Path.GetDirectoryName(OBJPath) + "\\" + Path.GetFileNameWithoutExtension(OBJPath) + "_Tex");
            foreach (var v in c.Data.Textures)
            {
                if (!(v is ImageTextureCtr))
                {
                    continue;
                }
                ((ImageTextureCtr)v).GetBitmap().Save(Path.GetDirectoryName(OBJPath) + "\\" + Path.GetFileNameWithoutExtension(OBJPath) + "_Tex\\" + v.Name + ".png");
            }
        }
 public CMDLViewer(CGFX Resource, CMDL Model)
 {
     this.Resource = Resource;
     this.Model = Model;
     InitializeComponent();
     simpleOpenGlControl1.MouseWheel += new MouseEventHandler(simpleOpenGlControl1_MouseWheel);
 }
 public static void N3DS_NW4C_GFX_ToOBJ(String BCMDLPath, int ModelIdx, String OBJPath)
 {
     CGFX c = new CGFX(File.ReadAllBytes(BCMDLPath));
     if (c.Data.Models == null || c.Data.Models.Length <= ModelIdx) throw new Exception("Model does not exist in the specified CGFX file!");
     CMDL Model = c.Data.Models[ModelIdx];
     OBJ o = Model.ToOBJ();
     o.MTLPath = Path.GetFileNameWithoutExtension(OBJPath) + ".mtl";
     MTL m = Model.ToMTL(Path.GetFileNameWithoutExtension(OBJPath) + "_Tex");
     byte[] d = o.Write();
     byte[] d2 = m.Write();
     File.Create(OBJPath).Close();
     File.WriteAllBytes(OBJPath, d);
     File.Create(Path.ChangeExtension(OBJPath, "mtl")).Close();
     File.WriteAllBytes(Path.ChangeExtension(OBJPath, "mtl"), d2);
     Directory.CreateDirectory(Path.GetDirectoryName(OBJPath) + "\\" + Path.GetFileNameWithoutExtension(OBJPath) + "_Tex");
     foreach (var v in c.Data.Textures)
     {
         if (!(v is ImageTextureCtr)) continue;
         ((ImageTextureCtr)v).GetBitmap().Save(Path.GetDirectoryName(OBJPath) + "\\" + Path.GetFileNameWithoutExtension(OBJPath) + "_Tex\\" + v.Name + ".png");
     }
 }
Exemple #5
0
 public CGFXViewer(CGFX mod)
 {
     this.mod = mod;
     InitializeComponent();
     Win32Util.SetWindowTheme(treeView1.Handle, "explorer", null);
     ImageL            = new ImageList();
     ImageL.ColorDepth = ColorDepth.Depth32Bit;
     ImageL.ImageSize  = new Size(16, 16);
     ImageL.Images.Add(Resource.jar);
     ImageL.Images.Add(Resource.point);
     ImageL.Images.Add(Resource.images_stack);
     ImageL.Images.Add(Resource.image_sunset);
     ImageL.Images.Add(Resource.films);
     ImageL.Images.Add(Resource.film);
     ImageL.Images.Add(Resource.tables_stacks);
     ImageL.Images.Add(Resource.table);
     ImageL.Images.Add(Resource.weather_clouds);
     ImageL.Images.Add(Resource.weather_cloud);
     ImageL.Images.Add(Resource.lighthouse_shine);
     ImageL.Images.Add(Resource.light_bulb);
     treeView1.ImageList = ImageL;
 }
 public CGFXViewer(CGFX mod)
 {
     this.mod = mod;
     InitializeComponent();
     Win32Util.SetWindowTheme(treeView1.Handle, "explorer", null);
     ImageL = new ImageList();
     ImageL.ColorDepth = ColorDepth.Depth32Bit;
     ImageL.ImageSize = new Size(16, 16);
     ImageL.Images.Add(Resource.jar);
     ImageL.Images.Add(Resource.point);
     ImageL.Images.Add(Resource.images_stack);
     ImageL.Images.Add(Resource.image_sunset);
     ImageL.Images.Add(Resource.films);
     ImageL.Images.Add(Resource.film);
     ImageL.Images.Add(Resource.tables_stacks);
     ImageL.Images.Add(Resource.table);
     ImageL.Images.Add(Resource.weather_clouds);
     ImageL.Images.Add(Resource.weather_cloud);
     ImageL.Images.Add(Resource.lighthouse_shine);
     ImageL.Images.Add(Resource.light_bulb);
     treeView1.ImageList = ImageL;
 }
        // This REQUIRES a backing CGFX file and doesn't contain enough data to regenerate one from scratch
        public SimplifiedModel(CGFX cgfx)
        {
            this.cgfx = cgfx;

            // Models are always the first entry per CGFX standard
            var models = cgfx.Data.Entries[0]?.Entries;

            // Textures are the second
            var textures = cgfx.Data.Entries[1]?.Entries.Select(e => e.EntryObject).Cast <DICTObjTexture>().ToList();

            if (textures != null && textures.Count > 0)
            {
                Textures = new SMTexture[textures.Count];

                for (var t = 0; t < textures.Count; t++)
                {
                    Bitmap textureBitmap = null;
                    var    name          = textures[t].Name;
                    var    textureData   = textures[t];

                    if (textureData != null)
                    {
                        var textureRGBA = TextureCodec.ConvertTextureToRGBA(new Utility(null, null, Endianness.Little), textureData.TextureCGFXData, textureData.TextureFormat, (int)textureData.Width, (int)textureData.Height);

                        textureBitmap = new Bitmap((int)textureData.Width, (int)textureData.Height, PixelFormat.Format32bppArgb);
                        var imgData = textureBitmap.LockBits(new Rectangle(0, 0, textureBitmap.Width, textureBitmap.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
                        Marshal.Copy(textureRGBA, 0, imgData.Scan0, textureRGBA.Length);
                        textureBitmap.UnlockBits(imgData);
                        textureBitmap.RotateFlip(RotateFlipType.RotateNoneFlipY);
                    }

                    var smTexture = new SMTexture(name, textureBitmap);
                    Textures[t] = smTexture;
                }
            }

            if (models != null && models.Count > 0)
            {
                // This probably isn't a difficult problem to work around, but it's out of my scope at this time
                if (models.Count != 1)
                {
                    throw new InvalidOperationException("File contains more than one model; only supporting one for now.");
                }

                var model = (DICTObjModel)models.First().EntryObject;

                // NOTE: Currently NOT committing the skeleton back, we're just keeping it for model software
                var bones = model.Skeleton?.Bones.Entries.Select(e => e.EntryObject).Cast <DICTObjBone>().ToList() ?? new List <DICTObjBone>();

                Bones = bones.Select(b => new SMBone
                {
                    Name           = b.Name,
                    ParentName     = b.Parent?.Name,
                    Rotation       = b.Rotation,
                    Translation    = b.Translation,
                    Scale          = b.Scale,
                    LocalTransform = b.LocalTransform
                }).ToArray();

                Meshes = new SMMesh[model.Meshes.Length];

                for (var m = 0; m < model.Meshes.Length; m++)
                {
                    var mesh  = model.Meshes[m];
                    var shape = model.Shapes[mesh.ShapeIndex];

                    // There might be some clever way of handling multiple vertex buffers
                    // (if it actually happens) but I'm not worried about it. Only looking
                    // for a single one that is VertexBufferInterleaved.
                    var vertexBuffersInterleaved = shape.VertexBuffers.Where(vb => vb is VertexBufferInterleaved);
                    if (vertexBuffersInterleaved.Count() != 1)
                    {
                        throw new InvalidOperationException("Unsupported count of VertexBuffers in VertexBufferInterleaved format");
                    }

                    // Only expecting / supporting 1 SubMesh entry
                    if (shape.SubMeshes.Count != 1)
                    {
                        throw new InvalidOperationException("Unsupported amount of SubMeshes");
                    }

                    var subMesh = shape.SubMeshes[0];

                    // The BoneReferences in the SubMesh are what the vertex's local index references.
                    var boneReferences = subMesh.BoneReferences;

                    // These aren't "faces" in the geometrical sense, but rather a header of sorts
                    if (subMesh.Faces.Count != 1)
                    {
                        throw new InvalidOperationException("Unsupported amount of Faces");
                    }

                    var faceHeader = subMesh.Faces[0];

                    // Again, just one FaceDescriptor...
                    if (faceHeader.FaceDescriptors.Count != 1)
                    {
                        throw new InvalidOperationException("Unsupported amount of FaceDescriptors");
                    }

                    var faceDescriptor = faceHeader.FaceDescriptors[0];

                    // We're also only supporting triangles at this point; the model format probably
                    // allows for more groups of geometry, but again, out of my scope
                    if (faceDescriptor.PrimitiveMode != FaceDescriptor.PICAPrimitiveMode.Triangles)
                    {
                        throw new InvalidOperationException("Only supporting triangles format");
                    }

                    // Vertices are stored (in GPU-compatible form)
                    var vertexBuffer      = (VertexBufferInterleaved)vertexBuffersInterleaved.Single();
                    var vertexBufferIndex = shape.VertexBuffers.IndexOf(vertexBuffer);
                    var attributes        = vertexBuffer.Attributes.Select(a => VertexBufferCodec.PICAAttribute.GetPICAAttribute(a)).ToList();

                    // The following are the only VertexAttributes we are supporting at this time
                    var supportedAttributes = new List <VertexBuffer.PICAAttributeName>
                    {
                        VertexBuffer.PICAAttributeName.Position,
                        VertexBuffer.PICAAttributeName.Normal,
                        VertexBuffer.PICAAttributeName.TexCoord0,
                        VertexBuffer.PICAAttributeName.BoneIndex,
                        VertexBuffer.PICAAttributeName.BoneWeight,

                        // Caution: Vertex color may not be supported by all model editors!
                        VertexBuffer.PICAAttributeName.Color
                    };

                    // Check if any unsupported attributes are in use
                    var unsupportedAttributes = attributes.Where(a => !supportedAttributes.Contains(a.Name)).Select(a => a.Name);
                    if (unsupportedAttributes.Any())
                    {
                        throw new InvalidOperationException($"This model is using the following unsupported attributes: {string.Join(", ", unsupportedAttributes)}");
                    }

                    var nativeVertices = VertexBufferCodec.GetVertices(shape, vertexBufferIndex);

                    // Convert to the simplified vertices
                    var boneIndexCount  = GetElementsOfAttribute(attributes, VertexBuffer.PICAAttributeName.BoneIndex);  // How many bone indices are actually used
                    var boneWeightCount = GetElementsOfAttribute(attributes, VertexBuffer.PICAAttributeName.BoneWeight); // How many bone weights are actually used

                    // FIXME? There seems to be, on occasion, a bone relationship that points to
                    // the entire mesh but not assigned to any of the vertices. So basically the
                    // vertices are recorded as having no bone indices but in fact are all dependent
                    // upon associating with bone index 0 (?) This will force it to use at least
                    // one bone index even if zero is specified for this case.
                    if (boneReferences != null && boneReferences.Count > 0)
                    {
                        boneIndexCount = Math.Max(boneIndexCount, 1);
                    }

                    var vertices = nativeVertices.Select(v => new SMVertex
                    {
                        Position    = new Vector3(v.Position.X, v.Position.Y, v.Position.Z),
                        Normal      = new Vector3(v.Normal.X, v.Normal.Y, v.Normal.Z),
                        TexCoord    = new Vector3(v.TexCoord0.X, v.TexCoord0.Y, v.TexCoord0.Z),
                        BoneIndices = (new[] { v.Indices.b0, v.Indices.b1, v.Indices.b2, v.Indices.b3 }).Take(boneIndexCount).ToArray(),
                        Weights     = (new[] { v.Weights.w0, v.Weights.w1, v.Weights.w2, v.Weights.w3 }).Take(boneWeightCount).ToArray(),
                        Color       = v.Color // Caution! Not all 3D model editors may support vertex color!
                    }).ToList();

                    // The vertices use relative bone indices based on the SubMesh definitions,
                    // which we're going to make absolute now
                    for (var v = 0; v < vertices.Count; v++)
                    {
                        var vertex = vertices[v];

                        for (var i = 0; i < vertex.BoneIndices.Length; i++)
                        {
                            vertex.BoneIndices[i] = boneReferences[vertex.BoneIndices[i]].Index;

                            // Also, if no bone weights are available, assign a weight of 1 to the first bone.
                            // This won't be stored ultimately as the PICA attributes won't specify it.
                            if (vertex.Weights.Length == 0)
                            {
                                vertex.Weights = new float[] { 1.0f };
                            }
                        }
                    }

                    // Deconstruct into triangle faces
                    var triangles = new List <SMTriangle>();
                    var indices   = faceDescriptor.Indices;
                    for (var i = 0; i < indices.Count; i += 3)
                    {
                        triangles.Add(new SMTriangle
                        {
                            v1 = indices[i + 0],
                            v2 = indices[i + 1],
                            v3 = indices[i + 2]
                        });
                    }

                    // Finally, assign material, if available (mostly for the model editor's benefit)
                    var material  = model.ModelMaterials.Entries.Select(e => e.EntryObject).Cast <DICTObjModelMaterial>().ToList()[mesh.MaterialId];
                    var texture   = material.TextureMappers.First().TextureReference;
                    var name      = texture.ReferenceName;
                    var smTexture = (Textures != null) ? Textures.Where(t => t.Name == name).SingleOrDefault() : null;
                    if (smTexture == null)
                    {
                        smTexture = new SMTexture(name, null);
                    }

                    Meshes[m] = new SMMesh(vertices, triangles, shape, vertexBufferIndex, smTexture);
                }
            }
        }
        public static file load(Stream data)
        {
            //Too small
            if (data.Length < 0x10)
            {
                data.Close();
                return(new file {
                    type = formatType.unsupported
                });
            }

            BinaryReader input = new BinaryReader(data);
            uint         magic, length;

            switch (peek(input))
            {
            case 0x00010000: return(new file {
                    data = GfModel.load(data), type = formatType.model
                });

            case 0x00060000: return(new file {
                    data = GfMotion.loadAnim(input), type = formatType.anims
                });

            case 0x15041213: return(new file {
                    data = GfTexture.load(data), type = formatType.image
                });

            case 0x15122117:
                RenderBase.OModelGroup mdls = new RenderBase.OModelGroup();
                mdls.model.Add(GfModel.loadModel(data));
                return(new file {
                    data = mdls, type = formatType.model
                });
            }

            switch (getMagic(input, 5))
            {
            case "MODEL": return(new file {
                    data = DQVIIPack.load(data), type = formatType.container
                });
            }

            switch (getMagic(input, 4))
            {
            case "CGFX": return(new file {
                    data = CGFX.load(data), type = formatType.model
                });

            case "CRAG": return(new file {
                    data = GARC.load(data), type = formatType.container
                });

            case "darc": return(new file {
                    data = DARC.load(data), type = formatType.container
                });

            case "FPT0": return(new file {
                    data = FPT0.load(data), type = formatType.container
                });

            case "IECP":
                magic  = input.ReadUInt32();
                length = input.ReadUInt32();
                return(load(new MemoryStream(LZSS.decompress(data, length))));

            case "NLK2":
                data.Seek(0x80, SeekOrigin.Begin);
                return(new file
                {
                    data = CGFX.load(data),
                    type = formatType.model
                });

            case "SARC": return(new file {
                    data = SARC.load(data), type = formatType.container
                });

            case "SMES": return(new file {
                    data = NLP.loadMesh(data), type = formatType.model
                });

            case "Yaz0":
                magic  = input.ReadUInt32();
                length = IOUtils.endianSwap(input.ReadUInt32());
                data.Seek(8, SeekOrigin.Current);
                return(load(new MemoryStream(Yaz0.decompress(data, length))));

            case "zmdl": return(new file {
                    data = ZMDL.load(data), type = formatType.model
                });

            case "ztex": return(new file {
                    data = ZTEX.load(data), type = formatType.texture
                });
            }

            //Check if is a BCLIM or BFLIM file (header on the end)
            if (data.Length > 0x28)
            {
                data.Seek(-0x28, SeekOrigin.End);
                string clim = IOUtils.readStringWithLength(input, 4);
                if (clim == "CLIM" || clim == "FLIM")
                {
                    return new file {
                               data = BCLIM.load(data), type = formatType.image
                    }
                }
                ;
            }

            switch (getMagic(input, 3))
            {
            case "BCH":
                byte[] buffer = new byte[data.Length];
                input.Read(buffer, 0, buffer.Length);
                data.Close();
                return(new file
                {
                    data = BCH.load(new MemoryStream(buffer)),
                    type = formatType.model
                });

            case "DMP": return(new file {
                    data = DMP.load(data), type = formatType.image
                });
            }

            string magic2b = getMagic(input, 2);

            switch (magic2b)
            {
            case "AD": return(new file {
                    data = AD.load(data), type = formatType.model
                });

            case "BM": return(new file {
                    data = MM.load(data), type = formatType.model
                });

            case "BS": return(new file {
                    data = BS.load(data), type = formatType.anims
                });

            case "CM": return(new file {
                    data = CM.load(data), type = formatType.model
                });

            case "CP": return(new file {
                    data = CP.load(data), type = formatType.model
                });

            case "GR": return(new file {
                    data = GR.load(data), type = formatType.model
                });

            case "MM": return(new file {
                    data = MM.load(data), type = formatType.model
                });

            case "PC": return(new file {
                    data = PC.load(data), type = formatType.model
                });

            case "PT": return(new file {
                    data = PT.load(data), type = formatType.texture
                });
            }

            if (magic2b.Length == 2)
            {
                if ((magic2b[0] >= 'A' && magic2b[0] <= 'Z') &&
                    (magic2b[1] >= 'A' && magic2b[1] <= 'Z'))
                {
                    return(new file {
                        data = PkmnContainer.load(data), type = formatType.container
                    });
                }
            }

            //Compressions
            data.Seek(0, SeekOrigin.Begin);
            uint cmp = input.ReadUInt32();

            if ((cmp & 0xff) == 0x13)
            {
                cmp = input.ReadUInt32();
            }
            switch (cmp & 0xff)
            {
            case 0x11: return(load(new MemoryStream(LZSS_Ninty.decompress(data, cmp >> 8))));

            case 0x90:
                byte[] buffer  = BLZ.decompress(data);
                byte[] newData = new byte[buffer.Length - 1];
                Buffer.BlockCopy(buffer, 1, newData, 0, newData.Length);
                return(load(new MemoryStream(newData)));
            }

            data.Close();
            return(new file {
                type = formatType.unsupported
            });
        }
Exemple #9
0
        /// <summary>
        ///     Reads the Model PACKage from Dragon Quest VII.
        /// </summary>
        /// <param name="data">Stream of the data</param>
        /// <returns></returns>
        public static OContainer load(Stream data)
        {
            BinaryReader input  = new BinaryReader(data);
            OContainer   output = new OContainer();

            List <sectionEntry> mainSection = getSection(input);

            //World nodes section
            data.Seek(mainSection[0].offset, SeekOrigin.Begin);
            List <node>         nodes             = new List <node>();
            List <sectionEntry> worldNodesSection = getSection(input);

            foreach (sectionEntry entry in worldNodesSection)
            {
                data.Seek(entry.offset, SeekOrigin.Begin);

                node n = new node();

                //Geometry node
                input.ReadUInt32(); //GNOD magic number
                input.ReadUInt32();
                input.ReadUInt32();
                n.parentId = input.ReadInt32();
                n.name     = IOUtils.readString(input, (uint)data.Position);

                data.Seek(entry.offset + 0x20, SeekOrigin.Begin);
                n.transform = new RenderBase.OMatrix();
                RenderBase.OVector4 t = new RenderBase.OVector4(input.ReadSingle(), input.ReadSingle(), input.ReadSingle(), input.ReadSingle());
                RenderBase.OVector4 r = new RenderBase.OVector4(input.ReadSingle(), input.ReadSingle(), input.ReadSingle(), input.ReadSingle());
                RenderBase.OVector4 s = new RenderBase.OVector4(input.ReadSingle(), input.ReadSingle(), input.ReadSingle(), input.ReadSingle());
                n.transform *= RenderBase.OMatrix.scale(new RenderBase.OVector3(s.x, s.y, s.z));
                n.transform *= RenderBase.OMatrix.rotateX(r.x);
                n.transform *= RenderBase.OMatrix.rotateY(r.y);
                n.transform *= RenderBase.OMatrix.rotateZ(r.z);
                n.transform *= RenderBase.OMatrix.translate(new RenderBase.OVector3(t.x, t.y, t.z));

                nodes.Add(n);
            }

            RenderBase.OMatrix[] nodesTransform = new RenderBase.OMatrix[nodes.Count];
            for (int i = 0; i < nodes.Count; i++)
            {
                RenderBase.OMatrix transform = new RenderBase.OMatrix();
                transformNode(nodes, i, ref transform);
                nodesTransform[i] = transform;
            }

            //Models section
            data.Seek(mainSection[1].offset, SeekOrigin.Begin);
            List <sectionEntry> modelsSection = getSection(input);

            foreach (sectionEntry entry in modelsSection)
            {
                data.Seek(entry.offset, SeekOrigin.Begin);

                //Field Data section

                /*
                 * Usually have 3 entries.
                 * 1st entry: Model CGFX
                 * 2nd entry: Unknow CGFX, possibly animations
                 * 3rd entry: Another FieldData section, possibly child object
                 */

                List <sectionEntry> fieldDataSection = getSection(input);
                data.Seek(fieldDataSection[0].offset, SeekOrigin.Begin);
                uint length = fieldDataSection[0].length;
                while ((length & 0x7f) != 0)
                {
                    length++;                          //Align
                }
                byte[] buffer = new byte[length];
                input.Read(buffer, 0, buffer.Length);

                OContainer.fileEntry file = new OContainer.fileEntry();
                file.name = CGFX.getName(new MemoryStream(buffer)) + ".bcmdl";
                file.data = buffer;

                output.content.Add(file);
            }

            //FILE section
            data.Seek(mainSection[2].offset, SeekOrigin.Begin);
            //TODO

            //Collision section
            data.Seek(mainSection[3].offset, SeekOrigin.Begin);
            //TODO

            //PARM(???) section
            data.Seek(mainSection[4].offset, SeekOrigin.Begin);
            //TODO

            //Textures CGFX
            data.Seek(mainSection[5].offset, SeekOrigin.Begin);
            byte[] texBuffer = new byte[mainSection[5].length];
            input.Read(texBuffer, 0, texBuffer.Length);

            OContainer.fileEntry texFile = new OContainer.fileEntry();
            texFile.name = "textures.bctex";
            texFile.data = texBuffer;

            output.content.Add(texFile);

            data.Close();

            return(output);
        }
 public CGFXViewer(CGFX cgfx)
 {
     this.cgfx = cgfx;
     InitializeComponent();
     simpleOpenGlControl1.MouseWheel += new MouseEventHandler(simpleOpenGlControl1_MouseWheel);
 }
Exemple #11
0
        private void FrmObjImport_Load(object sender, EventArgs e)
        {
            OpenFileDialog opn = new OpenFileDialog();

            opn.Title  = "Open a model file";
            opn.Filter = "Supported formats (.bcmdl, .obj)|*.bcmdl; *.obj";
            bool ok = true;

            if (opn.ShowDialog() != DialogResult.OK)
            {
                ok = false;
            }
            if (Path.GetExtension(opn.FileName).ToLower() == ".obj")
            {
                if (MessageBox.Show("The obj will be converted to bcmdl with Every File Explorer's method, this is known to have problems, especially with models made in sketchup.\r\nDo you want to continue ?", "Warning", MessageBoxButtons.YesNo) == DialogResult.Yes)
                {
                    modelPath    = opn.FileName;
                    ObjModelPath = modelPath;
                    IsObj        = true;
                    render.addModel(modelPath, "Model", new System.Windows.Media.Media3D.Vector3D(0, 0, 0), new System.Windows.Media.Media3D.Vector3D(1, 1, 1), 0, 0, 0);
                }
                else
                {
                    MessageBox.Show("You can convert the model to bcmdl with the leaked tools");
                    this.Close();
                }
            }
            else if (Path.GetExtension(opn.FileName).ToLower() == ".bcmdl")
            {
                tmpPath = Path.GetTempPath() + "TmpT4D";
                string Name = tmpPath + "\\model.obj";
                Directory.CreateDirectory(tmpPath);
                CGFX mod = null;
                mod = new _3DS.NintendoWare.GFX.CGFX(File.ReadAllBytes(opn.FileName));
                CommonFiles.OBJ o = mod.Data.Models[0].ToOBJ();
                o.MTLPath = Path.GetFileNameWithoutExtension(Name) + ".mtl";
                MTL    m  = mod.Data.Models[0].ToMTL("Tex");
                byte[] d  = o.Write();
                byte[] d2 = m.Write();
                File.Create(Name).Close();
                File.WriteAllBytes(Name, d);
                File.Create(Path.ChangeExtension(Name, "mtl")).Close();
                File.WriteAllBytes(Path.ChangeExtension(Name, "mtl"), d2);
                Directory.CreateDirectory(tmpPath + "\\Tex");
                foreach (var v in mod.Data.Textures)
                {
                    if (!(v is ImageTextureCtr))
                    {
                        continue;
                    }
                    ((ImageTextureCtr)v).GetBitmap().Save(tmpPath + "\\Tex\\" + v.Name + ".png");
                }
                modelPath    = opn.FileName;
                ObjModelPath = Name;
                IsObj        = false;
                render.addModel(Name, "Model", new System.Windows.Media.Media3D.Vector3D(0, 0, 0), new System.Windows.Media.Media3D.Vector3D(1, 1, 1), 0, 0, 0);
                textBox1.Text    = mod.Data.Models[0].Name;
                textBox1.Enabled = false;
                render.SetSortFrequency(0);
            }
            else
            {
                if (ok)
                {
                    MessageBox.Show("File not supported");
                }
                else
                {
                    MessageBox.Show("You must select your model file to use this function");
                }
                this.Close();
            }
        }
Exemple #12
0
        private void button1_Click(object sender, EventArgs e)
        {
            if (!File.Exists(PaPath))
            {
                MessageBox.Show("Pa file not found !"); return;
            }
            if (!File.Exists(KclPath))
            {
                MessageBox.Show("kcl file not found !"); return;
            }
            if (!File.Exists(modelPath))
            {
                MessageBox.Show("Model file not found !"); return;
            }
            SaveFileDialog s = new SaveFileDialog();

            s.Filter   = "Szs files|*.szs";
            s.FileName = textBox1.Text;
            if (s.ShowDialog() != DialogResult.OK)
            {
                return;
            }
            CommonCompressors.YAZ0   y       = new CommonCompressors.YAZ0();
            NDS.NitroSystem.FND.NARC SzsArch = new NDS.NitroSystem.FND.NARC();
            SFSDirectory             dir     = new SFSDirectory("", true);

            //Model
            SFSFile Model = new SFSFile(0, textBox1.Text + ".bcmdl", dir);

            if (IsObj)
            {
                CGFX mod = null;
                mod = new CGFX();
                CGFXGenerator.FromOBJ(mod, modelPath, textBox1.Text);
                Model.Data = mod.Write();
            }
            else
            {
                Model.Data = File.ReadAllBytes(modelPath);
            }
            dir.Files.Add(Model);
            //Collisions
            SFSFile KclFile = new SFSFile(1, textBox1.Text + ".kcl", dir);

            KclFile.Data = File.ReadAllBytes(KclPath);
            dir.Files.Add(KclFile);
            SFSFile PaFile = new SFSFile(2, textBox1.Text + ".pa", dir);

            PaFile.Data = File.ReadAllBytes(PaPath);
            dir.Files.Add(PaFile);
            //InitSensor
            SFSFile Sensor = new SFSFile(3, "InitSensor.byml", dir);

            Sensor.Data = BymlConverter.GetByml(Properties.Resources.Sensor);
            dir.Files.Add(Sensor);
            //InitActor
            SFSFile Actor = new SFSFile(4, "InitActor.byml", dir);

            Actor.Data = BymlConverter.GetByml(Properties.Resources.Actor);
            dir.Files.Add(Actor);
            //InitClipping
            string  clip     = "<?xml version=\"1.0\" encoding=\"shift_jis\"?>\r\n<Root>\r\n  <isBigEndian Value=\"False\" />\r\n  <BymlFormatVersion Value=\"1\" />\r\n  <C1>\r\n    <D2 Name=\"Radius\" StringValue=\"" + numericUpDown1.Value.ToString() + "\" />\r\n  </C1>\r\n</Root>";
            SFSFile Clipping = new SFSFile(5, "InitClipping.byml", dir);

            Clipping.Data = BymlConverter.GetByml(clip);
            dir.Files.Add(Clipping);

            SzsArch.FromFileSystem(dir);
            File.WriteAllBytes(s.FileName, y.Compress(SzsArch.Write()));
            MessageBox.Show("Done !");
            MessageBox.Show("Remember you need to add the object to the CreatorClassNameTable to use the object in-game (Other modding -> CreatorClassNameTable editor)");
            MessageBox.Show("To view the model in the editor you must copy it in the models folder with the name " + textBox1.Text + ".obj or else you will see a blue box");
            this.Close();
        }
Exemple #13
0
        private static void ExportImportCGX(OperationInfo opInfo, string[] args)
        {
            // The base, input, and output files
            var baseFile = args[1];
            var inFile   = args[args.Length == 4 ? 2 : 1];
            var outFile  = args[args.Length == 4 ? 3 : 2];

            var inFileExt  = Path.GetExtension(inFile).ToLower();
            var outFileExt = Path.GetExtension(outFile).ToLower();

            // As we must have a BCRES for "backing", it will be loaded either way
            // before we do anything else.
            CGFX            cgfxBase;
            SimplifiedModel simplifiedModel;

            using (var br = new BinaryReader(File.Open(baseFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)))
            {
                // Load the BCRES (CGFX)
                cgfxBase = CGFX.Load(br);

                // Create a "SimplifiedModel" out of the base CGFX
                simplifiedModel = new SimplifiedModel(cgfxBase);
            }

            try
            {
                Console.WriteLine($"Converting {inFile} to {outFile}...");

                // If we're converting FROM a BCRES TO another file type...
                if (opInfo.Operation == Operations.ExportFromCGFX)
                {
                    // Convert it and save it to the requested file type
                    using (var bw = new BinaryWriter(File.Open(outFile, FileMode.Create)))
                    {
                        if (outFileExt == ".ms3d")
                        {
                            var milkShape = MilkShapeConverter.ToMilkShape(simplifiedModel);
                            milkShape.Save(bw);
                        }
                        else
                        {
                            throw new NotImplementedException($"Unsupported Destination filetype {outFileExt}");
                        }
                    }

                    // Dump textures
                    if (simplifiedModel.Textures != null)
                    {
                        var dumpTextureDir = Path.GetDirectoryName(outFile);
                        foreach (var texture in simplifiedModel.Textures)
                        {
                            Console.WriteLine($"Exporting texture {texture.Name}...");
                            texture.TextureBitmap.Save(Path.Combine(dumpTextureDir, texture.Name + ".png"));
                        }
                    }

                    Console.WriteLine();
                    Console.WriteLine("Done.");
                    Console.WriteLine();
                    Console.WriteLine("Note, if there are any textures you do NOT want to modify, you can delete the respective PNG files");
                    Console.WriteLine("and they'll be skipped on import.");
                    Console.WriteLine();
                    Console.WriteLine();
                }
                else
                {
                    // Converting from a model file TO a BCRES...

                    if (baseFile == outFile)
                    {
                        // The only reason I'm actually blocking this is lack of trust in that if
                        // there's a bug that causes data loss, it may compound over subsequent
                        // writes. So until I trust this code more, we'll force an "unmodified" base
                        // to be used. (Of course, I can't KNOW the base is "unmodified"...)
                        throw new InvalidOperationException("Currently writing to the base BCRES/CGFX file is prohibited. May lift this restriction in the future.");
                    }

                    using (var br = new BinaryReader(File.Open(inFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)))
                        using (var bw = new BinaryWriter(File.Open(outFile, FileMode.Create)))
                        {
                            if (inFileExt == ".ms3d")
                            {
                                var milkShape = MilkShape.Load(br);
                                MilkShapeConverter.FromMilkShape(simplifiedModel, milkShape);
                            }
                            else
                            {
                                throw new NotImplementedException($"Unsupported Source filetype {inFileExt}");
                            }

                            // Import textures
                            var dumpTextureDir = Path.GetDirectoryName(inFile);

                            // Find WHAT textures we have (user has option to not include any or all)
                            if (simplifiedModel.Textures != null)
                            {
                                var importTextures = simplifiedModel.Textures
                                                     .Select(t => new
                                {
                                    Filename = Path.Combine(dumpTextureDir, t.Name + ".png"),
                                    Texture  = t
                                })
                                                     .Where(t => File.Exists(t.Filename))
                                                     .Select(t => new
                                {
                                    t.Texture.Name,
                                    TextureBitmap = Image.FromFile(t.Filename)
                                })
                                                     .ToList();

                                foreach (var texture in importTextures)
                                {
                                    Console.WriteLine($"Importing texture {texture.Name}...");

                                    // Corresponding texture in SimplifiedModel
                                    var smTexture = simplifiedModel.Textures.Where(t => t.Name == texture.Name).Single();
                                    smTexture.TextureBitmap = (Bitmap)texture.TextureBitmap;
                                }
                            }

                            simplifiedModel.RecomputeVertexNormals();
                            simplifiedModel.ApplyChanges();
                            cgfxBase.Save(bw);
                        }


                    Console.WriteLine();
                    Console.WriteLine("Done.");
                    Console.WriteLine();
                }
            }
            catch
            {
                if (File.Exists(outFile))
                {
                    File.Delete(outFile);
                }

                throw;
            }
        }
Exemple #14
0
        public DAE ToDAE(CGFX Resource)
        {
            var m = this;
            var o = new DAE();
            o.Content.scene = new DAE.COLLADA._scene();
            o.Content.scene.instance_visual_scene = new DAE.InstanceWithExtra();
            o.Content.scene.instance_visual_scene.url = "#ID1";
            o.Content.library_visual_scenes = new DAE.library_visual_scenes();
            var scene = new DAE.visual_scene("ID1");
            var rootnode = new DAE.node(m.Name);
            scene.node.Add(rootnode);
            o.Content.library_visual_scenes.visual_scene.Add(scene);
            o.Content.library_geometries = new DAE.library_geometries();
            o.Content.library_materials = new DAE.library_materials();
            o.Content.library_effects = new DAE.library_effects();
            if (Resource.Data.Textures != null && Resource.Data.Textures.Length > 0) o.Content.library_images = new DAE.library_images();
            int id = 2;
            int i = 0;
            foreach (var matt in m.Materials)
            {
                var mat2 = new DAE.material();
                mat2.id = "ID" + id++;
                mat2.name = matt.Name;
                var eff = new DAE.effect();
                eff.id = "ID" + id++;
                mat2.instance_effect = new DAE.instance_effect();
                mat2.instance_effect.url = "#" + eff.id;
                eff.profile_COMMON = new DAE.profile_COMMON();
                eff.profile_COMMON.technique = new DAE.profile_COMMON._technique();
                eff.profile_COMMON.technique.sid = "COMMON";
                eff.profile_COMMON.technique.lambert = new DAE.profile_COMMON._technique._lambert();
                eff.profile_COMMON.technique.lambert.diffuse = new DAE.common_color_or_texture_type();
                if (matt.Tex0 != null && matt.Tex0.TextureObject is ReferenceTexture)
                {
                    string texid = "ID" + id++;
                    o.Content.library_images.image.Add(new DAE.image() { id = texid, init_from = "Tex/" + ((ReferenceTexture)matt.Tex0.TextureObject).LinkedTextureName + ".png" });

                    var param1 = new DAE.common_newparam_type() { sid = "ID" + id++, choice = new DAE.fx_surface_common() { type = DAE.fx_surface_type_enum._2D } };
                    ((DAE.fx_surface_common)param1.choice).init_from.Add(new DAE.fx_surface_init_from_common() { content = texid });
                    eff.profile_COMMON.newparam = new List<DAE.common_newparam_type>();
                    eff.profile_COMMON.newparam.Add(param1);
                    eff.profile_COMMON.newparam.Add(new DAE.common_newparam_type() { sid = "ID" + id++, choice = new DAE.fx_sampler2D_common() { source = param1.sid } });
                    eff.profile_COMMON.technique.lambert.diffuse.texture = new DAE.common_color_or_texture_type._texture() { texture = eff.profile_COMMON.newparam[1].sid, texcoord = "UVSET0" };
                }
                else
                {
                    eff.profile_COMMON.technique.lambert.diffuse.color = new DAE.common_color_or_texture_type._color();
                    eff.profile_COMMON.technique.lambert.diffuse.color.content = Color.White;
                }
                o.Content.library_materials.material.Add(mat2);
                o.Content.library_effects.effect.Add(eff);
            }

            int ff = 0;
            //foreach (CMDL m in Models)
            {
                foreach (var vv in m.Shapes)
                {
                    var geometry = new DAE.geometry();
                    geometry.id = "ID" + id++;

                    Polygon p = vv.GetVertexData(m);
                    var mat = m.Materials[m.Meshes[ff].MaterialIndex];

                    geometry.mesh = new DAE.mesh();
                    geometry.mesh.vertices = new DAE.vertices() { id = "ID" + id++ };
                    if (p.Vertex != null)
                    {
                        var src = new DAE.source() { id = "ID" + id++ };
                        src.float_array = new DAE.source._float_array() { id = "ID" + id++, count = (uint)p.Vertex.Length * 3 };
                        foreach (var v in p.Vertex)
                        {
                            src.float_array.content.Add(v.X);
                            src.float_array.content.Add(v.Y);
                            src.float_array.content.Add(v.Z);
                        }
                        src.technique_common = new DAE.source._technique_common();
                        src.technique_common.accessor = new DAE.accessor();
                        src.technique_common.accessor.count = (uint)p.Vertex.Length;
                        src.technique_common.accessor.source = "#" + src.float_array.id;
                        src.technique_common.accessor.stride = 3;
                        src.technique_common.accessor.param.Add(new DAE.param() { name = "X", type = "float" });
                        src.technique_common.accessor.param.Add(new DAE.param() { name = "Y", type = "float" });
                        src.technique_common.accessor.param.Add(new DAE.param() { name = "Z", type = "float" });
                        geometry.mesh.source.Add(src);
                        geometry.mesh.vertices.input.Add(new DAE.InputLocal() { semantic = "POSITION", source = "#" + src.id });
                    }
                    if (p.Normals != null)
                    {
                        var src = new DAE.source() { id = "ID" + id++ };
                        src.float_array = new DAE.source._float_array() { id = "ID" + id++, count = (uint)p.Normals.Length * 3 };
                        foreach (var v in p.Normals)
                        {
                            src.float_array.content.Add(v.X);
                            src.float_array.content.Add(v.Y);
                            src.float_array.content.Add(v.Z);
                        }
                        src.technique_common = new DAE.source._technique_common();
                        src.technique_common.accessor = new DAE.accessor();
                        src.technique_common.accessor.count = (uint)p.Normals.Length;
                        src.technique_common.accessor.source = "#" + src.float_array.id;
                        src.technique_common.accessor.stride = 3;
                        src.technique_common.accessor.param.Add(new DAE.param() { name = "X", type = "float" });
                        src.technique_common.accessor.param.Add(new DAE.param() { name = "Y", type = "float" });
                        src.technique_common.accessor.param.Add(new DAE.param() { name = "Z", type = "float" });
                        geometry.mesh.source.Add(src);
                        geometry.mesh.vertices.input.Add(new DAE.InputLocal() { semantic = "NORMAL", source = "#" + src.id });
                    }
                    DAE.source texcoordsrc = null;
                    if (p.TexCoords != null)
                    {
                        if (mat.NrActiveTextureCoordiators > 0 && mat.TextureCoordiators[0].MappingMethod == 0)
                        {
                            Vector2[] texc;
                            if (mat.TextureCoordiators[0].SourceCoordinate == 0)
                            {
                                texc = p.TexCoords.ToArray();
                            }
                            else if (mat.TextureCoordiators[0].SourceCoordinate == 1)
                            {
                                texc = p.TexCoords2.ToArray();
                            }
                            else
                            {
                                texc = p.TexCoords3.ToArray();
                            }

                            var src = texcoordsrc = new DAE.source() { id = "ID" + id++ };
                            src.float_array = new DAE.source._float_array() { id = "ID" + id++, count = (uint)texc.Length * 2 };
                            foreach (var v in texc)
                            {
                                Vector2 result = v * new Matrix34(mat.TextureCoordiators[0].Matrix);
                                src.float_array.content.Add(result.X);
                                src.float_array.content.Add(result.Y);
                            }
                            src.technique_common = new DAE.source._technique_common();
                            src.technique_common.accessor = new DAE.accessor();
                            src.technique_common.accessor.count = (uint)p.TexCoords.Length;
                            src.technique_common.accessor.source = "#" + src.float_array.id;
                            src.technique_common.accessor.stride = 2;
                            src.technique_common.accessor.param.Add(new DAE.param() { name = "S", type = "float" });
                            src.technique_common.accessor.param.Add(new DAE.param() { name = "T", type = "float" });
                            geometry.mesh.source.Add(src);
                        }
                    }
                    DAE.source colorsrc = null;
                    if (p.Colors != null)
                    {
                        var src = colorsrc = new DAE.source() { id = "ID" + id++ };
                        src.float_array = new DAE.source._float_array() { id = "ID" + id++, count = (uint)p.Colors.Length * 4 };
                        foreach (var v in p.Colors)
                        {
                            src.float_array.content.Add(v.R / 255f);
                            src.float_array.content.Add(v.G / 255f);
                            src.float_array.content.Add(v.B / 255f);
                            src.float_array.content.Add(v.A / 255f);
                        }
                        src.technique_common = new DAE.source._technique_common();
                        src.technique_common.accessor = new DAE.accessor();
                        src.technique_common.accessor.count = (uint)p.Colors.Length;
                        src.technique_common.accessor.source = "#" + src.float_array.id;
                        src.technique_common.accessor.stride = 4;
                        src.technique_common.accessor.param.Add(new DAE.param() { name = "R", type = "float" });
                        src.technique_common.accessor.param.Add(new DAE.param() { name = "G", type = "float" });
                        src.technique_common.accessor.param.Add(new DAE.param() { name = "B", type = "float" });
                        src.technique_common.accessor.param.Add(new DAE.param() { name = "A", type = "float" });
                        geometry.mesh.source.Add(src);
                    }

                    foreach (var q in vv.PrimitiveSets[0].Primitives[0].IndexStreams)
                    {
                        Vector3[] defs = q.GetFaceData();

                        var tri = new DAE.triangles() { count = (uint)defs.Length, material = mat.Name };
                        uint offs = 0;
                        tri.input.Add(new DAE.InputLocalOffset() { offset = offs++, semantic = "VERTEX", source = "#" + geometry.mesh.vertices.id });
                        if (texcoordsrc != null) tri.input.Add(new DAE.InputLocalOffset() { offset = offs++, semantic = "TEXCOORD", source = "#" + texcoordsrc.id });
                        if (colorsrc != null) tri.input.Add(new DAE.InputLocalOffset() { offset = offs++, semantic = "COLOR", source = "#" + colorsrc.id, set = 0 });
                        tri.p.Add(new DAE.p());
                        foreach (Vector3 d in defs)
                        {
                            tri.p[0].content.Add((ulong)d.X);
                            if (texcoordsrc != null) tri.p[0].content.Add((ulong)d.X);
                            if (colorsrc != null) tri.p[0].content.Add((ulong)d.X);
                            tri.p[0].content.Add((ulong)d.Y);
                            if (texcoordsrc != null) tri.p[0].content.Add((ulong)d.Y);
                            if (colorsrc != null) tri.p[0].content.Add((ulong)d.Y);
                            tri.p[0].content.Add((ulong)d.Z);
                            if (texcoordsrc != null) tri.p[0].content.Add((ulong)d.Z);
                            if (colorsrc != null) tri.p[0].content.Add((ulong)d.Z);
                        }
                        geometry.mesh.triangles.Add(tri);
                    }
                    o.Content.library_geometries.geometry.Add(geometry);
                    var instgem = new DAE.instance_geometry() { url = "#" + geometry.id };
                    instgem.bind_material = new DAE.bind_material();
                    instgem.bind_material.technique_common = new DAE.bind_material._technique_common();
                    var instmat = new DAE.instance_material();
                    instmat.symbol = mat.Name;
                    instmat.target = "#" + o.Content.library_materials.material[(int)m.Meshes[ff].MaterialIndex].id;
                    instmat.bind_vertex_input.Add(new DAE.instance_material._bind_vertex_input() { semantic = "UVSET0", input_semantic = "TEXCOORD", input_set = 0 });
                    instgem.bind_material.technique_common.instance_material.Add(instmat);
                    rootnode.instance_geometry.Add(instgem);
                    ff++;
                }
            }
            return o;
        }
 public static void FromOBJ(CGFX c, String OBJPath, String ModelName = "EFEModel")
 {
     OBJ Model = new OBJ(File.ReadAllBytes(OBJPath));
     if (Model.MTLPath == null) throw new Exception("Model without materials not supported!");
     String MtlPath = Path.GetDirectoryName(OBJPath) + "\\" + Model.MTLPath;
     MTL MatLib = new MTL(File.ReadAllBytes(MtlPath));
     List<String> MatNames = new List<string>();
     foreach (var f in Model.Faces)
     {
         if (!MatNames.Contains(f.Material)) MatNames.Add(f.Material);
     }
     Bitmap[] Textures = new Bitmap[MatLib.Materials.Count];
     int q = 0;
     int NrTextures = 0;
     foreach (var v in MatLib.Materials)
     {
         if (!MatNames.Contains(v.Name)) { q++; continue; }
         if (v.DiffuseMapPath != null)
         {
             Textures[q] = new Bitmap(new MemoryStream(File.ReadAllBytes(Path.GetDirectoryName(MtlPath) + "\\" + v.DiffuseMapPath)));
             NrTextures++;
         }
         q++;
     }
     c.Data.Dictionaries[0] = new DICT();
     c.Data.Dictionaries[0].Add(ModelName);
     c.Data.Models = new CMDL[1];
     c.Data.Models[0] = new CMDL(ModelName);
     CMDL cmdl = c.Data.Models[0];
     //Mesh Node Visibility
     {
         cmdl.NrMeshNodes = 1;
         cmdl.MeshNodeVisibilitiesDict = new DICT();
         cmdl.MeshNodeVisibilitiesDict.Add("CompleteModel");
         cmdl.MeshNodeVisibilities = new CMDL.MeshNodeVisibilityCtr[] { new CMDL.MeshNodeVisibilityCtr("CompleteModel") };
     }
     //Meshes
     {
         cmdl.NrMeshes = (uint)MatNames.Count;
         cmdl.Meshes = new CMDL.Mesh[MatNames.Count];
         for (int i = 0; i < MatNames.Count; i++)
         {
             cmdl.Meshes[i] = new CMDL.Mesh();
             cmdl.Meshes[i].MeshNodeName = "CompleteModel";
             cmdl.Meshes[i].MaterialIndex = (uint)i;
             cmdl.Meshes[i].ShapeIndex = (uint)i;
         }
     }
     //Materials
     {
         cmdl.NrMaterials = (uint)MatNames.Count;
         cmdl.MaterialsDict = new DICT();
         cmdl.Materials = new CMDL.MTOB[MatNames.Count];
         for (int i = 0; i < MatNames.Count; i++)
         {
             cmdl.MaterialsDict.Add(MatNames[i]);
             cmdl.Materials[i] = new CMDL.MTOB(MatNames[i]);
             cmdl.Materials[i].FragShader.TextureCombiners[0].SrcRgb = 0xEE0;
             cmdl.Materials[i].FragShader.TextureCombiners[0].SrcAlpha = 0xEE0;
             for (int qq = 1; qq < 6; qq++)
             {
                 cmdl.Materials[i].FragShader.TextureCombiners[qq].SrcRgb = 0xEEF;
                 cmdl.Materials[i].FragShader.TextureCombiners[qq].SrcAlpha = 0xEEF;
             }
             Bitmap tex = Textures[MatLib.Materials.IndexOf(MatLib.GetMaterialByName(MatNames[i]))];
             if (tex != null)
             {
                 cmdl.Materials[i].NrActiveTextureCoordiators = 1;
                 cmdl.Materials[i].TextureCoordiators[0].Scale = new LibEveryFileExplorer.Collections.Vector2(1, 1);
                 cmdl.Materials[i].Tex0 = new CMDL.MTOB.TexInfo(MatNames[i]);
                 cmdl.Materials[i].FragShader.TextureCombiners[0].SrcRgb = 0xE30;
                 cmdl.Materials[i].FragShader.TextureCombiners[0].SrcAlpha = 0xE30;
                 cmdl.Materials[i].FragShader.TextureCombiners[0].CombineRgb = 1;
                 cmdl.Materials[i].FragShader.TextureCombiners[0].CombineAlpha = 1;
             }
         }
     }
     //Shapes
     {
         cmdl.NrShapes = (uint)MatNames.Count;
         cmdl.Shapes = new CMDL.SeparateDataShape[MatNames.Count];
         for (int i = 0; i < MatNames.Count; i++)
         {
             cmdl.Shapes[i] = new CMDL.SeparateDataShape();
             Vector3 min = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue);
             Vector3 max = new Vector3(float.MinValue, float.MinValue, float.MinValue);
             int nrfaces = 0;
             bool texcoords = false;
             foreach (var f in Model.Faces)
             {
                 if (f.Material != MatNames[i]) continue;
                 nrfaces++;
                 if (f.TexCoordIndieces.Count > 0) texcoords = true;
                 foreach (var qqq in f.VertexIndieces)
                 {
                     if (Model.Vertices[qqq].X < min.X) min.X = Model.Vertices[qqq].X;
                     if (Model.Vertices[qqq].Y < min.Y) min.Y = Model.Vertices[qqq].Y;
                     if (Model.Vertices[qqq].Z < min.Z) min.Z = Model.Vertices[qqq].Z;
                     if (Model.Vertices[qqq].X > max.X) max.X = Model.Vertices[qqq].X;
                     if (Model.Vertices[qqq].Y > max.Y) max.Y = Model.Vertices[qqq].Y;
                     if (Model.Vertices[qqq].Z > max.Z) max.Z = Model.Vertices[qqq].Z;
                 }
             }
             ((OrientedBoundingBox)cmdl.Shapes[i].BoundingBox).CenterPosition = (min + max) / 2;
             ((OrientedBoundingBox)cmdl.Shapes[i].BoundingBox).Size = max - min;
             cmdl.Shapes[i].NrPrimitiveSets = 1;
             cmdl.Shapes[i].PrimitiveSets = new CMDL.SeparateDataShape.PrimitiveSet[1];
             cmdl.Shapes[i].PrimitiveSets[0] = new CMDL.SeparateDataShape.PrimitiveSet();
             cmdl.Shapes[i].PrimitiveSets[0].NrPrimitives = 1;
             cmdl.Shapes[i].PrimitiveSets[0].Primitives = new CMDL.SeparateDataShape.PrimitiveSet.Primitive[1];
             cmdl.Shapes[i].PrimitiveSets[0].Primitives[0] = new CMDL.SeparateDataShape.PrimitiveSet.Primitive();
             cmdl.Shapes[i].PrimitiveSets[0].Primitives[0].NrBufferObjects = 1;
             cmdl.Shapes[i].PrimitiveSets[0].Primitives[0].BufferObjects = new uint[] { 0 };
             cmdl.Shapes[i].PrimitiveSets[0].Primitives[0].NrIndexStreams = 1;
             cmdl.Shapes[i].PrimitiveSets[0].Primitives[0].IndexStreams = new CMDL.SeparateDataShape.PrimitiveSet.Primitive.IndexStreamCtr[1];
             cmdl.Shapes[i].PrimitiveSets[0].Primitives[0].IndexStreams[0] = new CMDL.SeparateDataShape.PrimitiveSet.Primitive.IndexStreamCtr();
             if (nrfaces * 3 > 255) cmdl.Shapes[i].PrimitiveSets[0].Primitives[0].IndexStreams[0].FormatType = 0x1403;
             cmdl.Shapes[i].PrimitiveSets[0].Primitives[0].IndexStreams[0].FaceDataLength = (uint)(nrfaces * 3 * ((nrfaces * 3 > 255) ? 2 : 1));
             cmdl.Shapes[i].PrimitiveSets[0].Primitives[0].IndexStreams[0].FaceData = new byte[cmdl.Shapes[i].PrimitiveSets[0].Primitives[0].IndexStreams[0].FaceDataLength];
             int offs = 0;
             int idx = 0;
             foreach (var f in Model.Faces)
             {
                 if (f.Material != MatNames[i]) continue;
                 if (nrfaces * 3 > 255)
                 {
                     IOUtil.WriteU16LE(cmdl.Shapes[i].PrimitiveSets[0].Primitives[0].IndexStreams[0].FaceData, offs, (ushort)idx);
                     IOUtil.WriteU16LE(cmdl.Shapes[i].PrimitiveSets[0].Primitives[0].IndexStreams[0].FaceData, offs + 2, (ushort)(idx + 1));
                     IOUtil.WriteU16LE(cmdl.Shapes[i].PrimitiveSets[0].Primitives[0].IndexStreams[0].FaceData, offs + 4, (ushort)(idx + 2));
                     offs += 2 * 3;
                 }
                 else
                 {
                     cmdl.Shapes[i].PrimitiveSets[0].Primitives[0].IndexStreams[0].FaceData[idx] = (byte)idx;
                     cmdl.Shapes[i].PrimitiveSets[0].Primitives[0].IndexStreams[0].FaceData[idx + 1] = (byte)(idx + 1);
                     cmdl.Shapes[i].PrimitiveSets[0].Primitives[0].IndexStreams[0].FaceData[idx + 2] = (byte)(idx + 2);
                     offs += 3;
                 }
                 idx += 3;
             }
             cmdl.Shapes[i].NrVertexAttributes = 2;
             cmdl.Shapes[i].VertexAttributes = new CMDL.SeparateDataShape.VertexAttributeCtr[2];
             //interleaved
             cmdl.Shapes[i].VertexAttributes[0] = new CMDL.SeparateDataShape.InterleavedVertexStreamCtr();
             ((CMDL.SeparateDataShape.InterleavedVertexStreamCtr)cmdl.Shapes[i].VertexAttributes[0]).NrVertexStreams = (texcoords ? 2u : 1u);
             ((CMDL.SeparateDataShape.InterleavedVertexStreamCtr)cmdl.Shapes[i].VertexAttributes[0]).VertexStreams = new CMDL.SeparateDataShape.InterleavedVertexStreamCtr.VertexStreamCtr[texcoords ? 2 : 1];
             ((CMDL.SeparateDataShape.InterleavedVertexStreamCtr)cmdl.Shapes[i].VertexAttributes[0]).VertexStreams[0] = new CMDL.SeparateDataShape.InterleavedVertexStreamCtr.VertexStreamCtr(CMDL.SeparateDataShape.VertexAttributeCtr.VertexAttributeUsage.Position, CMDL.SeparateDataShape.DataType.GL_FLOAT, 3, 0);
             if (texcoords) ((CMDL.SeparateDataShape.InterleavedVertexStreamCtr)cmdl.Shapes[i].VertexAttributes[0]).VertexStreams[1] = new CMDL.SeparateDataShape.InterleavedVertexStreamCtr.VertexStreamCtr(CMDL.SeparateDataShape.VertexAttributeCtr.VertexAttributeUsage.TextureCoordinate0, CMDL.SeparateDataShape.DataType.GL_FLOAT, 2, 12);
             ((CMDL.SeparateDataShape.InterleavedVertexStreamCtr)cmdl.Shapes[i].VertexAttributes[0]).VertexDataEntrySize = (texcoords ? 20u : 12u);
             byte[] Result = new byte[nrfaces * 3 * ((CMDL.SeparateDataShape.InterleavedVertexStreamCtr)cmdl.Shapes[i].VertexAttributes[0]).VertexDataEntrySize];
             offs = 0;
             foreach (var f in Model.Faces)
             {
                 if (f.Material != MatNames[i]) continue;
                 for (int qqq = 0; qqq < 3; qqq++)
                 {
                     Vector3 Pos = Model.Vertices[f.VertexIndieces[qqq]];
                     IOUtil.WriteSingleLE(Result, offs, Pos.X);
                     IOUtil.WriteSingleLE(Result, offs + 4, Pos.Y);
                     IOUtil.WriteSingleLE(Result, offs + 8, Pos.Z);
                     offs += 12;
                     if (texcoords)
                     {
                         Vector2 Tex = Model.TexCoords[f.TexCoordIndieces[qqq]];
                         IOUtil.WriteSingleLE(Result, offs, Tex.X);
                         IOUtil.WriteSingleLE(Result, offs + 4, Tex.Y);
                         offs += 8;
                     }
                 }
             }
             ((CMDL.SeparateDataShape.InterleavedVertexStreamCtr)cmdl.Shapes[i].VertexAttributes[0]).VertexStreamLength = (uint)Result.Length;
             ((CMDL.SeparateDataShape.InterleavedVertexStreamCtr)cmdl.Shapes[i].VertexAttributes[0]).VertexStream = Result;
             //color
             cmdl.Shapes[i].VertexAttributes[1] = new CMDL.SeparateDataShape.VertexParamAttributeCtr(CMDL.SeparateDataShape.VertexAttributeCtr.VertexAttributeUsage.Color, 1, 1, 1, MatLib.GetMaterialByName(MatNames[i]).Alpha);
         }
     }
     if (NrTextures != 0)
     {
         c.Data.Dictionaries[1] = new DICT();
         c.Data.Textures = new TXOB[NrTextures];
         int qqq = 0;
         int idx = 0;
         foreach (Bitmap b in Textures)
         {
             if (b == null) { qqq++; continue; }
             c.Data.Dictionaries[1].Add(MatLib.Materials[qqq].Name);
             c.Data.Textures[idx] = new ImageTextureCtr(MatLib.Materials[qqq].Name, b, GPU.Textures.ImageFormat.ETC1A4);
             idx++;
             qqq++;
         }
     }
 }
 public CGFXViewer(CGFX cgfx)
 {
     this.cgfx = cgfx;
     InitializeComponent();
     simpleOpenGlControl1.MouseWheel += new MouseEventHandler(simpleOpenGlControl1_MouseWheel);
 }