/// <summary> /// Creates a Model using data from an obj file. If unable to parse the file, null will be returned. /// </summary> public Model LoadObj(FileStream stream) { StreamReader reader = new StreamReader(stream); Dictionary<string, int> vectorMap = new Dictionary<string, int>(); List<Vector3> points = new List<Vector3>(); List<Vector3> normals = new List<Vector3>(); List<Vector2> texCoords = new List<Vector2>(); Model model = new Model(); model.Mesh = new Mesh(); string mtlFileName = ""; string line; while ((line = reader.ReadLine()) != null) { line = line.Trim(splitChar); string[] parameters = line.Split(splitChar); switch (parameters[0]) { case "mtllib": mtlFileName = string.Join(splitChar.ToString(), parameters, 1, parameters.Length - 1); break; case "p": // Point break; case "v": // Vertex Vector3 vert; if (!parseVector3(parameters, out vert)) { return null; } points.Add(vert); break; case "vt": // TexCoord Vector2 tex; if (!parseVector2(parameters, out tex)) { return null; } texCoords.Add(tex); break; case "vn": // Normal Vector3 norm; if (!parseVector3(parameters, out norm)) { return null; } normals.Add(norm); break; case "f": // Face if (!parseFace(model, parameters, points, normals, texCoords, vectorMap)) { return null; } break; } } string mtlFilePath = Path.Combine(Path.GetDirectoryName(stream.Name), mtlFileName); model.SetTexture(LoadMtl(mtlFilePath)); return model; }
/// <summary> /// Draw the edges for each portal potentially including motion blur. /// </summary> /// <param name="portalViewList"></param> /// <param name="cam"></param> private void RenderPortalEdges(List<PortalView> portalViewList, ICamera2 cam) { int iterations = Math.Min(portalViewList.Count, StencilMaxValue); /* Escape early if there aren't any visible portals. * The first iteration is just for the main view which doesn't have portal edges.*/ if (iterations <= 1) { return; } GL.Clear(ClearBufferMask.DepthBufferBit); SetEnable(EnableCap.StencilTest, false); GL.Disable(EnableCap.DepthTest); GL.Clear(ClearBufferMask.StencilBufferBit); Clipper c = new Clipper(); c.StrictlySimple = true; Model portalEdges = new Model(); portalEdges.SetTexture(Textures["lineBlur.png"]); SetEnable(EnableCap.Blend, true); for (int i = 1; i < iterations; i++) { for (int j = 0; j < 2; j++) { LineF line = portalViewList[i].FovLines[j]; float minWidth = Math.Abs(cam.GetWorldTransform().Size) / 300; double angleDiff = GetLineBlurAngle(line, portalViewList[i].FovLinesPrevious[j]); float widthEnd = (float)Math.Tan(angleDiff) * line.Length; widthEnd = Math.Max(widthEnd, minWidth); Vector2[] lineWidth = PolygonFactory.CreateLineWidth(line, minWidth); Vector2 camPos = cam.GetWorldTransform().Position; Vector2[] lineWidthOff = Vector2Ext.Transform(lineWidth, Matrix4.CreateTranslation(new Vector3(-camPos))); Vector2[] lineTarget = PolygonFactory.CreateLineWidth(line.Translate(-camPos), minWidth, widthEnd); Matrix4d homography = Matrix4d.CreateTranslation(new Vector3d((Vector2d)(-camPos))); homography *= MathExt.GetHomography(lineWidthOff, lineTarget); homography *= Matrix4d.CreateTranslation(new Vector3d((Vector2d)camPos)); bool obscured = true; for (int k = 0; k < portalViewList[i].Parent.Paths.Count; k++) { List<IntPoint> path = portalViewList[i].Parent.Paths[k]; if (Clipper.PointInPolygon(ClipperConvert.ToIntPoint(line[0]), path) == 1) { obscured = false; break; } } if (obscured) { continue; } foreach (PortalView p in portalViewList[i].Parent.Children) { if (p == portalViewList[i]) { continue; } if (p.PortalLine.IsInsideFOV(camPos, line[0])) { obscured = true; break; } } if (obscured) { continue; } int index = ModelFactory.AddPolygon((Mesh)portalEdges.Mesh, lineWidth); IMesh mesh = portalEdges.Mesh; for (int k = index; k < mesh.GetVertices().Count; k++) { Vertex vertex = mesh.GetVertices()[k]; Vector3 pos = Vector3Ext.Transform(vertex.Position, homography); pos.Z = CameraExt.UnitZToWorld(cam, pos.Z); Vector2 texCoord; Vector2 v = new Vector2(vertex.Position.X, vertex.Position.Y); double distance = MathExt.PointLineDistance(v, line.GetPerpendicularLeft(), false); double texCoordX = MathExt.PointLineDistance(v, line, false) / minWidth; if (line.GetSideOf(v) == Side.Left) { texCoordX *= -1; } texCoordX += 0.5; texCoord = new Vector2((float)texCoordX, (float)(distance / line.Length)); mesh.GetVertices()[k] = new Vertex(pos, texCoord); } } } RenderModel(portalEdges, CameraExt.GetViewMatrix(cam, false)); SetEnable(EnableCap.Blend, false); GL.Enable(EnableCap.DepthTest); }