BCMDL Generating!

This commit is contained in:
Gericom 2015-01-09 18:41:33 +01:00
parent 32aa0290dd
commit 2ad6438463
11 changed files with 847 additions and 86 deletions

View File

@ -65,6 +65,7 @@
<Compile Include="NintendoWare\GFX\BoundingVolume.cs" />
<Compile Include="NintendoWare\GFX\CANM.cs" />
<Compile Include="NintendoWare\GFX\CGFX.cs" />
<Compile Include="NintendoWare\GFX\CGFXGenerator.cs" />
<Compile Include="NintendoWare\GFX\CGFXShader.cs" />
<Compile Include="NintendoWare\GFX\CGFXWriterContext.cs" />
<Compile Include="NintendoWare\GFX\CMDL.cs" />
@ -106,6 +107,12 @@
<Compile Include="UI\CFNTViewer.Designer.cs">
<DependentUpon>CFNTViewer.cs</DependentUpon>
</Compile>
<Compile Include="UI\CGFXGenDialog.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="UI\CGFXGenDialog.Designer.cs">
<DependentUpon>CGFXGenDialog.cs</DependentUpon>
</Compile>
<Compile Include="UI\CLIMViewer.cs">
<SubType>Form</SubType>
</Compile>
@ -197,6 +204,9 @@
<EmbeddedResource Include="UI\CFNTViewer.resx">
<DependentUpon>CFNTViewer.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="UI\CGFXGenDialog.resx">
<DependentUpon>CGFXGenDialog.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="UI\CLIMViewer.resx">
<DependentUpon>CLIMViewer.cs</DependentUpon>
</EmbeddedResource>

View File

@ -9,6 +9,7 @@ namespace _3DS.NintendoWare.GFX
{
public class BoundingVolume
{
public BoundingVolume() { }
public BoundingVolume(EndianBinaryReader er)
{
Type = er.ReadUInt32();
@ -51,6 +52,15 @@ namespace _3DS.NintendoWare.GFX
public class OrientedBoundingBox : BoundingVolume
{
public OrientedBoundingBox()
: base()
{
Type = 0x80000000;
//All to be set by the user
CenterPosition = new Vector3(0, 0, 0);
OrientationMatrix = new float[] { 1, 0, 0, 0, 1, 0, 0, 0, 1 };
Size = new Vector3(1, 1, 1);
}
public OrientedBoundingBox(EndianBinaryReader er)
: base(er)
{

View File

@ -14,8 +14,14 @@ using LibEveryFileExplorer.Collections;
namespace _3DS.NintendoWare.GFX
{
public class CGFX : FileFormat<CGFX.CGFXIdentifier>, IViewable, IWriteable
public class CGFX : FileFormat<CGFX.CGFXIdentifier>, IFileCreatable, IViewable, IWriteable
{
public CGFX()
{
Header = new CGFXHeader();
Data = new DATA();
}
public CGFX(byte[] Data)
{
EndianBinaryReader er = new EndianBinaryReader(new MemoryStream(Data), Endianness.LittleEndian);
@ -66,9 +72,31 @@ namespace _3DS.NintendoWare.GFX
return result;
}
public bool CreateFromFile()
{
System.Windows.Forms.OpenFileDialog f = new System.Windows.Forms.OpenFileDialog();
f.Filter = OBJ.Identifier.GetFileFilter();
if (f.ShowDialog() == System.Windows.Forms.DialogResult.OK
&& f.FileName.Length > 0)
{
UI.CGFXGenDialog d = new UI.CGFXGenDialog();
d.ShowDialog();
CGFXGenerator.FromOBJ(this, f.FileName, d.ModelName);
return true;
}
return false;
}
public CGFXHeader Header;
public class CGFXHeader
{
public CGFXHeader()
{
Signature = "CGFX";
Endianness = 0xFEFF;
HeaderSize = 0x14;
Version = 0x5000000;
}
public CGFXHeader(EndianBinaryReader er)
{
Signature = er.ReadString(Encoding.ASCII, 4);
@ -98,6 +126,12 @@ namespace _3DS.NintendoWare.GFX
public DATA Data;
public class DATA
{
public DATA()
{
Signature = "DATA";
DictionaryEntries = new DictionaryInfo[16];
Dictionaries = new DICT[16];
}
public DATA(EndianBinaryReader er)
{
Signature = er.ReadString(Encoding.ASCII, 4);

View File

@ -0,0 +1,208 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using CommonFiles;
using System.IO;
using System.Drawing;
using LibEveryFileExplorer.Collections;
using LibEveryFileExplorer.IO;
namespace _3DS.NintendoWare.GFX
{
public class CGFXGenerator
{
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++;
}
}
}
}
}

View File

@ -15,6 +15,21 @@ namespace _3DS.NintendoWare.GFX
{
public class CMDL
{
public CMDL(String Name)
{
Type = 0x40000012;
Signature = "CMDL";
Revision = 0x9000000;
this.Name = Name;
Flags = 1;
IsBranchVisible = true;
Scale = new Vector3(1, 1, 1);
Rotation = new Vector3(0, 0, 0);
Translation = new Vector3(0, 0, 0);
LocalMatrix = new float[] { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0 };
WorldMatrix = new float[] { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0 };
Unknown23 = 1;//unknown what this does...
}
public CMDL(EndianBinaryReader er)
{
Type = er.ReadUInt32();
@ -29,7 +44,8 @@ namespace _3DS.NintendoWare.GFX
NrChildren = er.ReadUInt32();
Unknown7 = er.ReadUInt32();
NrAnimationGroupDescriptions = er.ReadUInt32();
AnimationGroupDescriptionsDictOffset = (UInt32)er.BaseStream.Position + er.ReadUInt32();
AnimationGroupDescriptionsDictOffset =er.ReadUInt32();
if (AnimationGroupDescriptionsDictOffset != 0) AnimationGroupDescriptionsDictOffset += (UInt32)er.BaseStream.Position - 4;
Scale = er.ReadVector3();
Rotation = er.ReadVector3();
Translation = er.ReadVector3();
@ -52,8 +68,11 @@ namespace _3DS.NintendoWare.GFX
long curpos = er.BaseStream.Position;
er.BaseStream.Position = NameOffset;
Name = er.ReadStringNT(Encoding.ASCII);
er.BaseStream.Position = AnimationGroupDescriptionsDictOffset;
AnimationInfoDict = new DICT(er);
if (AnimationGroupDescriptionsDictOffset != 0)
{
er.BaseStream.Position = AnimationGroupDescriptionsDictOffset;
AnimationInfoDict = new DICT(er);
}
er.BaseStream.Position = MeshOffsetsOffset;
MeshOffsets = new UInt32[NrMeshes];
for (int i = 0; i < NrMeshes; i++)
@ -180,16 +199,22 @@ namespace _3DS.NintendoWare.GFX
er.Write(new uint[NrShapes], 0, (int)NrShapes);
long anmgrpdict = er.BaseStream.Position;
er.BaseStream.Position = anmgrpdescdictoffs;
er.Write((uint)(anmgrpdict - anmgrpdescdictoffs));
er.BaseStream.Position = anmgrpdict;
AnimationInfoDict.Write(er, c);
if (NrAnimationGroupDescriptions != 0 && AnimationInfoDict != null)
{
er.BaseStream.Position = anmgrpdescdictoffs;
er.Write((uint)(anmgrpdict - anmgrpdescdictoffs));
er.BaseStream.Position = anmgrpdict;
AnimationInfoDict.Write(er, c);
}
long matdict = er.BaseStream.Position;
er.BaseStream.Position = matdictoffs;
er.Write((uint)(matdict - matdictoffs));
er.BaseStream.Position = matdict;
MaterialsDict.Write(er, c);
if (NrMaterials != 0 && MaterialsDict != null)
{
er.BaseStream.Position = matdictoffs;
er.Write((uint)(matdict - matdictoffs));
er.BaseStream.Position = matdict;
MaterialsDict.Write(er, c);
}
long mshnoddict = er.BaseStream.Position;
if (NrMeshNodes != 0 && MeshNodeVisibilitiesDict != null)
@ -703,6 +728,11 @@ namespace _3DS.NintendoWare.GFX
public MeshNodeVisibilityCtr[] MeshNodeVisibilities;
public class MeshNodeVisibilityCtr
{
public MeshNodeVisibilityCtr(String Name)
{
this.Name = Name;
Visible = true;
}
public MeshNodeVisibilityCtr(EndianBinaryReader er)
{
NameOffset = (uint)er.BaseStream.Position + er.ReadUInt32();
@ -743,6 +773,24 @@ namespace _3DS.NintendoWare.GFX
ParticleMaterialEnabled = 32
}
public MTOB(String Name)
{
Type = 0x8000000;
Signature = "MTOB";
Revision = 0x6000003;
this.Name = Name;
MaterialColor = new MaterialColorCtr();
Rasterization = new RasterizationCtr();
FragmentOperation = new FragmentOperationCtr();
NrActiveTextureCoordiators = 0;
TextureCoordiators = new TextureCoordinatorCtr[3];
TextureCoordiators[0] = new TextureCoordinatorCtr();
TextureCoordiators[1] = new TextureCoordinatorCtr();
TextureCoordiators[2] = new TextureCoordinatorCtr();
Shader = new SHDR();
FragShader = new FragmentShader();
}
public MTOB(EndianBinaryReader er)
{
Type = er.ReadUInt32();
@ -1064,6 +1112,32 @@ namespace _3DS.NintendoWare.GFX
public class MaterialColorCtr
{
public MaterialColorCtr()
{
Emission = new Vector4(0, 0, 0, 0);
EmissionU32 = Color.FromArgb(0);
Ambient = new Vector4(1, 1, 1, 1);
AmbientU32 = Color.White;
Diffuse = new Vector4(1, 1, 1, 1);
DiffuseU32 = Color.White;
Specular0 = new Vector4(0.33f, 0.33f, 0.33f, 0);
Specular0U32 = Color.FromArgb(0, 84, 84, 84);
Specular1 = new Vector4(0, 0, 0, 0);
Specular1U32 = Color.FromArgb(0);
Constant0 = new Vector4(0, 0, 0, 0);
Constant0U32 = Color.FromArgb(0);
Constant1 = new Vector4(0, 0, 0, 0);
Constant1U32 = Color.FromArgb(0);
Constant2 = new Vector4(0, 0, 0, 0);
Constant2U32 = Color.FromArgb(0);
Constant3 = new Vector4(0, 0, 0, 0);
Constant3U32 = Color.FromArgb(0);
Constant4 = new Vector4(0, 0, 0, 0);
Constant4U32 = Color.FromArgb(0);
Constant5 = new Vector4(0, 0, 0, 0);
Constant5U32 = Color.FromArgb(0);
CommandCache = 0;
}
public MaterialColorCtr(EndianBinaryReader er)
{
Emission = er.ReadVector4();
@ -1182,6 +1256,14 @@ namespace _3DS.NintendoWare.GFX
{
PolygonOffsetEnabled = 1
}
public RasterizationCtr()
{
Flags = 0;
CullingMode = 3;
PolygonOffsetUnit = 0;
Command1 = 0;
Command2 = 0x00010040;
}
public RasterizationCtr(EndianBinaryReader er)
{
Flags = (RasterizationFlags)er.ReadUInt32();
@ -1216,6 +1298,12 @@ namespace _3DS.NintendoWare.GFX
public class FragmentOperationCtr
{
public FragmentOperationCtr()
{
DepthOperation = new DepthOperationCtr();
BlendOperation = new BlendOperationCtr();
StencilOperation = new StencilOperationCtr();
}
public FragmentOperationCtr(EndianBinaryReader er)
{
DepthOperation = new DepthOperationCtr(er);
@ -1301,6 +1389,14 @@ namespace _3DS.NintendoWare.GFX
TestEnabled = 1,
MaskEnabled = 2
}
public DepthOperationCtr()
{
Flags = DepthFlags.TestEnabled | DepthFlags.MaskEnabled;
Command1 = 0x41;
Command2 = 0x10107;
Command3 = 0x3000000;
Command4 = 0x80126;
}
public DepthOperationCtr(EndianBinaryReader er)
{
Flags = (DepthFlags)er.ReadUInt32();
@ -1326,6 +1422,17 @@ namespace _3DS.NintendoWare.GFX
public BlendOperationCtr BlendOperation;
public class BlendOperationCtr
{
public BlendOperationCtr()
{
Mode = 0;
BlendColor = new Vector4(0, 0, 0, 1);
Command1 = 0xe40100;
Command2 = 0x803f0100;
Command3 = 0x01010000;
Command4 = 0;
Command5 = 0xff000000;
Command6 = 0;
}
public BlendOperationCtr(EndianBinaryReader er)
{
Mode = er.ReadUInt32();
@ -1419,6 +1526,13 @@ namespace _3DS.NintendoWare.GFX
public StencilOperationCtr StencilOperation;
public class StencilOperationCtr
{
public StencilOperationCtr()
{
Command1 = 0xff000000;
Command2 = 0xd0105;
Command3 = 0;
Command4 = 0xf0106;
}
public StencilOperationCtr(EndianBinaryReader er)
{
Command1 = er.ReadUInt32();
@ -1442,6 +1556,18 @@ namespace _3DS.NintendoWare.GFX
public class TextureCoordinatorCtr
{
public TextureCoordinatorCtr()
{
SourceCoordinate = 0;
MappingMethod = 0;
ReferenceCamera = 0;
MatrixMode = 0;
Scale = new Vector2(0, 0);
Rotate = 0;
Translate = new Vector2(0, 0);
Unknown3 = 0;
Matrix = new float[] { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0 };
}
public TextureCoordinatorCtr(EndianBinaryReader er)
{
SourceCoordinate = er.ReadUInt32();
@ -1479,6 +1605,21 @@ namespace _3DS.NintendoWare.GFX
public class TexInfo
{
public TexInfo(String RefTex)
{
Type = 0x80000000;
DynamicAllocator = 0;
Unknown4 = 0;
Unknown5 = 0x8E;
Unknown6 = 1;
Unknown7 = 0xFF000000;
Unknown8 = 0x81;
Unknown9 = 0x809f;
Unknown12 = 0x1002206;
CommandSizeToSend = 0x38;
TextureObject = new ReferenceTexture(RefTex);
Sampler = new StandardTextureSamplerCtr();
}
public TexInfo(EndianBinaryReader er)
{
Type = er.ReadUInt32();
@ -1578,67 +1719,14 @@ namespace _3DS.NintendoWare.GFX
//Procedural Texture Mapper = 0x40000000
public TXOB TextureObject;
/*public TXOB TextureObject;
public class TXOB
{
public TXOB(EndianBinaryReader er)
{
Type = er.ReadUInt32();
Signature = er.ReadString(Encoding.ASCII, 4);
if (Signature != "TXOB") throw new SignatureNotCorrectException(Signature, "TXOB", er.BaseStream.Position);
Revision = er.ReadUInt32();
NameOffset = (UInt32)er.BaseStream.Position + er.ReadUInt32();
Unknown2 = er.ReadUInt32();
Unknown3 = er.ReadUInt32();
LinkedTextureNameOffset = (UInt32)er.BaseStream.Position + er.ReadUInt32();
LinkedTextureOffset = (UInt32)er.BaseStream.Position + er.ReadUInt32();
long curpos = er.BaseStream.Position;
er.BaseStream.Position = NameOffset;
Name = er.ReadStringNT(Encoding.ASCII);
er.BaseStream.Position = LinkedTextureNameOffset;
LinkedTextureName = er.ReadStringNT(Encoding.ASCII);
er.BaseStream.Position = curpos;
}
public void Write(EndianBinaryWriter er, CGFXWriterContext c)
{
er.Write(Type);
er.Write(Signature, Encoding.ASCII, false);
er.Write(Revision);
c.WriteStringReference(Name, er);
er.Write(Unknown2);
er.Write(Unknown3);
c.WriteStringReference(LinkedTextureName, er);
er.Write((uint)0);//TODO: Texture Offset
}
public UInt32 Type;
public String Signature;
public UInt32 Revision;
public UInt32 NameOffset;
public UInt32 Unknown2;
public UInt32 Unknown3;
public UInt32 LinkedTextureNameOffset;
public UInt32 LinkedTextureOffset;
public String Name;
public String LinkedTextureName;
public override string ToString()
{
return Name;
}
//The types are like this:
//Image Texture = 0x20000011
//Cube Texture = 0x20000009
//Reference Texture = 0x20000004 (this structure)
//Procedural Texture = 0x20000002
//Shadow Texture = 0x20000021
}*/
public TextureSamplerCtr Sampler;
public class TextureSamplerCtr
{
public TextureSamplerCtr()
{
MinFilter = 5;
}
public TextureSamplerCtr(EndianBinaryReader er)
{
Type = er.ReadUInt32();
@ -1669,6 +1757,13 @@ namespace _3DS.NintendoWare.GFX
public class StandardTextureSamplerCtr : TextureSamplerCtr
{
public StandardTextureSamplerCtr()
: base()
{
Type = 0x80000000;
BorderColor = new Vector4(0, 0, 0, 1);
LodBias = 0;
}
public StandardTextureSamplerCtr(EndianBinaryReader er)
: base(er)
{
@ -1688,6 +1783,14 @@ namespace _3DS.NintendoWare.GFX
public SHDR Shader;
public class SHDR
{
public SHDR()
{
Type = 0x80000001;
Signature = "SHDR";
Revision = 0x6000000;
Name = "";
LinkedShaderName = "DefaultShader";
}
public SHDR(EndianBinaryReader er)
{
Type = er.ReadUInt32();
@ -1740,6 +1843,26 @@ namespace _3DS.NintendoWare.GFX
public FragmentShader FragShader;
public class FragmentShader
{
public FragmentShader()
{
BufferColor = new Vector4(0, 0, 0, 1);
FragmentLighting = new FragmentLightingCtr();
TextureCombiners = new TextureCombinerCtr[6];
TextureCombiners[0] = new TextureCombinerCtr(0);
TextureCombiners[1] = new TextureCombinerCtr(1);
TextureCombiners[2] = new TextureCombinerCtr(2);
TextureCombiners[3] = new TextureCombinerCtr(3);
TextureCombiners[4] = new TextureCombinerCtr(4);
TextureCombiners[5] = new TextureCombinerCtr(5);
AlphaTest = new AlphaTestCtr();
BufferCommand1 = 0xFF000000;
BufferCommand2 = 0xF00FD;
BufferCommand3 = 0;
BufferCommand4 = 0x200E0;
BufferCommand5 = 0x400;
BufferCommand6 = 0x201C3;
FragmentLightingTable = new FragmentLightingTableCtr();
}
public FragmentShader(EndianBinaryReader er)
{
BufferColor = er.ReadVector4();
@ -1807,7 +1930,10 @@ namespace _3DS.NintendoWare.GFX
UseGeometricFactor1 = 16,
UseReflection = 32
}
public FragmentLightingCtr()
{
IsBumpRenormalize = false;
}
public FragmentLightingCtr(EndianBinaryReader er)
{
Flags = (FragmentLightingFlags)er.ReadUInt32();
@ -1839,6 +1965,7 @@ namespace _3DS.NintendoWare.GFX
public FragmentLightingTableCtr FragmentLightingTable;
public class FragmentLightingTableCtr
{
public FragmentLightingTableCtr() { }
public FragmentLightingTableCtr(EndianBinaryReader er)
{
ReflectanceRSamplerOffset = er.ReadUInt32();
@ -2053,6 +2180,14 @@ namespace _3DS.NintendoWare.GFX
public class TextureCombinerCtr
{
private static readonly uint[] Addresses = { 0xC0, 0xC8, 0xD0, 0xD8, 0xF0, 0xF8 };
public TextureCombinerCtr(int Index)
{
SrcRgb = 0xEE0;
SrcAlpha = 0xEE0;
Address = 0x804F0000 | Addresses[Index];
ConstRgba = Color.Black;
}
public TextureCombinerCtr(EndianBinaryReader er)
{
Constant = er.ReadUInt32();
@ -2093,6 +2228,11 @@ namespace _3DS.NintendoWare.GFX
public class AlphaTestCtr
{
public AlphaTestCtr()
{
Command1 = 0x10;
Command2 = 0xF0104;
}
public AlphaTestCtr(EndianBinaryReader er)
{
Command1 = er.ReadUInt32();
@ -2152,6 +2292,14 @@ namespace _3DS.NintendoWare.GFX
public class Mesh
{
public Mesh()
{
Type = 0x1000000;
Signature = "SOBJ";
Revision = 0;
Name = "";
IsVisible = true;
}
public Mesh(EndianBinaryReader er)
{
Type = er.ReadUInt32();
@ -2196,8 +2344,11 @@ namespace _3DS.NintendoWare.GFX
long curpos = er.BaseStream.Position;
er.BaseStream.Position = NameOffset;
Name = er.ReadStringNT(Encoding.ASCII);
er.BaseStream.Position = MeshNodeNameOffset;
MeshNodeName = er.ReadStringNT(Encoding.ASCII);
if (MeshNodeNameOffset != 0)
{
er.BaseStream.Position = MeshNodeNameOffset;
MeshNodeName = er.ReadStringNT(Encoding.ASCII);
}
er.BaseStream.Position = curpos;
}
public void Write(EndianBinaryWriter er, CGFXWriterContext c, long OwnerOffset)
@ -2232,7 +2383,8 @@ namespace _3DS.NintendoWare.GFX
er.Write(Unknown23);
er.Write(Unknown24);
er.Write(Unknown25);
c.WriteStringReference(MeshNodeName, er);
if (MeshNodeName != null) c.WriteStringReference(MeshNodeName, er);
else er.Write((uint)0);
er.Write(Unknown27);
er.Write(Unknown28);
er.Write(Unknown29);
@ -2298,6 +2450,15 @@ namespace _3DS.NintendoWare.GFX
GL_SHORT = 0x1402,//might also be unsigned short
GL_FLOAT = 0x1406
}
public SeparateDataShape()
{
Type = 0x10000001;
Signature = "SOBJ";
Revision = 0;
Name = "";
BoundingBox = new OrientedBoundingBox();
PositionOffset = new Vector3(0, 0, 0);
}
public SeparateDataShape(EndianBinaryReader er)
{
Type = er.ReadUInt32();
@ -2456,6 +2617,11 @@ namespace _3DS.NintendoWare.GFX
public PrimitiveSet[] PrimitiveSets;
public class PrimitiveSet
{
public PrimitiveSet()
{
NrRelatedBones = 0;
SkinningMode = 0;
}
public PrimitiveSet(EndianBinaryReader er)
{
NrRelatedBones = er.ReadUInt32();
@ -2522,6 +2688,7 @@ namespace _3DS.NintendoWare.GFX
public Primitive[] Primitives;
public class Primitive
{
public Primitive() { }
public Primitive(EndianBinaryReader er)
{
NrIndexStreams = er.ReadUInt32();
@ -2588,6 +2755,13 @@ namespace _3DS.NintendoWare.GFX
public IndexStreamCtr[] IndexStreams;
public class IndexStreamCtr
{
public IndexStreamCtr()
{
FormatType = 0x1401;
PrimitiveMode = 0;
IsVisible = true;
}
public IndexStreamCtr(EndianBinaryReader er)
{
FormatType = er.ReadUInt32();
@ -2722,6 +2896,7 @@ namespace _3DS.NintendoWare.GFX
VertexParam = 1,
Interleave = 2
}
public VertexAttributeCtr() { }
public VertexAttributeCtr(EndianBinaryReader er)
{
Type = er.ReadUInt32();
@ -2757,6 +2932,13 @@ namespace _3DS.NintendoWare.GFX
}
public class InterleavedVertexStreamCtr : VertexAttributeCtr
{
public InterleavedVertexStreamCtr()
: base()
{
Type = 0x40000002;
Usage = VertexAttributeUsage.Interleave;
Flags = VertexAttributeFlags.Interleave;
}
public InterleavedVertexStreamCtr(EndianBinaryReader er)
: base(er)
{
@ -2829,6 +3011,17 @@ namespace _3DS.NintendoWare.GFX
public VertexStreamCtr[] VertexStreams;
public class VertexStreamCtr : VertexAttributeCtr
{
public VertexStreamCtr(VertexAttributeUsage Usage, DataType FormatType, int NrComponents, int Offset, Single Scale = 1)
: base()
{
Type = 0x40000001;
Flags = 0;
this.Usage = Usage;
this.FormatType = FormatType;
this.NrComponents = (uint)NrComponents;
this.Scale = Scale;
this.Offset = (uint)Offset;
}
public VertexStreamCtr(EndianBinaryReader er)
: base(er)
{
@ -3007,6 +3200,17 @@ namespace _3DS.NintendoWare.GFX
}
public class VertexParamAttributeCtr : VertexAttributeCtr
{
public VertexParamAttributeCtr(VertexAttributeUsage Usage, params Single[] Attributes)
: base()
{
Type = 0x80000000;
Flags = VertexAttributeFlags.VertexParam;
this.Usage = Usage;
FormatType = DataType.GL_FLOAT;
Scale = 1;
NrAttributes = (uint)Attributes.Length;
this.Attributes = Attributes;
}
public VertexParamAttributeCtr(EndianBinaryReader er)
: base(er)
{

View File

@ -9,6 +9,12 @@ namespace _3DS.NintendoWare.GFX
{
public class DICT
{
public DICT()
{
Signature = "DICT";
RootNode = new Node();
Entries = new List<Node>();
}
public DICT(EndianBinaryReader er)
{
Signature = er.ReadString(Encoding.ASCII, 4);

View File

@ -11,6 +11,12 @@ namespace _3DS.NintendoWare.GFX
{
public class TXOB
{
public TXOB()
{
Signature = "TXOB";
Revision = 0x5000000;
Name = "";
}
public TXOB(EndianBinaryReader er)
{
Type = er.ReadUInt32();
@ -70,6 +76,12 @@ namespace _3DS.NintendoWare.GFX
public class ReferenceTexture : TXOB
{
public ReferenceTexture(String RefTex)
: base()
{
Type = 0x20000004;
LinkedTextureName = RefTex;
}
public ReferenceTexture(EndianBinaryReader er)
: base(er)
{
@ -97,13 +109,28 @@ namespace _3DS.NintendoWare.GFX
public class PixelBasedTexture : TXOB
{
protected static readonly uint[] GLFormats =
{
0x6752, 0x6754, 0x6752, 0x6754, 0x6752, 0x6758, 0x6759, 0x6757, 0x6756, 0x6758, 0x6757, 0x6756, 0x675A, 0x675B
};
protected static readonly uint[] GLTypes =
{
0x1401, 0x1401, 0x8034, 0x8363, 0x8033, 0x1401, 0x1401, 0x1401, 0x1401, 0x6760, 0x6761 , 0x6761 , 0, 0
};
public PixelBasedTexture()
: base()
{
}
public PixelBasedTexture(EndianBinaryReader er)
: base(er)
{
Height = er.ReadUInt32();
Width = er.ReadUInt32();
GLFormat = er.ReadUInt32();
Type = er.ReadUInt32();
GLType = er.ReadUInt32();
NrLevels = er.ReadUInt32();
TextureObject = er.ReadUInt32();
LocationFlag = er.ReadUInt32();
@ -115,7 +142,7 @@ namespace _3DS.NintendoWare.GFX
er.Write(Height);
er.Write(Width);
er.Write(GLFormat);
er.Write(Type);
er.Write(GLType);
er.Write(NrLevels);
er.Write(TextureObject);
er.Write(LocationFlag);
@ -124,7 +151,7 @@ namespace _3DS.NintendoWare.GFX
public UInt32 Height;
public UInt32 Width;
public UInt32 GLFormat;
public UInt32 Type;
public UInt32 GLType;
public UInt32 NrLevels;//mipmaps
public UInt32 TextureObject;
public UInt32 LocationFlag;
@ -133,6 +160,19 @@ namespace _3DS.NintendoWare.GFX
public class ImageTextureCtr : PixelBasedTexture
{
public ImageTextureCtr(String Name, Bitmap Tex, Textures.ImageFormat Format)
: base()
{
Type = 0x20000011;
this.Name = Name;
Width = (uint)Tex.Width;
Height = (uint)Tex.Height;
HWFormat = Format;
GLFormat = GLFormats[(int)Format];
GLType = GLTypes[(int)Format];
NrLevels = 1;
TextureImage = new PixelBasedImageCtr(Tex, Format);
}
public ImageTextureCtr(EndianBinaryReader er)
: base(er)
{
@ -154,6 +194,14 @@ namespace _3DS.NintendoWare.GFX
public PixelBasedImageCtr TextureImage;
public class PixelBasedImageCtr
{
public PixelBasedImageCtr(Bitmap Tex, Textures.ImageFormat Format)
{
Width = (uint)Tex.Width;
Height = (uint)Tex.Height;
BitsPerPixel = (uint)Textures.GetBpp(Format);
Data = Textures.FromBitmap(Tex, Format);
DataSize = (uint)Data.Length;
}
public PixelBasedImageCtr(EndianBinaryReader er)
{
Height = er.ReadUInt32();

89
3DS/UI/CGFXGenDialog.Designer.cs generated Normal file
View File

@ -0,0 +1,89 @@
namespace _3DS.UI
{
partial class CGFXGenDialog
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.label1 = new System.Windows.Forms.Label();
this.textBox1 = new System.Windows.Forms.TextBox();
this.button1 = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(12, 15);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(73, 13);
this.label1.TabIndex = 0;
this.label1.Text = "Model Name: ";
//
// textBox1
//
this.textBox1.Location = new System.Drawing.Point(91, 12);
this.textBox1.Name = "textBox1";
this.textBox1.Size = new System.Drawing.Size(197, 20);
this.textBox1.TabIndex = 1;
this.textBox1.Text = "EFEModel";
this.textBox1.TextChanged += new System.EventHandler(this.textBox1_TextChanged);
//
// button1
//
this.button1.DialogResult = System.Windows.Forms.DialogResult.OK;
this.button1.Location = new System.Drawing.Point(213, 38);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(75, 23);
this.button1.TabIndex = 2;
this.button1.Text = "OK";
this.button1.UseVisualStyleBackColor = true;
//
// CGFXGenDialog
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(300, 66);
this.ControlBox = false;
this.Controls.Add(this.button1);
this.Controls.Add(this.textBox1);
this.Controls.Add(this.label1);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "CGFXGenDialog";
this.Text = "Generate CGFX";
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Label label1;
private System.Windows.Forms.TextBox textBox1;
private System.Windows.Forms.Button button1;
}
}

27
3DS/UI/CGFXGenDialog.cs Normal file
View File

@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace _3DS.UI
{
public partial class CGFXGenDialog : Form
{
public String ModelName;
public CGFXGenDialog()
{
InitializeComponent();
ModelName = textBox1.Text;
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
ModelName = textBox1.Text;
if (textBox1.Text.Length == 0) button1.Enabled = false;
}
}
}

120
3DS/UI/CGFXGenDialog.resx Normal file
View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -5,6 +5,7 @@ using System.Text;
using LibEveryFileExplorer.Files;
using System.Drawing;
using System.IO;
using System.Globalization;
namespace CommonFiles
{
@ -17,6 +18,8 @@ namespace CommonFiles
public MTL(byte[] Data)
{
var enusculture = new CultureInfo("en-US");
Materials = new List<MTLMaterial>();
MTLMaterial CurrentMaterial = null;
TextReader tr = new StreamReader(new MemoryStream(Data));
String line;
@ -37,39 +40,41 @@ namespace CommonFiles
case "Ka":
{
if (parts.Length < 4) continue;
float r = float.Parse(parts[1]);
float g = float.Parse(parts[2]);
float b = float.Parse(parts[3]);
float r = float.Parse(parts[1], enusculture);
float g = float.Parse(parts[2], enusculture);
float b = float.Parse(parts[3], enusculture);
CurrentMaterial.AmbientColor = Color.FromArgb((int)(r * 255f), (int)(g * 255f), (int)(b * 255f));
break;
}
case "Kd":
{
if (parts.Length < 4) continue;
float r = float.Parse(parts[1]);
float g = float.Parse(parts[2]);
float b = float.Parse(parts[3]);
float r = float.Parse(parts[1], enusculture);
float g = float.Parse(parts[2], enusculture);
float b = float.Parse(parts[3], enusculture);
CurrentMaterial.DiffuseColor = Color.FromArgb((int)(r * 255f), (int)(g * 255f), (int)(b * 255f));
break;
}
case "Ks":
{
if (parts.Length < 4) continue;
float r = float.Parse(parts[1]);
float g = float.Parse(parts[2]);
float b = float.Parse(parts[3]);
float r = float.Parse(parts[1], enusculture);
float g = float.Parse(parts[2], enusculture);
float b = float.Parse(parts[3], enusculture);
CurrentMaterial.SpecularColor = Color.FromArgb((int)(r * 255f), (int)(g * 255f), (int)(b * 255f));
break;
}
case "d":
if (parts.Length < 2) continue;
CurrentMaterial.Alpha = float.Parse(parts[1]);
CurrentMaterial.Alpha = float.Parse(parts[1], enusculture);
break;
case "map_Kd":
CurrentMaterial.DiffuseMapPath = line.Substring(parts[0].Length + 1).Trim();
break;
}
}
if(CurrentMaterial != null && !Materials.Contains(CurrentMaterial))
Materials.Add(CurrentMaterial);
tr.Close();
}