public void ReadRawFaces(int off) { RawFaces = new List <RawFace>(); int size = BitConverter.ToInt32(memory, off); if (size != 8) { ReadUnknown5(off); return; } offFace = off; int count = BitConverter.ToInt32(memory, off + 4); int pos = off + 8; RawFace f = new RawFace(); for (int i = 0; i < count; i++) { f.e0 = BitConverter.ToUInt16(memory, pos); f.e1 = BitConverter.ToUInt16(memory, pos + 2); f.e2 = BitConverter.ToUInt16(memory, pos + 4); RawFaces.Add(f); pos += size; } currpos = pos; }
public RealGeometryFile Collect(RawGeometryFile rawGeom) { RealGeometryFile geom = new RealGeometryFile(); Hashtable MatTex = new Hashtable(); LoadMaterialHT(); for (int i = 0; i < rawGeom.Header.NumMaterials; i++) { MatTexStringPair pair = new MatTexStringPair(); string mat = rawGeom.Header.MatNames[i].Data; if (materialHT.ContainsKey(mat)) { mat = (string)materialHT[mat]; } string[] split = mat.Split('/'); if (split.Length < 2) { Compiler.WarningOutput(string.Format("Material {0} has invalid name.", mat)); pair.Material = "DEFAULT"; pair.Texture = "DEFAULT"; } else { pair.Material = split[0]; pair.Texture = split[1]; } MatTex.Add(i, pair); } ArrayList mountPointObjects = new ArrayList(); //ArrayList transparentObjects = new ArrayList(new string[] {"base_a","kit00_front_window_a","kit00_left_headlight_a"}); ArrayList transparentObjects = new ArrayList(); int diffuse; ArrayList basePartObjects = new ArrayList(); for (int i = 0; i < rawGeom.Header.NumObjects; i++) { Compiler.VerboseOutput(string.Format("Compiling object {0}: {1}", i + 1, rawGeom.Header.ObjHeaders[i].ObjName)); if (rawGeom.Header.ObjHeaders[i].ObjName.Data.StartsWith("#")) { string mountName; uint mountHash; mountName = rawGeom.Header.ObjHeaders[i].ObjName.Data.Substring(1).ToUpper(); if (mountName.IndexOf("[") > -1) { mountName = mountName.Substring(0, mountName.IndexOf("[")); } if (mountName.StartsWith("0x")) { mountHash = uint.Parse(mountName.Substring(2), NumberStyles.HexNumber); } else { mountHash = RealHash(mountName); } Compiler.VerboseOutput(string.Format(" + Mount Point Name: {0}", mountName)); Compiler.VerboseOutput(string.Format(" + Compiled Hash: 0x{0:x}", mountHash)); RealMountPoint mp = new RealMountPoint(); mp.Hash = mountHash; mp.Transform = new RealMatrix(); mp.Transform.m = new float[16]; float[] transform = rawGeom.Header.ObjHeaders[i].Transform; mp.Transform.m[0] = 1.0f; mp.Transform.m[5] = 1.0f; mp.Transform.m[10] = 1.0f; mp.Transform.m[15] = 1.0f; mp.Transform.m[12] = transform[14]; //z mp.Transform.m[13] = transform[12]; //x mp.Transform.m[14] = transform[13]; //y mountPointObjects.Add(mp); } else { Hashtable subMeshes = new Hashtable(); UniqueList textures = new UniqueList(); UniqueList materials = new UniqueList(); if (transparentObjects.Contains(rawGeom.Header.ObjHeaders[i].ObjName.ToString())) { diffuse = 0x7FFFFFFF; } else { diffuse = -1; } for (int j = 0; j < rawGeom.Header.ObjHeaders[i].NumFaces; j++) { SubMesh subMesh; RawFace face = rawGeom.Objects[i].Faces[j]; MatTexPair pair = new MatTexPair(); MatTexStringPair strPair = (MatTexStringPair)MatTex[face.MatIndex]; pair.Material = materials.Add(strPair.Material); pair.Texture = textures.Add(strPair.Texture); if (subMeshes.ContainsKey(pair)) { subMesh = subMeshes[pair] as SubMesh; } else { subMesh = new SubMesh(); subMesh.TextureId = pair.Texture; subMesh.MaterialId = pair.Material; subMeshes.Add(pair, subMesh); } // note ZM default = CCW, MW = CW RawVertex v1 = rawGeom.Objects[i].Vertices[face.I3]; RawVertex v2 = rawGeom.Objects[i].Vertices[face.I2]; RawVertex v3 = rawGeom.Objects[i].Vertices[face.I1]; RealVertex rv; // v1 rv = new RealVertex(); rv.Initialize(true, 0); /* * rv.Position.x =-v1.X; * rv.Position.y = v1.Z; * rv.Position.z = v1.Y; * rv.Normal.x =-v1.nX; * rv.Normal.y = v1.nZ; * rv.Normal.z = v1.nY; */ rv.Position.x = v1.Z; rv.Position.y = v1.X; rv.Position.z = v1.Y; rv.Normal.x = v1.nZ; rv.Normal.y = v1.nX; rv.Normal.z = v1.nY; rv.Diffuse = diffuse; rv.UV.u = face.tU3; rv.UV.v = face.tV3; subMesh.IndexList.Add((ushort)subMesh.VertexList.Add(rv)); // v2 rv = new RealVertex(); rv.Initialize(true, 0); /* * rv.Position.x =-v2.X; * rv.Position.y = v2.Z; * rv.Position.z = v2.Y; * rv.Normal.x =-v2.nX; * rv.Normal.y = v2.nZ; * rv.Normal.z = v2.nY; */ rv.Position.x = v2.Z; rv.Position.y = v2.X; rv.Position.z = v2.Y; rv.Normal.x = v2.nZ; rv.Normal.y = v2.nX; rv.Normal.z = v2.nY; rv.Diffuse = diffuse; rv.UV.u = face.tU2; rv.UV.v = face.tV2; subMesh.IndexList.Add((ushort)subMesh.VertexList.Add(rv)); // v3 rv = new RealVertex(); rv.Initialize(true, 0); /* * rv.Position.x =-v3.X; * rv.Position.y = v3.Z; * rv.Position.z = v3.Y; * rv.Normal.x =-v3.nX; * rv.Normal.y = v3.nZ; * rv.Normal.z = v3.nY; */ rv.Position.x = v3.Z; rv.Position.y = v3.X; rv.Position.z = v3.Y; rv.Normal.x = v3.nZ; rv.Normal.y = v3.nX; rv.Normal.z = v3.nY; rv.Diffuse = diffuse; rv.UV.u = face.tU1; rv.UV.v = face.tV1; subMesh.IndexList.Add((ushort)subMesh.VertexList.Add(rv)); } Compiler.VerboseOutput(string.Format(" + Compiled into {0} submeshes", subMeshes.Count)); SubMesh[] subMeshList = new SubMesh[subMeshes.Count]; subMeshes.Values.CopyTo(subMeshList, 0); for (int j = 0; j < subMeshes.Count; j++) { SubMesh subMesh = subMeshList[j]; Compiler.VerboseOutput(string.Format(" + Submesh {0}:", j + 1)); Compiler.VerboseOutput(string.Format(" + Material: {0}", materials[subMesh.MaterialId])); Compiler.VerboseOutput(string.Format(" + Texture: {0}", textures[subMesh.TextureId])); Compiler.VerboseOutput(string.Format(" + Vertices: {0}", subMesh.VertexList.Count)); Compiler.VerboseOutput(string.Format(" + Triangles: {0}", subMesh.IndexList.Count / 3)); } Compiler.VerboseOutput(string.Format("Creating part data for binary object file...")); RealGeometryPart part = new RealGeometryPart(); //----- part info ---------- RealVector4 boundsMin; RealVector4 boundsMax; if (rawGeom.Header.ObjHeaders[i].ObjName.Data.ToUpper().StartsWith("BASE_")) { basePartObjects.Add(part); } string resolvedName = ResolveRealNameForce(rawGeom.Header.ObjHeaders[i].ObjName.Data); part.PartInfo.Hash = RealHash(resolvedName); part.PartInfo.PartName = new FixedLenString(resolvedName); part.PartInfo.ShaderCount = (byte)materials.Count; part.PartInfo.Shaders = new uint[materials.Count]; for (int j = 0; j < materials.Count; j++) { string matName = materials[j] as string; if (matName.StartsWith("0x")) { part.PartInfo.Shaders[j] = uint.Parse(matName.Substring(2), NumberStyles.HexNumber); } else { part.PartInfo.Shaders[j] = RealHash(matName); } } part.PartInfo.TextureCount = (byte)textures.Count; part.PartInfo.Textures = new uint[textures.Count]; for (int j = 0; j < textures.Count; j++) { string texName = textures[j] as string; if (texName.StartsWith("0x")) { part.PartInfo.Textures[j] = uint.Parse(texName.Substring(2), NumberStyles.HexNumber); } else { part.PartInfo.Textures[j] = RealHash(ResolveRealName(texName)); } } part.PartInfo.Transform.m = rawGeom.Header.ObjHeaders[i].Transform; /* * part.PartInfo.Transform.m = new float[16]; * part.PartInfo.Transform.m[0] = 1.0f; * part.PartInfo.Transform.m[5] = 1.0f; * part.PartInfo.Transform.m[10] = 1.0f; * part.PartInfo.Transform.m[15] = 1.0f; */ part.PartInfo.TriangleCount = rawGeom.Header.ObjHeaders[i].NumFaces; part.PartInfo.Unk1 = 0x00400018; part.PartInfo.Unk2 = 0x000EA550; part.PartInfo.Unk3 = 0x000EA550; part.PartInfo.Unk4_MW = 0; part.PartInfo.Unk5_MW = 1; part.PartInfo.Unk6_MW = part.PartInfo.TriangleCount; //----- part data ---------- part.PartData.Flags = 0x000080 + /* 0x000100 */ +0x004000 /* + 0x010000*/; part.PartData.GroupCount = subMeshList.Length; part.PartData.Groups = new RealShadingGroup[subMeshList.Length]; int indexOffset = 0; for (int j = 0; j < subMeshList.Length; j++) { SubMesh subMesh = subMeshList[j]; part.PartData.Groups[j] = new RealShadingGroup(); boundsMin = new RealVector4(); boundsMax = new RealVector4(); if (subMesh.VertexList.Count > 0) { RealVector3 v = ((RealVertex)subMesh.VertexList[0]).Position; boundsMin.x = v.x; boundsMin.y = v.y; boundsMin.z = v.z; boundsMax = boundsMin; } for (int k = 1; k < subMesh.VertexList.Count; k++) { RealVector3 v = ((RealVertex)subMesh.VertexList[k]).Position; if (v.x > boundsMax.x) { boundsMax.x = v.x; } if (v.y > boundsMax.y) { boundsMax.y = v.y; } if (v.z > boundsMax.z) { boundsMax.z = v.z; } if (v.x < boundsMin.x) { boundsMin.x = v.x; } if (v.y < boundsMin.y) { boundsMin.y = v.y; } if (v.z < boundsMin.z) { boundsMin.z = v.z; } } part.PartData.Groups[j].BoundsMax = new RealVector3(boundsMax.x, boundsMax.y, boundsMax.z); part.PartData.Groups[j].BoundsMin = new RealVector3(boundsMin.x, boundsMin.y, boundsMin.z); part.PartData.Groups[j].Length = subMesh.IndexList.Count; part.PartData.Groups[j].TextureIndex0 = (byte)subMesh.TextureId; part.PartData.Groups[j].TextureIndex1 = (byte)subMesh.TextureId; part.PartData.Groups[j].TextureIndex2 = (byte)subMesh.TextureId; part.PartData.Groups[j].TextureIndex3 = (byte)subMesh.TextureId; part.PartData.Groups[j].TextureIndex4 = (byte)subMesh.TextureId; part.PartData.Groups[j].ShaderIndex0 = (byte)subMesh.MaterialId; part.PartData.Groups[j].Unk1 = 0x4; part.PartData.Groups[j].Flags = part.PartData.Flags; part.PartData.Groups[j].VertexCount = subMesh.VertexList.Count; part.PartData.Groups[j].TriangleCount = subMesh.IndexList.Count / 3; part.PartData.Groups[j].Offset = indexOffset; indexOffset += subMesh.IndexList.Count; } // -- bit of partinfo here -- caclulate bounds boundsMin = new RealVector4(); boundsMax = new RealVector4(); if (part.PartData.Groups.Length > 0) { RealVector3 v = part.PartData.Groups[0].BoundsMin; boundsMin.x = v.x; boundsMin.y = v.y; boundsMin.z = v.z; v = part.PartData.Groups[0].BoundsMax; boundsMax.x = v.x; boundsMax.y = v.y; boundsMax.z = v.z; } for (int j = 1; j < part.PartData.Groups.Length; j++) { RealVector3 v = part.PartData.Groups[j].BoundsMax; if (v.x > boundsMax.x) { boundsMax.x = v.x; } if (v.y > boundsMax.y) { boundsMax.y = v.y; } if (v.z > boundsMax.z) { boundsMax.z = v.z; } v = part.PartData.Groups[j].BoundsMin; if (v.x < boundsMin.x) { boundsMin.x = v.x; } if (v.y < boundsMin.y) { boundsMin.y = v.y; } if (v.z < boundsMin.z) { boundsMin.z = v.z; } } part.PartInfo.BoundMax = boundsMax; part.PartInfo.BoundMin = boundsMin; // -- end -- part.PartData.IndexCount = indexOffset; part.PartData.Indices = new ushort[indexOffset]; int vertexOffset = 0; indexOffset = 0; for (int j = 0; j < subMeshList.Length; j++) { for (int k = 0; k < subMeshList[j].IndexList.Count; k++) { part.PartData.Indices[indexOffset++] = (ushort)((ushort)subMeshList[j].IndexList[k] + vertexOffset); } vertexOffset += subMeshList[j].VertexList.Count; } part.PartData.TriangleCount = indexOffset / 3; part.PartData.Unk1 = 0x12; part.PartData.VBCount = 1; part.PartData.Vertices = new RealVertex[vertexOffset]; vertexOffset = 0; for (int j = 0; j < subMeshList.Length; j++) { for (int k = 0; k < subMeshList[j].VertexList.Count; k++) { part.PartData.Vertices[vertexOffset++] = (RealVertex)subMeshList[j].VertexList[k]; } } geom.AddPart(part); } Compiler.VerboseOutput(" + Complete."); } if (mountPointObjects.Count > 0) { Compiler.VerboseOutput("Merging mount points into base parts..."); if (basePartObjects.Count == 0) { Compiler.WarningOutput("Mount points provided without any base parts! Ignoring mount points."); } else { RealMountPoint[] mountPoints = new RealMountPoint[mountPointObjects.Count]; mountPointObjects.CopyTo(mountPoints); foreach (RealGeometryPart part in basePartObjects) { part.PartInfo.MountPoints = mountPoints; } } Compiler.VerboseOutput(" + Complete."); } Compiler.VerboseOutput("Collecting part cross links..."); LoadCrossLinks(geom); geom.GeometryInfo.PartCount = geom.PartCount; geom.GeometryInfo.Unk1 = 0x1D; geom.GeometryInfo.Unk2 = 0x80; geom.GeometryInfo.ClassType = new FixedLenString("DEFAULT", 0x20); geom.GeometryInfo.RelFilePath = new FixedLenString("GEOMETRY.BIN", 0x38); Compiler.VerboseOutput("Data successfully collected."); return(geom); }
public void ReadRawFaces(int off) { RawFaces = new List<RawFace>(); int size = BitConverter.ToInt32(memory, off); if (size != 8) { ReadUnknown5(off); return; } offFace = off; int count = BitConverter.ToInt32(memory, off + 4); int pos = off + 8; RawFace f = new RawFace(); for (int i = 0; i < count; i++) { f.e0 = BitConverter.ToUInt16(memory, pos); f.e1 = BitConverter.ToUInt16(memory, pos + 2); f.e2 = BitConverter.ToUInt16(memory, pos + 4); RawFaces.Add(f); pos += size; } currpos = pos; }
public static Geometry LoadFromJson(Stream s) { Geometry geo = new Geometry(); using (var reader = new StreamReader(s)) { var txt = reader.ReadToEnd(); var raw = JsonConvert.DeserializeObject <GeometryRaw>(txt); RawVertex[] verts = new RawVertex[raw.vertexAttrEdge.Length]; RawEdge[] edges = new RawEdge[raw.edgeAttrFace.Length]; RawFace[] faces = new RawFace[raw.faceAttrEdge.Length]; geo.HasVertices = raw.vertexPositions != null; geo.HasUVs = raw.vertexUVs != null; geo.HasNormals = raw.vertexNormals != null; geo.HasTangents = raw.vertexTangents != null; if (geo.HasVertices) { for (int i = 0, j = 0; i < verts.Length; ++i) { verts[i].Position = new OpenTK.Vector3(raw.vertexPositions[j++], raw.vertexPositions[j++], raw.vertexPositions[j++]); } } if (geo.HasUVs) { for (int i = 0, j = 0; i < verts.Length; ++i) { verts[i].UV = new OpenTK.Vector2(raw.vertexUVs[j++], raw.vertexUVs[j++]); } } if (geo.HasNormals) { for (int i = 0, j = 0; i < verts.Length; ++i) { verts[i].Normal = new OpenTK.Vector3(raw.vertexNormals[j++], raw.vertexNormals[j++], raw.vertexNormals[j++]); } } if (geo.HasTangents) { for (int i = 0, j = 0; i < verts.Length; ++i) { verts[i].Tangent = new OpenTK.Vector3(raw.vertexTangents[j++], raw.vertexTangents[j++], raw.vertexTangents[j++]); } } for (int i = 0; i < verts.Length; ++i) { verts[i].Edge = raw.vertexAttrEdge[i]; } for (int i = 0; i < edges.Length; ++i) { edges[i].Next = raw.edgeAttrNext[i]; edges[i].Head = raw.edgeAttrHead[i]; edges[i].Opposite = raw.edgeAttrOpposite[i]; edges[i].Face = raw.edgeAttrFace[i]; } for (int i = 0; i < faces.Length; ++i) { faces[i].Edge = raw.faceAttrEdge[i]; } geo.vertices = verts.ToList(); geo.edges = edges.ToList(); geo.faces = faces.ToList(); } geo.UpdateBoundingBox(); geo.UpdateHasBoundary(); return(geo); }