/// <summary> /// Renders a billboard along a line. /// </summary> /// <param name="pos">Start position.</param> /// <param name="p2">End position.</param> /// <param name="width">Width of the line.</param> /// <param name="facing">Facing target.</param> /// <param name="view">Relevant view.</param> public void RenderBilboardLine(Location pos, Location p2, float width, Location facing, View3D view) { Location center = (pos + p2) * 0.5; double len = (center - facing).Length(); Location lookdir = (center - facing) / len; double len2 = (p2 - pos).Length(); if (len < 0.001 || len2 < 0.001) { return; } Location updir = (p2 - pos) / len2; Location right = updir.CrossProduct(lookdir); Matrix4d mat = Matrix4d.CreateTranslation(-0.5f, -0.5f, 0f) * Matrix4d.Scale((float)len2 * 0.5f, width, 1f); Matrix4d m2 = new Matrix4d(right.X, updir.X, lookdir.X, center.X, right.Y, updir.Y, lookdir.Y, center.Y, right.Z, updir.Z, lookdir.Z, center.Z, 0, 0, 0, 1); m2.Transpose(); mat *= m2; view.SetMatrix(2, mat); GL.BindVertexArray(Square._VAO); GL.DrawElements(PrimitiveType.Triangles, 6, DrawElementsType.UnsignedInt, IntPtr.Zero); GL.BindVertexArray(0); }
/// <summary> /// Render a cylinder between two points. /// </summary> /// <param name="start">The initial point.</param> /// <param name="end">The ending point.</param> /// <param name="width">The width of the cylinder.</param> /// <param name="view">The relevant view.</param> public void RenderCylinder(Location start, Location end, float width, View3D view) { float len = (float)(end - start).Length(); Location vecang = Utilities.VectorToAngles(start - end); vecang.Yaw += 180; Matrix4d mat = Matrix4d.CreateRotationY((float)(90 * Utilities.PI180)) * Matrix4d.Scale(len, width, width) * Matrix4d.CreateRotationY((float)(vecang.Y * Utilities.PI180)) * Matrix4d.CreateRotationZ((float)(vecang.Z * Utilities.PI180)) * Matrix4d.CreateTranslation(start.ToOpenTK3D()); view.SetMatrix(2, mat); Models.Cylinder.Draw(); // TODO: Models reference in constructor - or client reference? }
/// <summary> /// Render a cylinder between two points. /// </summary> /// <param name="context">The sourcing render context.</param> /// <param name="start">The initial point.</param> /// <param name="end">The ending point.</param> /// <param name="width">The width of the cylinder.</param> /// <param name="view">The relevant view.</param> public void RenderCylinder(RenderContext context, Location start, Location end, float width, View3D view) { float len = (float)(end - start).Length(); Location vecang = MathUtilities.VectorToAngles(start - end); vecang.Yaw += 180; Matrix4d mat = Matrix4d.CreateRotationY((float)(90 * MathUtilities.PI180)) * Matrix4d.Scale(len, width, width) * Matrix4d.CreateRotationY((float)(vecang.Y * MathUtilities.PI180)) * Matrix4d.CreateRotationZ((float)(vecang.Z * MathUtilities.PI180)) * Matrix4d.CreateTranslation(start.ToOpenTK3D()); view.SetMatrix(2, mat); Models.Cylinder.Draw(context); }
/// <summary> /// Render a line between two points. /// </summary> /// <param name="start">The initial point.</param> /// <param name="end">The ending point.</param> /// <param name="view">The relevant view.</param> public void RenderLine(Location start, Location end, View3D view) { // TODO: Efficiency! float len = (float)(end - start).Length(); Location vecang = Utilities.VectorToAngles(start - end); vecang.Yaw += 180; Matrix4d mat = Matrix4d.Scale(len, 1, 1) * Matrix4d.CreateRotationY((float)(vecang.Y * Utilities.PI180)) * Matrix4d.CreateRotationZ((float)(vecang.Z * Utilities.PI180)) * Matrix4d.CreateTranslation(start.ToOpenTK3D()); view.SetMatrix(2, mat); GL.BindVertexArray(Line._VAO); GL.DrawElements(PrimitiveType.Lines, 2, DrawElementsType.UnsignedInt, IntPtr.Zero); }
/// <summary> /// Renders a flat billboard (a sprite). /// </summary> /// <param name="center">The center of it.</param> /// <param name="scale">The scale of it.</param> /// <param name="facing">Where it's facing.</param> /// <param name="view">The relevant view.</param> /// <param name="pzr">Z rotation if any.</param> public void RenderBillboard(Location center, Location scale, Location facing, View3D view, float pzr = 0f) { Location lookdir = (facing - center).Normalize(); Location right = lookdir.CrossProduct(Location.UnitZ); // TODO: Camera up vector! Location updir = right.CrossProduct(lookdir); Matrix4d mat = Matrix4d.CreateTranslation(-0.5f, -0.5f, 0f) * Matrix4d.Scale((float)scale.X, (float)scale.Y, (float)scale.Z); Matrix4d m2 = new Matrix4d(right.X, updir.X, lookdir.X, center.X, right.Y, updir.Y, lookdir.Y, center.Y, right.Z, updir.Z, lookdir.Z, center.Z, 0, 0, 0, 1); m2.Transpose(); mat *= m2; view.SetMatrix(2, mat); GL.BindVertexArray(Square._VAO); GL.DrawElements(PrimitiveType.Triangles, 6, DrawElementsType.UnsignedInt, IntPtr.Zero); GL.BindVertexArray(0); /* * // TODO: Quaternion magic? * Location relang = Utilities.VectorToAngles(pos - facing); * if (relang.IsInfinite() || relang.IsNaN()) * { * throw new Exception("Unable to handle billboard: relang=" + relang); * } * Matrix4d mat = * Matrix4d.Scale(ClientUtilities.ConvertD(scale)) * Matrix4d.CreateTranslation(-0.5f, -0.5f, 0f) * Matrix4d.CreateRotationY((float)((relang.Y - 90) * Utilities.PI180)) * Matrix4d.CreateRotationZ((float)(relang.Z * Utilities.PI180)) * Matrix4d.CreateTranslation(ClientUtilities.ConvertD(pos + new Location(scale.X * 0.5, scale.Y * 0.5, 0.0))); * Client.Central.MainWorldView.SetMatrix(2, mat); // TODO: Client reference! * GL.BindVertexArray(Square._VAO); * GL.DrawElements(PrimitiveType.Triangles, 6, DrawElementsType.UnsignedInt, IntPtr.Zero); * GL.BindVertexArray(0); */ }
/// <summary> /// Renders a line box. /// </summary> /// <param name="min">The minimum coordinate.</param> /// <param name="max">The maximmum coordinate.</param> /// <param name="view">The relevant view.</param> /// <param name="rot">Any rotation.</param> public void RenderLineBox(Location min, Location max, View3D view, Matrix4d?rot = null) { if (min.IsNaN() || min.IsInfinite() || max.IsNaN() || max.IsInfinite()) { SysConsole.Output(OutputType.WARNING, "Invalid line box from " + min + " to " + max); SysConsole.Output(OutputType.DEBUG, Environment.StackTrace); return; } GL.ActiveTexture(TextureUnit.Texture0); TEngine.White.Bind(); GraphicsUtil.CheckError("RenderLineBox: BindTexture"); Location halfsize = (max - min) * 0.5; if ((min + halfsize) == Location.Zero) { return; // ??? } if (Math.Abs(min.X + halfsize.X) < 1 || Math.Abs(min.Y + halfsize.Y) < 1 || Math.Abs(min.Z + halfsize.Z) < 1) { return; // ??? } if (Math.Abs(min.X) < 1 || Math.Abs(min.Y) < 1 || Math.Abs(min.Z) < 1) { return; // ??? } Matrix4d mat = Matrix4d.Scale(halfsize.ToOpenTK3D()) * (rot != null && rot.HasValue ? rot.Value : Matrix4d.Identity) * Matrix4d.CreateTranslation((min + halfsize).ToOpenTK3D()); view.SetMatrix(2, mat); // TODO: Client reference! GraphicsUtil.CheckError("RenderLineBox: SetMatrix"); GL.BindVertexArray(Box._VAO); GraphicsUtil.CheckError("RenderLineBox: Bind VAO"); GL.DrawElements(PrimitiveType.Lines, 24, DrawElementsType.UnsignedInt, IntPtr.Zero); GraphicsUtil.CheckError("RenderLineBox: Pass"); }