public static WavefrontObjFile ToObj(NiFile model) { var obj = new WavefrontObjFile(); //var matrix = Matrix.RotationZ((float)Math.PI) * Matrix.RotationX(-(float)Math.PI/2f); float d90 = (float)Math.PI / 2f; var matrix = Matrix.Scaling(1, 1, -1) * Matrix.RotationYawPitchRoll(0, d90, 0); AddModelToObj(obj, model, matrix, new[] { Program.Arguments.NifLayer }, false); if (obj.MeshCount == 0) { AddModelToObj(obj, model, matrix, new string[0], true); } return(obj); }
public void Dispose() { if (ObjWriter == null) { return; } DoorWriter.Flush(); DoorWriter.Dispose(); GeomSetWriter.Flush(); GeomSetWriter.Dispose(); ObjWriter.Save(); if (ObjWriter.Empty) { File.Delete(ObjWriter.File); } ObjWriter = null; }
public Zone2Obj(Zone2 zone) { Zone = zone; if (!Directory.Exists("zones")) { Directory.CreateDirectory("zones"); } string filename = Path.Combine("zones", string.Format("zone{0:D3}", zone.ID)); DoorWriter = new DoorWriter(filename + ".doors"); GeomSetWriter = new GeomSetWriter(filename + ".geomset"); ObjWriter = new WavefrontObjFile(filename + ".obj") { Scale = MESH_SCALE }; GeomSetWriter.WriteLoadMesh(filename + ".obj"); FirstPass = !NavmeshMgr.IsPathingEnabled(zone); }
private static LosTreeType _LoadZone(Region region, Zone zone, string filename) { var(vertices, objects) = WavefrontObjFile.Load(zone, filename); if (vertices == null || vertices.Length == 0 || objects == null) { return(null); } var zoneMin = new Vector3(float.PositiveInfinity); var zoneMax = new Vector3(float.NegativeInfinity); foreach (var v in vertices) { if (v.Z <= 0 || v.Z > 65530) { continue; } zoneMin = Vector3.Min(zoneMin, v); zoneMax = Vector3.Max(zoneMax, v); } zoneMin.Z -= 500; zoneMax.Z += 500; var zoneTree = new LosTreeType(new AABoundingBox(zoneMin, zoneMax), 1); foreach (var faces in objects) { foreach (var(a, b, c) in faces) { zoneTree.AddObject(new Triangle(vertices, a, b, c)); } } if (log.IsDebugEnabled) { log.Debug($"[LosMgr] Zone {zone.ZoneSkinID} loaded: {objects.Count:N0} objects {objects.Select(o => o.Length).Sum():N0} faces {vertices.Length:N0} vertices"); } return(zoneTree); }
public static void AddModelToObj(WavefrontObjFile objFile, NiFile model, Matrix worldMatrix, string[] filter, bool exclude) { if (model == null) { return; } bool foundMesh = false; // find all trimeshs and tristrips foreach (NiObject obj in model.ObjectsByRef.Values) { var avNode = obj as NiAVObject; if (avNode == null || ((exclude && IsFiltered(avNode, filter)) || (!exclude && !IsFiltered(avNode, filter)))) { continue; } var shape = obj as NiTriShape; if (shape != null) { eFaceDrawMode mode = FindDrawMode(shape); foundMesh = true; Matrix myMatrix = ComputeWorldMatrix(shape) * worldMatrix; var data = shape.Data.Object as NiTriShapeData; if (data.Triangles.Length == 0) { continue; } var transformedVertices = new Vector3[data.Vertices.Length]; for (int i = 0; i < data.Vertices.Length; i++) { Vector4 transformedVector = Vector3.Transform(data.Vertices[i], myMatrix); transformedVertices[i] = new Vector3(transformedVector.X, transformedVector.Y, transformedVector.Z); } var triangles = new List <Triangle>(); // CCW if (mode == eFaceDrawMode.DRAW_BOTH || mode == eFaceDrawMode.DRAW_CCW || mode == eFaceDrawMode.DRAW_CCW_OR_BOTH) { for (int i = 0; i < data.Triangles.Length; i++) { triangles.Add(new Triangle(data.Triangles[i].Z, data.Triangles[i].Y, data.Triangles[i].X)); } } // CC if (mode == eFaceDrawMode.DRAW_BOTH || mode == eFaceDrawMode.DRAW_CW) { foreach (Triangle t in data.Triangles) { triangles.Add(t); } } objFile.AddMesh(transformedVertices, triangles.ToArray()); } var strips = obj as NiTriStrips; if (strips != null) { eFaceDrawMode mode = FindDrawMode(strips); foundMesh = true; Matrix myMatrix = ComputeWorldMatrix(strips) * worldMatrix; var data = strips.Data.Object as NiTriStripsData; var transformedVertices = new Vector3[data.Vertices.Length]; for (int i = 0; i < data.Vertices.Length; i++) { Vector4 transformedVector = Vector3.Transform(data.Vertices[i], myMatrix); transformedVertices[i] = new Vector3(transformedVector.X, transformedVector.Y, transformedVector.Z); } var triangles = new List <Triangle>(); foreach (var points in data.Points) { // CCW if (mode == eFaceDrawMode.DRAW_BOTH || mode == eFaceDrawMode.DRAW_CCW || mode == eFaceDrawMode.DRAW_CCW_OR_BOTH) { for (int i = 0; i < points.Length - 2; i++) { triangles.Add(i % 2 == 0 ? new Triangle(points[i + 2], points[i + 1], points[i + 0]) : new Triangle(points[i + 2], points[i + 0], points[i + 1])); } } // CC if (mode == eFaceDrawMode.DRAW_BOTH || mode == eFaceDrawMode.DRAW_CW) { for (int i = 0; i < points.Length - 2; i++) { triangles.Add(i % 2 == 0 ? new Triangle(points[i + 0], points[i + 1], points[i + 2]) : new Triangle(points[i + 0], points[i + 2], points[i + 1])); } } } objFile.AddMesh(transformedVertices, triangles.ToArray()); } } if (!foundMesh && filter[0] == "pickee") { // no pickee found, use collide Console.WriteLine("Warning: Using collidee!"); AddModelToObj(objFile, model, worldMatrix, new[] { "collide" }, false); } }