protected node AddToCollada(List <material> materials, List <effect> effects, List <geometry> geometries, List <string> visitedAttaches, bool hasTextures, ref int nodeID) { BasicAttach attach = Attach as BasicAttach; if (attach == null || visitedAttaches.Contains(attach.Name)) { goto skipAttach; } visitedAttaches.Add(attach.Name); int m = 0; foreach (NJS_MATERIAL item in attach.Material) { materials.Add(new material { id = "material_" + attach.Name + "_" + m, name = "material_" + attach.Name + "_" + m, instance_effect = new instance_effect { url = "#" + "material_" + attach.Name + "_" + m + "_eff" } }); if (hasTextures & item.UseTexture) { effects.Add(new effect { id = "material_" + attach.Name + "_" + m + "_eff", name = "material_" + attach.Name + "_" + m + "_eff", Items = new effectFx_profile_abstractProfile_COMMON[] { new effectFx_profile_abstractProfile_COMMON { Items = new object[] { new common_newparam_type { sid = "material_" + attach.Name + "_" + m + "_eff_surface", /*Item = new Collada141.fx_sampler2D_common() * { instance_image = new Collada141.instance_image() { url = "#image_" + (item.TextureID + 1).ToString(System.Globalization.NumberFormatInfo.InvariantInfo) } }, * ItemElementName = Collada141.ItemChoiceType.sampler2D*/ Item = new fx_surface_common { type = fx_surface_type_enum.Item2D, init_from = new fx_surface_init_from_common[] { new fx_surface_init_from_common { Value = "image_" + (item.TextureID + 1).ToString(NumberFormatInfo.InvariantInfo) } } }, ItemElementName = ItemChoiceType.surface } }, technique = new effectFx_profile_abstractProfile_COMMONTechnique { sid = "standard", Item = new effectFx_profile_abstractProfile_COMMONTechniquePhong { ambient = new common_color_or_texture_type { Item = new common_color_or_texture_typeTexture { texture = "material_" + attach.Name + "_" + m + "_eff_surface", texcoord = "CHANNEL0" } }, diffuse = new common_color_or_texture_type { Item = new common_color_or_texture_typeColor { Values = new double[] { item.DiffuseColor.R / 255d, item.DiffuseColor.G / 255d, item.DiffuseColor.B / 255d, item.UseAlpha ? item.DiffuseColor.A / 255d : 1 } } } } } } } }); } else { effects.Add(new effect { id = "material_" + attach.Name + "_" + m + "_eff", name = "material_" + attach.Name + "_" + m + "_eff", Items = new effectFx_profile_abstractProfile_COMMON[] { new effectFx_profile_abstractProfile_COMMON { technique = new effectFx_profile_abstractProfile_COMMONTechnique { sid = "standard", Item = new effectFx_profile_abstractProfile_COMMONTechniquePhong { diffuse = new common_color_or_texture_type { Item = new common_color_or_texture_typeColor { Values = new double[] { item.DiffuseColor.R / 255d, item.DiffuseColor.G / 255d, item.DiffuseColor.B / 255d, item.UseAlpha ? item.DiffuseColor.A / 255d : 1 } } } } } } } }); } m++; } List <double> verts = new List <double>(); foreach (Vertex item in attach.Vertex) { verts.Add(item.X); verts.Add(item.Y); verts.Add(item.Z); } source pos = new source { id = attach.Name + "_position", Item = new float_array { id = attach.Name + "_position_array", count = (ulong)verts.Count, Values = verts.ToArray() }, technique_common = new sourceTechnique_common { accessor = new accessor { source = "#" + attach.Name + "_position_array", count = (ulong)(verts.Count / 3), stride = 3, param = new param[] { new param { name = "X", type = "float" }, new param { name = "Y", type = "float" }, new param { name = "Z", type = "float" } } } } }; verts = new List <double>(); foreach (Vertex item in attach.Normal) { verts.Add(item.X); verts.Add(item.Y); verts.Add(item.Z); } source nor = new source { id = attach.Name + "_normal", Item = new float_array { id = attach.Name + "_normal_array", count = (ulong)verts.Count, Values = verts.ToArray() }, technique_common = new sourceTechnique_common { accessor = new accessor { source = "#" + attach.Name + "_normal_array", count = (ulong)(verts.Count / 3), stride = 3, param = new param[] { new param { name = "X", type = "float" }, new param { name = "Y", type = "float" }, new param { name = "Z", type = "float" } } } } }; List <source> srcs = new List <source> { pos, nor }; foreach (NJS_MESHSET mitem in attach.Mesh) { if (mitem.UV != null) { verts = new List <double>(); foreach (UV item in mitem.UV) { verts.Add(item.U); verts.Add(-item.V); } srcs.Add(new source { id = mitem.UVName, Item = new float_array { id = mitem.UVName + "_array", count = (ulong)verts.Count, Values = verts.ToArray() }, technique_common = new sourceTechnique_common { accessor = new accessor { source = "#" + mitem.UVName + "_array", count = (ulong)(verts.Count / 2), stride = 2, param = new param[] { new param { name = "S", type = "float" }, new param { name = "T", type = "float" } } } } }); } } List <triangles> tris = new List <triangles>(); foreach (NJS_MESHSET mesh in attach.Mesh) { bool hasVColor = mesh.VColor != null; bool hasUV = mesh.UV != null; uint currentstriptotal = 0; foreach (Poly poly in mesh.Poly) { List <uint> inds = new List <uint>(); switch (mesh.PolyType) { case Basic_PolyType.Triangles: for (uint i = 0; i < 3; i++) { inds.Add(poly.Indexes[i]); if (hasUV) { inds.Add(currentstriptotal + i); } } currentstriptotal += 3; break; case Basic_PolyType.Quads: for (uint i = 0; i < 3; i++) { inds.Add(poly.Indexes[i]); if (hasUV) { inds.Add(currentstriptotal + i); } } for (uint i = 1; i < 4; i++) { inds.Add(poly.Indexes[i]); if (hasUV) { inds.Add(currentstriptotal + i); } } currentstriptotal += 4; break; case Basic_PolyType.NPoly: case Basic_PolyType.Strips: bool flip = !((Strip)poly).Reversed; for (int k = 0; k < poly.Indexes.Length - 2; k++) { flip = !flip; if (!flip) { for (uint i = 0; i < 3; i++) { inds.Add(poly.Indexes[k + i]); if (hasUV) { inds.Add(currentstriptotal + i); } } } else { inds.Add(poly.Indexes[k + 1]); if (hasUV) { inds.Add(currentstriptotal + 1); } inds.Add(poly.Indexes[k]); if (hasUV) { inds.Add(currentstriptotal); } inds.Add(poly.Indexes[k + 2]); if (hasUV) { inds.Add(currentstriptotal + 2); } } currentstriptotal += 1; } currentstriptotal += 2; break; } string[] indstr = new string[inds.Count]; for (int i = 0; i < inds.Count; i++) { indstr[i] = inds[i].ToString(NumberFormatInfo.InvariantInfo); } List <InputLocalOffset> inp = new List <InputLocalOffset> { new InputLocalOffset { semantic = "VERTEX", offset = 0, source = "#" + attach.Name + "_vertices" } }; if (hasUV) { inp.Add(new InputLocalOffset { semantic = "TEXCOORD", offset = 1, source = "#" + mesh.UVName, setSpecified = true }); } tris.Add(new triangles { material = "material_" + attach.Name + "_" + mesh.MaterialID, count = (ulong)(inds.Count / (hasUV ? 6 : 3)), input = inp.ToArray(), p = string.Join(" ", indstr) }); } } geometries.Add(new geometry { id = attach.Name, name = attach.Name, Item = new mesh { source = srcs.ToArray(), vertices = new vertices { id = attach.Name + "_vertices", input = new InputLocal[] { new InputLocal { semantic = "POSITION", source = "#" + attach.Name + "_position" }, new InputLocal { semantic = "NORMAL", source = "#" + attach.Name + "_normal" } } }, Items = tris.ToArray() } }); skipAttach: ++nodeID; node node = new node { id = $"{nodeID:000}_{Name}", name = $"{nodeID:000}_{Name}", Items = new object[] { new TargetableFloat3 { sid = "translate", Values = new double[] { Position.X, Position.Y, Position.Z } }, new rotate { sid = "rotateZ", Values = new double[] { 0, 0, 1, Rotation.BAMSToDeg(Rotation.Z) } }, new rotate { sid = "rotateX", Values = new double[] { 1, 0, 0, Rotation.BAMSToDeg(Rotation.X) } }, new rotate { sid = "rotateY", Values = new double[] { 0, 1, 0, Rotation.BAMSToDeg(Rotation.Y) } }, new TargetableFloat3 { sid = "scale", Values = new double[] { Scale.X, Scale.Y, Scale.Z } } }, ItemsElementName = new ItemsChoiceType2[] { ItemsChoiceType2.translate, ItemsChoiceType2.rotate, ItemsChoiceType2.rotate, ItemsChoiceType2.rotate, ItemsChoiceType2.scale } }; if (attach != null) { List <instance_material> mats = new List <instance_material>(); foreach (NJS_MESHSET item in attach.Mesh) { mats.Add(new instance_material { symbol = "material_" + attach.Name + "_" + item.MaterialID, target = "#" + "material_" + attach.Name + "_" + item.MaterialID }); } node.instance_geometry = new instance_geometry[] { new instance_geometry { url = "#" + attach.Name, bind_material = new bind_material { technique_common = mats.ToArray() } } }; } List <node> childnodes = new List <node>(); foreach (NJS_OBJECT item in Children) { childnodes.Add(item.AddToCollada(materials, effects, geometries, visitedAttaches, hasTextures, ref nodeID)); } node.node1 = childnodes.ToArray(); return(node); }
static void Main(string[] args) { string filename; if (args.Length > 0) { filename = args[0]; Console.WriteLine("File: {0}", filename); } else { Console.Write("File: "); filename = Console.ReadLine(); } LandTable level = LandTable.LoadFromFile(filename); switch (level.Format) { case LandTableFormat.SA1: { List<COL> newcollist = new List<COL>(); foreach (COL col in level.COL.Where((col) => col.Model != null && col.Model.Attach != null)) { if ((col.SurfaceFlags & SurfaceFlags.Visible) == SurfaceFlags.Visible) { COL newcol = new COL() { Bounds = col.Bounds }; newcol.SurfaceFlags = SurfaceFlags.Visible; newcol.Model = new SonicRetro.SAModel.NJS_OBJECT() { Name = col.Model.Name + "_cnk" }; newcol.Model.Position = col.Model.Position; newcol.Model.Rotation = col.Model.Rotation; newcol.Model.Scale = col.Model.Scale; BasicAttach basatt = (BasicAttach)col.Model.Attach; ChunkAttach cnkatt = new ChunkAttach(true, true) { Name = basatt.Name + "_cnk", Bounds = basatt.Bounds }; newcol.Model.Attach = cnkatt; VertexChunk vcnk; if (basatt.Normal != null && basatt.Normal.Length > 0) vcnk = new VertexChunk(ChunkType.Vertex_VertexNormal); else vcnk = new VertexChunk(ChunkType.Vertex_Vertex); vcnk.Vertices = new List<Vertex>(basatt.Vertex); if (basatt.Normal != null) vcnk.Normals = new List<Vertex>(basatt.Normal); vcnk.VertexCount = (ushort)basatt.Vertex.Length; vcnk.Size = (ushort)((vcnk.Type == ChunkType.Vertex_VertexNormal ? vcnk.VertexCount * 6 : vcnk.VertexCount * 3) + 1); cnkatt.Vertex.Add(vcnk); foreach (NJS_MESHSET mesh in basatt.Mesh) { if (mesh.PolyType != Basic_PolyType.Strips) { Console.WriteLine("Warning: Skipping non-strip mesh in {0} ({1}).", basatt.MeshName, mesh.PolyType); continue; } NJS_MATERIAL mat = null; if (basatt.Material != null && mesh.MaterialID < basatt.Material.Count) { mat = basatt.Material[mesh.MaterialID]; cnkatt.Poly.Add(new PolyChunkBitsBlendAlpha() { SourceAlpha = mat.SourceAlpha, DestinationAlpha = mat.DestinationAlpha }); cnkatt.Poly.Add(new PolyChunkTinyTextureID() { ClampU = mat.ClampU, ClampV = mat.ClampV, FilterMode = mat.FilterMode, FlipU = mat.FlipU, FlipV = mat.FlipV, SuperSample = mat.SuperSample, TextureID = (ushort)mat.TextureID }); cnkatt.Poly.Add(new PolyChunkMaterial() { Diffuse = mat.DiffuseColor, Specular = mat.SpecularColor, SpecularExponent = (byte)mat.Exponent }); } PolyChunkStrip strip; if (mesh.UV != null & mesh.VColor != null) strip = new PolyChunkStrip(ChunkType.Strip_StripUVNColor); else if (mesh.UV != null) strip = new PolyChunkStrip(ChunkType.Strip_StripUVN); else if (mesh.VColor != null) strip = new PolyChunkStrip(ChunkType.Strip_StripColor); else strip = new PolyChunkStrip(ChunkType.Strip_Strip); if (mat != null) { strip.IgnoreLight = mat.IgnoreLighting; strip.IgnoreSpecular = mat.IgnoreSpecular; strip.UseAlpha = mat.UseAlpha; strip.DoubleSide = mat.DoubleSided; strip.FlatShading = mat.FlatShading; strip.EnvironmentMapping = mat.EnvironmentMap; } int striptotal = 0; foreach (Strip item in mesh.Poly.Cast<Strip>()) { UV[] uvs = null; if (mesh.UV != null) { uvs = new UV[item.Indexes.Length]; Array.Copy(mesh.UV, striptotal, uvs, 0, item.Indexes.Length); } Color[] vcolors = null; if (mesh.VColor != null) { vcolors = new Color[item.Indexes.Length]; Array.Copy(mesh.VColor, striptotal, vcolors, 0, item.Indexes.Length); } strip.Strips.Add(new PolyChunkStrip.Strip(item.Reversed, item.Indexes, uvs, vcolors)); striptotal += item.Indexes.Length; } cnkatt.Poly.Add(strip); } newcollist.Add(newcol); } if ((col.SurfaceFlags & ~SurfaceFlags.Visible) != 0) { col.SurfaceFlags &= ~SurfaceFlags.Visible; newcollist.Add(col); } } level.COL = newcollist; } level.Anim = new List<GeoAnimData>(); level.Tool = "SA Tools Level Converter"; level.SaveToFile(System.IO.Path.ChangeExtension(filename, "sa2lvl"), LandTableFormat.SA2); break; case LandTableFormat.SA2: Vertex[] VertexBuffer = new Vertex[0]; Vertex[] NormalBuffer = new Vertex[0]; foreach (COL col in level.COL.Where((col) => col.Model != null && col.Model.Attach is ChunkAttach)) { ChunkAttach cnkatt = (ChunkAttach)col.Model.Attach; BasicAttach basatt = new BasicAttach() { Name = cnkatt.Name, Bounds = cnkatt.Bounds }; if (cnkatt.Vertex != null) foreach (VertexChunk chunk in cnkatt.Vertex) { if (VertexBuffer.Length < chunk.IndexOffset + chunk.VertexCount) { Array.Resize(ref VertexBuffer, chunk.IndexOffset + chunk.VertexCount); Array.Resize(ref NormalBuffer, chunk.IndexOffset + chunk.VertexCount); } Array.Copy(chunk.Vertices.ToArray(), 0, VertexBuffer, chunk.IndexOffset, chunk.Vertices.Count); Array.Copy(chunk.Normals.ToArray(), 0, NormalBuffer, chunk.IndexOffset, chunk.Normals.Count); } NJS_MATERIAL material = new NJS_MATERIAL() { UseTexture = true }; int minVtx = int.MaxValue; int maxVtx = int.MinValue; foreach (PolyChunk chunk in cnkatt.Poly) switch (chunk.Type) { case ChunkType.Bits_BlendAlpha: { PolyChunkBitsBlendAlpha c2 = (PolyChunkBitsBlendAlpha)chunk; material.SourceAlpha = c2.SourceAlpha; material.DestinationAlpha = c2.DestinationAlpha; } break; case ChunkType.Bits_MipmapDAdjust: break; case ChunkType.Bits_SpecularExponent: material.Exponent = ((PolyChunkBitsSpecularExponent)chunk).SpecularExponent; break; case ChunkType.Tiny_TextureID: case ChunkType.Tiny_TextureID2: { PolyChunkTinyTextureID c2 = (PolyChunkTinyTextureID)chunk; material.ClampU = c2.ClampU; material.ClampV = c2.ClampV; material.FilterMode = c2.FilterMode; material.FlipU = c2.FlipU; material.FlipV = c2.FlipV; material.SuperSample = c2.SuperSample; material.TextureID = c2.TextureID; } break; case ChunkType.Material_Diffuse: case ChunkType.Material_Ambient: case ChunkType.Material_DiffuseAmbient: case ChunkType.Material_Specular: case ChunkType.Material_DiffuseSpecular: case ChunkType.Material_AmbientSpecular: case ChunkType.Material_DiffuseAmbientSpecular: case ChunkType.Material_Diffuse2: case ChunkType.Material_Ambient2: case ChunkType.Material_DiffuseAmbient2: case ChunkType.Material_Specular2: case ChunkType.Material_DiffuseSpecular2: case ChunkType.Material_AmbientSpecular2: case ChunkType.Material_DiffuseAmbientSpecular2: { PolyChunkMaterial c2 = (PolyChunkMaterial)chunk; if (c2.Diffuse.HasValue) material.DiffuseColor = c2.Diffuse.Value; if (c2.Specular.HasValue) { material.SpecularColor = c2.Specular.Value; material.Exponent = c2.SpecularExponent; } } break; case ChunkType.Strip_Strip: case ChunkType.Strip_StripUVN: case ChunkType.Strip_StripUVH: case ChunkType.Strip_StripNormal: case ChunkType.Strip_StripUVNNormal: case ChunkType.Strip_StripUVHNormal: case ChunkType.Strip_StripColor: case ChunkType.Strip_StripUVNColor: case ChunkType.Strip_StripUVHColor: case ChunkType.Strip_Strip2: case ChunkType.Strip_StripUVN2: case ChunkType.Strip_StripUVH2: { PolyChunkStrip c2 = (PolyChunkStrip)chunk; material.DoubleSided = c2.DoubleSide; material.EnvironmentMap = c2.EnvironmentMapping; material.FlatShading = c2.FlatShading; material.IgnoreLighting = c2.IgnoreLight; material.IgnoreSpecular = c2.IgnoreSpecular; material.UseAlpha = c2.UseAlpha; bool hasVColor = false; switch (chunk.Type) { case ChunkType.Strip_StripColor: case ChunkType.Strip_StripUVNColor: case ChunkType.Strip_StripUVHColor: hasVColor = true; break; } bool hasUV = false; switch (chunk.Type) { case ChunkType.Strip_StripUVN: case ChunkType.Strip_StripUVH: case ChunkType.Strip_StripUVNColor: case ChunkType.Strip_StripUVHColor: case ChunkType.Strip_StripUVN2: case ChunkType.Strip_StripUVH2: hasUV = true; break; } List<Strip> strips = new List<Strip>(c2.StripCount); List<UV> uvs = hasUV ? new List<UV>() : null; List<Color> vcolors = hasVColor ? new List<Color>() : null; foreach (PolyChunkStrip.Strip strip in c2.Strips) { minVtx = Math.Min(minVtx, strip.Indexes.Min()); maxVtx = Math.Max(maxVtx, strip.Indexes.Max()); strips.Add(new Strip(strip.Indexes, strip.Reversed)); if (hasUV) uvs.AddRange(strip.UVs); if (hasVColor) vcolors.AddRange(strip.VColors); } NJS_MESHSET mesh = new NJS_MESHSET(strips.ToArray(), false, hasUV, hasVColor); if (hasUV) uvs.CopyTo(mesh.UV); if (hasVColor) vcolors.CopyTo(mesh.VColor); mesh.MaterialID = (ushort)basatt.Material.Count; basatt.Mesh.Add(mesh); basatt.Material.Add(material); material = new NJS_MATERIAL(material.GetBytes(), 0); } break; } int numVtx = maxVtx - minVtx + 1; basatt.ResizeVertexes(numVtx); Array.Copy(VertexBuffer, minVtx, basatt.Vertex, 0, numVtx); Array.Copy(NormalBuffer, minVtx, basatt.Normal, 0, numVtx); foreach (NJS_MESHSET mesh in basatt.Mesh) foreach (Poly poly in mesh.Poly) for (int i = 0; i < poly.Indexes.Length; i++) poly.Indexes[i] = (ushort)(poly.Indexes[i] - minVtx); col.Model.Attach = basatt; } level.Anim = new List<GeoAnimData>(); level.Tool = "SA Tools Level Converter"; level.SaveToFile(System.IO.Path.ChangeExtension(filename, "sa1lvl"), LandTableFormat.SA1); break; } }
public void ToNJA(TextWriter writer, bool DX, List <string> labels, string[] textures = null) { for (int i = 1; i < Children.Count; i++) { Children[i - 1].Sibling = Children[i]; } for (int i = Children.Count - 1; i >= 0; i--) { if (!labels.Contains(Children[i].Name)) { labels.Add(Children[i].Name); Children[i].ToNJA(writer, DX, labels, textures); writer.WriteLine(); } } if (Parent == null && Sibling != null && !labels.Contains(Sibling.Name)) { labels.Add(Sibling.Name); Sibling.ToNJA(writer, DX, labels, textures); writer.WriteLine(); } writer.WriteLine("OBJECT_START"); if (Attach is BasicAttach) { BasicAttach basicattach = Attach as BasicAttach; basicattach.ToNJA(writer, DX, labels, textures); } else if (Attach is ChunkAttach) { //ChunkAttach ChunkAttach = Attach as ChunkAttach; //ChunkAttach.ToNJA(writer, labels, textures); } writer.Write("OBJECT "); writer.Write(Name); writer.WriteLine("[]"); writer.WriteLine("START"); writer.WriteLine("EvalFlags ( " + ((StructEnums.NJD_EVAL)GetFlags()).ToString().Replace(", ", " | ") + " ),"); writer.WriteLine("Model " + (Attach != null ? "&" + Attach.Name : "NULL") + ","); writer.Write("OPosition ( "); foreach (float value in Position.ToArray()) { writer.Write(value.ToC()); writer.Write(", "); } writer.WriteLine("),"); writer.Write("OAngle ( "); foreach (float value in Rotation.ToArray()) { writer.Write(value.ToC()); writer.Write(", "); } writer.WriteLine("),"); writer.Write("OScale ( "); foreach (float value in Scale.ToArray()) { writer.Write(value.ToC()); writer.Write(", "); } writer.WriteLine("),"); writer.WriteLine("Child " + (Children.Count > 0 ? Children[0].Name : "NULL") + ","); writer.WriteLine("Sibling " + (Sibling != null ? Sibling.Name : "NULL")); writer.WriteLine("END"); writer.WriteLine("OBJECT_END"); }