public void Split() { R3DBox pBox = CentralPointsBoundingBox; float middleX = (pBox.Min.X + pBox.Max.X) / 2; float middleZ = (pBox.Min.Z + pBox.Max.Z) / 2; // Node 1 (bottom-left) Vector3 node1Min = new Vector3(pBox.Min.X, pBox.Min.Y, pBox.Min.Z); Vector3 node1Max = new Vector3(middleX, pBox.Max.Y, middleZ); NVRNode node1 = new NVRNode(new R3DBox(node1Min, node1Max), this); // Node 2 (top-left) Vector3 node2Min = new Vector3(pBox.Min.X, pBox.Min.Y, middleZ); Vector3 node2Max = new Vector3(middleX, pBox.Max.Y, pBox.Max.Z); NVRNode node2 = new NVRNode(new R3DBox(node2Min, node2Max), this); // Node 3 (top-right) Vector3 node3Min = new Vector3(middleX, pBox.Min.Y, middleZ); Vector3 node3Max = new Vector3(pBox.Max.X, pBox.Max.Y, pBox.Max.Z); NVRNode node3 = new NVRNode(new R3DBox(node3Min, node3Max), this); // Node 4 (bottom-right) Vector3 node4Min = new Vector3(middleX, pBox.Min.Y, pBox.Min.Z); Vector3 node4Max = new Vector3(pBox.Max.X, pBox.Max.Y, middleZ); NVRNode node4 = new NVRNode(new R3DBox(node4Min, node4Max), this); foreach (NVRNode childNode in Children) { Vector3 proportions = childNode.CentralPointsBoundingBox.GetProportions(); if ((childNode.Meshes.Count > 1) && (proportions.X > 100 || proportions.Z > 100)) { childNode.Split(); } } }
public Tuple <R3DSphere, R3DBox> CalculateBoundingGeometry() { R3DBox box = CalculateBoundingBox(); R3DSphere sphere = CalculateSphere(box); return(new Tuple <R3DSphere, R3DBox>(sphere, box)); }
public NVRNode(List <NVRMesh> meshes) { // Used when creating the big parent node. this.Meshes.AddRange(meshes); this.BoundingBox = this.CalculateBoundingBox(); this.CentralPointsBoundingBox = this.CalculateCentralPointsBoundingBox(); }
/// <summary> /// Calculates a Bounding Sphere of this <see cref="SKNSubmesh"/> /// </summary> public R3DSphere CalculateBoundingSphere() { R3DBox box = CalculateBoundingBox(); Vector3 centralPoint = CalculateCentralPoint(); return(new R3DSphere(centralPoint, Vector3.Distance(centralPoint, box.Max))); }
/// <summary> /// Calculates the Bounding Sphere of this <see cref="WGEOModel"/> from the specified <see cref="R3DBox"/> /// </summary> /// <param name="box"><see cref="R3DBox"/> to use for calculation</param> public R3DSphere CalculateSphere(R3DBox box) { Vector3 centralPoint = new Vector3(0.5f * (this.BoundingBox.Max.X + this.BoundingBox.Min.X), 0.5f * (this.BoundingBox.Max.Y + this.BoundingBox.Min.Y), 0.5f * (this.BoundingBox.Max.Z + this.BoundingBox.Min.Z)); return(new R3DSphere(centralPoint, Vector3.Distance(centralPoint, box.Max))); }
/// <summary> /// Calculates the Central Point of this <see cref="SKNSubmesh"/> /// </summary> public Vector3 CalculateCentralPoint() { R3DBox box = CalculateBoundingBox(); return(new Vector3(0.5f * (box.Min.X + box.Max.X), 0.5f * (box.Min.Y + box.Max.Y), 0.5f * (box.Min.Z + box.Max.Z))); }
public NVRNode(R3DBox centralPointsBox, NVRNode parentNode) { // Used if we create it from a parent node. this.CentralPointsBoundingBox = centralPointsBox; this.Meshes.AddRange(parentNode.Meshes.FindAll(x => this.CentralPointsBoundingBox.ContainsPoint(x.BoundingSphere.Position))); parentNode.Children.Add(this); this.BoundingBox = this.CalculateBoundingBox(); }
public SimpleSkin(Stream stream) { using (BinaryReader br = new BinaryReader(stream)) { uint magic = br.ReadUInt32(); if (magic != 0x00112233) { throw new Exception("Not a valid SKN file"); } ushort major = br.ReadUInt16(); ushort minor = br.ReadUInt16(); if (major != 2 && major != 4 && minor != 1) { throw new Exception("This SKN version is not supported"); } uint submeshCount = br.ReadUInt32(); for (int i = 0; i < submeshCount; i++) { this.Submeshes.Add(new SimpleSkinSubmesh(br)); } if (major == 4) { uint unknown = br.ReadUInt32(); } uint indexCount = br.ReadUInt32(); uint vertexCount = br.ReadUInt32(); uint vertexSize = major == 4 ? br.ReadUInt32() : 52; SimpleSkinVertexType vertexType = major == 4 ? (SimpleSkinVertexType)br.ReadUInt32() : SimpleSkinVertexType.Basic; R3DBox boundingBox = major == 4 ? new R3DBox(br) : R3DBox.Infinite; R3DSphere boundingSphere = major == 4 ? new R3DSphere(br) : R3DSphere.Infinite; List <ushort> indices = new List <ushort>(); List <SimpleSkinVertex> vertices = new List <SimpleSkinVertex>(); for (int i = 0; i < indexCount; i++) { indices.Add(br.ReadUInt16()); } for (int i = 0; i < vertexCount; i++) { vertices.Add(new SimpleSkinVertex(br, vertexType)); } foreach (SimpleSkinSubmesh submesh in this.Submeshes) { List <ushort> submeshIndices = indices.GetRange((int)submesh._startIndex, (int)submesh._indexCount); ushort minIndex = submeshIndices.Min(); submesh.Indices = submeshIndices.Select(x => x -= minIndex).ToList(); submesh.Vertices = vertices.GetRange((int)submesh._startVertex, (int)submesh._vertexCount); } } }
public static StaticObject ReadSCB(Stream stream) { using (BinaryReader br = new BinaryReader(stream)) { string magic = Encoding.ASCII.GetString(br.ReadBytes(8)); if (magic != "r3d2Mesh") { throw new Exception("This is not a valid SCB file"); } ushort major = br.ReadUInt16(); ushort minor = br.ReadUInt16(); if (major != 3 && major != 2 && minor != 1) //There are versions [2][1] and [1][1] aswell { throw new Exception(string.Format("The Version: {0}.{1} is not supported", major, minor)); } string name = Encoding.ASCII.GetString(br.ReadBytes(128)).Replace("\0", ""); uint vertexCount = br.ReadUInt32(); uint faceCount = br.ReadUInt32(); StaticObjectFlags flags = (StaticObjectFlags)br.ReadUInt32(); R3DBox boundingBox = new R3DBox(br); bool hasVertexColors = false; if (major == 3 && minor == 2) { hasVertexColors = br.ReadUInt32() == 1; } List <Vector3> vertices = new List <Vector3>((int)vertexCount); List <Color> vertexColors = new List <Color>((int)vertexCount); for (int i = 0; i < vertexCount; i++) { vertices.Add(new Vector3(br)); } if (hasVertexColors) { for (int i = 0; i < vertexCount; i++) { vertexColors.Add(br.ReadColor(ColorFormat.RgbaU8)); } } Vector3 centralPoint = new Vector3(br); List <StaticObjectFace> faces = new List <StaticObjectFace>((int)faceCount); for (int i = 0; i < faceCount; i++) { faces.Add(new StaticObjectFace(br)); } return(new StaticObject(name, CreateSubmeshes(vertices, vertexColors, faces), centralPoint)); } }
/// <summary> /// Initializes a new <see cref="MOBObject"/> from a <see cref="BinaryReader"/> /// </summary> /// <param name="br">The <see cref="BinaryReader"/> to read from</param> public MOBObject(BinaryReader br) { this.Name = Encoding.ASCII.GetString(br.ReadBytes(62)).Replace("\0", ""); this.Type = (MOBObjectType)br.ReadByte(); this.IgnoreCollisionOnPlacement = br.ReadBoolean(); this.Position = new Vector3(br); this.Rotation = new Vector3(br); this.Scale = new Vector3(br); this.BoundingBox = new R3DBox(br); this.SkinID = br.ReadUInt32(); }
/// <summary> /// Initializes a new <see cref="MOBObject"/> /// </summary> /// <param name="name">Name of this <see cref="MOBObject"/></param> /// <param name="type">Type of this <see cref="MOBObject"/></param> /// <param name="skinID">Skin ID of this <see cref="MOBObject"/></param> /// <param name="ignoreCollisionOnPlacement">Collision flag of this <see cref="MOBObject"/></param> /// <param name="position">Position of this <see cref="MOBObject"/></param> /// <param name="rotation">Scale of this <see cref="MOBObject"/></param> /// <param name="scale">Scale of this <see cref="MOBObject"/></param> /// <param name="boundingBox">Bounding Box of this <see cref="MOBObject"/></param> public MOBObject(string name, MOBObjectType type, uint skinID, bool ignoreCollisionOnPlacement, Vector3 position, Vector3 rotation, Vector3 scale, R3DBox boundingBox) { this.Name = name; this.Type = type; this.SkinID = skinID; this.IgnoreCollisionOnPlacement = ignoreCollisionOnPlacement; this.Position = position; this.Rotation = rotation; this.Scale = scale; this.BoundingBox = boundingBox; }
public R3DSphere CalculateSphere() { R3DBox box = CalculateBoundingBox(); Vector3 centralPoint = new Vector3 ( 0.5f * (BoundingBox.Max.X + BoundingBox.Min.X), 0.5f * (BoundingBox.Max.Y + BoundingBox.Min.Y), 0.5f * (BoundingBox.Max.Z + BoundingBox.Min.Z) ); return(new R3DSphere(centralPoint, Vector3.Distance(centralPoint, box.Max))); }
private R3DBox CalculateBoundingBox() { if (Meshes.Count > 0) { Vector3 min = new Vector3(Meshes[0].BoundingBox.Min.X, Meshes[0].BoundingBox.Min.Y, Meshes[0].BoundingBox.Min.Z); Vector3 max = new Vector3(Meshes[0].BoundingBox.Max.X, Meshes[0].BoundingBox.Max.Y, Meshes[0].BoundingBox.Max.Z); for (int i = 1; i < Meshes.Count; i++) { R3DBox box = Meshes[i].BoundingBox; if (box.Min.X < min.X) { min.X = box.Min.X; } if (box.Min.Y < min.Y) { min.Y = box.Min.Y; } if (box.Min.Z < min.Z) { min.Z = box.Min.Z; } if (box.Max.X > max.X) { max.X = box.Max.X; } if (box.Max.Y > max.Y) { max.Y = box.Max.Y; } if (box.Max.Z > max.Z) { max.Z = box.Max.Z; } } return(new R3DBox(min, max)); } else { // No meshes inside, set bounding box to return(new R3DBox(new Vector3(NullCoordinate, NullCoordinate, NullCoordinate), new Vector3(NullCoordinate, NullCoordinate, NullCoordinate))); } }
private static void DumpSimpleSkinInfo(SimpleSkin simpleSkin) { Console.WriteLine("----------SIMPLE SKIN INFO----------"); R3DBox boundingBox = simpleSkin.GetBoundingBox(); Console.WriteLine("Bounding Box:"); Console.WriteLine("\t Min: " + boundingBox.Min.ToString()); Console.WriteLine("\t Max: " + boundingBox.Max.ToString()); Console.WriteLine("Submesh Count: " + simpleSkin.Submeshes.Count); foreach (SimpleSkinSubmesh submesh in simpleSkin.Submeshes) { Console.WriteLine("--- SUBMESH ---"); Console.WriteLine("Material: " + submesh.Name); Console.WriteLine("Vertex Count: " + submesh.Vertices.Count); Console.WriteLine("Index Count: " + submesh.Indices.Count); Console.WriteLine("Face Count: " + submesh.Indices.Count / 3); Console.WriteLine(); } }
/// <summary> /// Calculates the Central Point of this <see cref="SKNSubmesh"/> from a <see cref="R3DBox"/> of this <see cref="SKNSubmesh"/> /// </summary> /// <param name="box"><see cref="R3DBox"/> of this <see cref="SKNSubmesh"/></param> public Vector3 CalculateCentralPoint(R3DBox box) { return(new Vector3(0.5f * (box.Min.X + box.Max.X), 0.5f * (box.Min.Y + box.Max.Y), 0.5f * (box.Min.Z + box.Max.Z))); }
/// <summary> /// Writes this <see cref="SKNFile"/> into the specified <see cref="Stream"/> /// </summary> /// <param name="stream">The <see cref="Stream"/> to write to</param> public void Write(Stream stream) { using (BinaryWriter bw = new BinaryWriter(stream)) { bw.Write(0x00112233); bw.Write((ushort)4); bw.Write((ushort)1); bw.Write(this.Submeshes.Count); bool hasTangent = false; uint indexCount = 0; uint vertexCount = 0; foreach (SKNSubmesh submesh in this.Submeshes) { if (!hasTangent) { foreach (SKNVertex vertex in submesh.Vertices) { if (vertex.Tangent != null) { hasTangent = true; } } } submesh.Write(bw); indexCount += (uint)submesh.Indices.Count; vertexCount += (uint)submesh.Vertices.Count; } bw.Write((uint)0); bw.Write(indexCount); bw.Write(vertexCount); if (hasTangent) { bw.Write((uint)56); bw.Write((uint)1); } else { bw.Write((uint)52); bw.Write((uint)0); } R3DBox box = CalculateBoundingBox(); box.Write(bw); CalculateBoundingSphere(box).Write(bw); foreach (SKNSubmesh submesh in this.Submeshes) { foreach (ushort index in submesh.Indices) { bw.Write(index); } } foreach (SKNSubmesh submesh in this.Submeshes) { foreach (SKNVertex vertex in submesh.Vertices) { if (hasTangent && vertex.Tangent == null) { vertex.Tangent = new Vector4Byte(255, 255, 255, 255); } else if (!hasTangent && vertex.Tangent != null) { vertex.Tangent = null; } vertex.Write(bw); } } bw.Write(new byte[12]); } }
public void Write(Stream stream) { using (BinaryWriter bw = new BinaryWriter(stream)) { bw.Write(0x00112233); bw.Write((ushort)4); bw.Write((ushort)1); bw.Write(this.Submeshes.Count); bool hasVertexColors = false; uint indexCount = 0; uint vertexCount = 0; foreach (SimpleSkinSubmesh submesh in this.Submeshes) { if (!hasVertexColors) { foreach (SimpleSkinVertex vertex in submesh.Vertices) { if (vertex.Color != null) { hasVertexColors = true; break; } } } submesh.Write(bw, vertexCount, indexCount); indexCount += (uint)submesh.Indices.Count; vertexCount += (uint)submesh.Vertices.Count; } bw.Write((uint)0); //Flags bw.Write(indexCount); bw.Write(vertexCount); if (hasVertexColors) { bw.Write((uint)56); bw.Write((uint)SimpleSkinVertexType.Color); } else { bw.Write((uint)52); bw.Write((uint)SimpleSkinVertexType.Basic); } R3DBox box = GetBoundingBox(); box.Write(bw); box.GetBoundingSphere().Write(bw); ushort indexOffset = 0; foreach (SimpleSkinSubmesh submesh in this.Submeshes) { foreach (ushort index in submesh.Indices.Select(x => x += indexOffset)) { bw.Write(index); } indexOffset += submesh.Indices.Max(); } foreach (SimpleSkinSubmesh submesh in this.Submeshes) { foreach (SimpleSkinVertex vertex in submesh.Vertices) { vertex.Write(bw, hasVertexColors ? SimpleSkinVertexType.Color : SimpleSkinVertexType.Basic); } } bw.Write(new byte[12]); //End tab } }
public SimpleSkin(Stream stream) { using (BinaryReader br = new BinaryReader(stream)) { uint magic = br.ReadUInt32(); if (magic != 0x00112233) { throw new InvalidFileSignatureException(); } ushort major = br.ReadUInt16(); ushort minor = br.ReadUInt16(); if (major != 0 && major != 2 && major != 4 && minor != 1) { throw new UnsupportedFileVersionException(); } uint indexCount = 0; uint vertexCount = 0; SimpleSkinVertexType vertexType = SimpleSkinVertexType.Basic; if (major == 0) { indexCount = br.ReadUInt32(); vertexCount = br.ReadUInt32(); } else { uint submeshCount = br.ReadUInt32(); for (int i = 0; i < submeshCount; i++) { this.Submeshes.Add(new SimpleSkinSubmesh(br)); } if (major == 4) { uint flags = br.ReadUInt32(); } indexCount = br.ReadUInt32(); vertexCount = br.ReadUInt32(); uint vertexSize = major == 4 ? br.ReadUInt32() : 52; vertexType = major == 4 ? (SimpleSkinVertexType)br.ReadUInt32() : SimpleSkinVertexType.Basic; R3DBox boundingBox = major == 4 ? new R3DBox(br) : new R3DBox(Vector3.Zero, Vector3.Zero); R3DSphere boundingSphere = major == 4 ? new R3DSphere(br) : R3DSphere.Infinite; } List <ushort> indices = new List <ushort>(); List <SimpleSkinVertex> vertices = new List <SimpleSkinVertex>(); for (int i = 0; i < indexCount; i++) { indices.Add(br.ReadUInt16()); } for (int i = 0; i < vertexCount; i++) { vertices.Add(new SimpleSkinVertex(br, vertexType)); } if (major == 0) { this.Submeshes.Add(new SimpleSkinSubmesh("Base", indices, vertices)); } else { foreach (SimpleSkinSubmesh submesh in this.Submeshes) { List <ushort> submeshIndices = indices.GetRange((int)submesh._startIndex, (int)submesh._indexCount); ushort minIndex = submeshIndices.Min(); submesh.Indices = submeshIndices.Select(x => x -= minIndex).ToList(); submesh.Vertices = vertices.GetRange((int)submesh._startVertex, (int)submesh._vertexCount); } } } }
/// <summary> /// Calculates a Bounding Sphere from a <see cref="R3DBox"/> and a Central Point of this <see cref="SKNSubmesh"/> /// </summary> /// <param name="box"><see cref="R3DBox"/> of this <see cref="SKNSubmesh"/></param> /// <param name="centralPoint">Position of the <see cref="R3DSphere"/></param> public R3DSphere CalculateBoundingSphere(R3DBox box, Vector3 centralPoint) { return(new R3DSphere(centralPoint, Vector3.Distance(centralPoint, box.Max))); }
/// <summary> /// Initializes a new <see cref="SKNFile"/> from a <see cref="Stream"/> /// </summary> /// <param name="stream">The <see cref="Stream"/> to read from</param> public SKNFile(Stream stream) { using (BinaryReader br = new BinaryReader(stream)) { uint magic = br.ReadUInt32(); if (magic != 0x00112233) { throw new Exception("Not a valid SKN file"); } ushort major = br.ReadUInt16(); ushort minor = br.ReadUInt16(); if (major != 2 && major != 4 && minor != 1) { throw new Exception("This SKN version is not supported"); } uint submeshCount = br.ReadUInt32(); for (int i = 0; i < submeshCount; i++) { this.Submeshes.Add(new SKNSubmesh(this, br)); } if (major == 4) { uint unknown = br.ReadUInt32(); } uint indexCount = br.ReadUInt32(); uint vertexCount = br.ReadUInt32(); uint vertexSize; bool isTangent = false; R3DBox boundingBox; R3DSphere boundingSphere; if (major == 4) { vertexSize = br.ReadUInt32(); isTangent = br.ReadUInt32() == 1; boundingBox = new R3DBox(br); boundingSphere = new R3DSphere(br); } List <ushort> indices = new List <ushort>(); List <SKNVertex> vertices = new List <SKNVertex>(); for (int i = 0; i < indexCount; i++) { indices.Add(br.ReadUInt16()); } for (int i = 0; i < vertexCount; i++) { vertices.Add(new SKNVertex(br, isTangent)); } foreach (SKNSubmesh submesh in this.Submeshes) { submesh.Indices = indices.GetRange((int)submesh._startIndex, (int)submesh._indexCount); submesh.Vertices = vertices.GetRange((int)submesh._startVertex, (int)submesh._vertexCount); } } }