From 3f536bd103667349eb34e22c8d6fb439c263e4fa Mon Sep 17 00:00:00 2001 From: mono Date: Mon, 25 Feb 2019 21:00:59 +0100 Subject: [PATCH] =?UTF-8?q?Habe=20eigene=20Vektor-Implementationen=20hinzu?= =?UTF-8?q?gef=C3=BCgt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/JuicyGraphics.csproj | 12 +- src/JuicyGraphics/{Program.cs => App.cs} | 5 +- src/JuicyGraphics/math/doubleExtentions.cs | 58 ++ .../math/normalizeVectorException.cs | 23 + src/JuicyGraphics/math/vec2.cs | 637 ++++++++++++ src/JuicyGraphics/math/vec3.cs | 956 ++++++++++++++++++ .../graphicalObjects/gridBackground.cs | 10 +- src/JuicyGraphics/renderer/stain.cs | 16 + .../renderer/stainGraphicTexture.cs | 10 + src/SharpGL/OpenGL.cs | 1 - 10 files changed, 1711 insertions(+), 17 deletions(-) rename src/JuicyGraphics/{Program.cs => App.cs} (78%) create mode 100644 src/JuicyGraphics/math/doubleExtentions.cs create mode 100644 src/JuicyGraphics/math/normalizeVectorException.cs create mode 100644 src/JuicyGraphics/math/vec2.cs create mode 100644 src/JuicyGraphics/math/vec3.cs create mode 100644 src/JuicyGraphics/renderer/stain.cs create mode 100644 src/JuicyGraphics/renderer/stainGraphicTexture.cs diff --git a/src/JuicyGraphics.csproj b/src/JuicyGraphics.csproj index 3b59ab8..4cbde03 100644 --- a/src/JuicyGraphics.csproj +++ b/src/JuicyGraphics.csproj @@ -51,7 +51,13 @@ + + + + + + @@ -66,7 +72,7 @@ mainForm.cs - + @@ -124,8 +130,6 @@ - - - + \ No newline at end of file diff --git a/src/JuicyGraphics/Program.cs b/src/JuicyGraphics/App.cs similarity index 78% rename from src/JuicyGraphics/Program.cs rename to src/JuicyGraphics/App.cs index 24c3c07..6ad3f1c 100644 --- a/src/JuicyGraphics/Program.cs +++ b/src/JuicyGraphics/App.cs @@ -1,11 +1,8 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; using System.Windows.Forms; namespace JuicyGraphics { - static class Program { + static class app { /// /// The main entry point for the application. /// diff --git a/src/JuicyGraphics/math/doubleExtentions.cs b/src/JuicyGraphics/math/doubleExtentions.cs new file mode 100644 index 0000000..3edd0fb --- /dev/null +++ b/src/JuicyGraphics/math/doubleExtentions.cs @@ -0,0 +1,58 @@ +using System; + +namespace JuicyGraphics.Mathematics { + + public static class doubleExtension { + public static bool almostEqualsWithAbsTolerance(this double a, double b, double maxAbsoluteError) { + double diff = Math.Abs(a - b); + + if (a.Equals(b)) { + return true; + } + + return diff <= maxAbsoluteError; + } + + public static bool almostEqualsWithAbsOrRelativeTolerance( + this double a, + double b, + double maxAbsoluteError, + double maxRelativeError) { + if (almostEqualsWithAbsTolerance(a, b, maxAbsoluteError)) { + return true; + } + + double absA = Math.Abs(a); + double absB = Math.Abs(b); + + double relativeError; + if (absB > absA) { + relativeError = Math.Abs((a - b) / b); + } + else { + relativeError = Math.Abs((a - b) / a); + } + + return relativeError <= maxRelativeError; + } + + public static bool almostEqualsWithAbsOrUlpsTolerance( + this double a, + double b, + double maxAbsoluteError, + long maxUlps) { + if (almostEqualsWithAbsTolerance(a, b, maxAbsoluteError)) { + return true; + } + + long longA = BitConverter.DoubleToInt64Bits(a); + longA = longA < 0 ? (long)(0x8000000000000000 - (ulong)longA) : longA; + + long longB = BitConverter.DoubleToInt64Bits(b); + longB = longB < 0 ? (long)(0x8000000000000000 - (ulong)longB) : longB; + + long diff = Math.Abs(longA - longB); + return diff <= maxUlps; + } + } +} \ No newline at end of file diff --git a/src/JuicyGraphics/math/normalizeVectorException.cs b/src/JuicyGraphics/math/normalizeVectorException.cs new file mode 100644 index 0000000..ee07027 --- /dev/null +++ b/src/JuicyGraphics/math/normalizeVectorException.cs @@ -0,0 +1,23 @@ +using System; +using System.Runtime.Serialization; + +namespace JuicyGraphics.Exceptions { + + [Serializable] + public class normalizeVectorException : Exception { + public normalizeVectorException() { + } + + public normalizeVectorException(string message) + : base(message) { + } + + public normalizeVectorException(string message, Exception innerException) + : base(message, innerException) { + } + + protected normalizeVectorException(SerializationInfo info, StreamingContext context) + : base(info, context) { + } + } +} diff --git a/src/JuicyGraphics/math/vec2.cs b/src/JuicyGraphics/math/vec2.cs new file mode 100644 index 0000000..741ac76 --- /dev/null +++ b/src/JuicyGraphics/math/vec2.cs @@ -0,0 +1,637 @@ +using System; +using System.ComponentModel; +using System.Xml.Serialization; + +namespace JuicyGraphics.Mathematics { + using Exceptions; + + [ImmutableObject(true), Serializable] + public struct vec2 + : IComparable, IComparable, IEquatable, IFormattable { + + private readonly double _x; + private readonly double _y; + + public vec2(double x, double y) { + this._x = x; + this._y = y; + } + + public vec2(double[] xy) { + if (xy.Length == 2) { + this._x = xy[0]; + this._y = xy[1]; + } + else { + throw new ArgumentException(TWO_COMPONENTS); + } + } + + public vec2(vec2 v1) { + this._x = v1.x; + this._y = v1.y; + } + + public double x { + get { + return _x; + } + } + + public double y { + get { + return _y; + } + } + + public vec2 xx { + get { + return new vec2(_x, _x); + } + } + + public vec2 xy { + get { + return this; + } + } + + public vec2 yx { + get { + return new vec2(_y, _x); + } + } + + public vec2 yy { + get { + return new vec2(_y, _y); + } + } + + public vec2 normal { + get { + return this.normalize(); + } + } + + public double magnitude { + get { + return Math.Sqrt(this.sumComponentSqrs()); + } + } + + [XmlIgnore] + public double[] array { + get { + return new[] { this.x, this.y }; + } + } + + public double this[int index] { + get { + switch (index) { + case 0: + return this._x; + case 1: + return this._y; + default: + throw new ArgumentException(TWO_COMPONENTS, "index"); + } + } + } + + public static vec2 operator +(vec2 v1, vec2 v2) { + return new vec2( + v1.x + v2.x, + v1.y + v2.y); + } + + public static vec2 operator -(vec2 v1, vec2 v2) { + return new vec2( + v1.x - v2.x, + v1.y - v2.y); + } + + public static vec2 operator *(vec2 v1, double s2) { + return + new vec2( + v1.x * s2, + v1.y * s2); + } + + public static vec2 operator *(double s1, vec2 v2) { + return v2 * s1; + } + + public static vec2 operator /(vec2 v1, double s2) { + return new vec2( + v1.x / s2, + v1.y / s2); + } + + public static vec2 operator -(vec2 v1) { + return new vec2( + -v1.x, + -v1.y); + } + + public static vec2 operator +(vec2 v1) { + return new vec2( + +v1.x, + +v1.y); + } + + public static bool operator <(vec2 v1, vec2 v2) { + return v1.sumComponentSqrs() < v2.sumComponentSqrs(); + } + + public static bool operator >(vec2 v1, vec2 v2) { + return v1.sumComponentSqrs() > v2.sumComponentSqrs(); + } + + public static bool operator <=(vec2 v1, vec2 v2) { + return v1.sumComponentSqrs() <= v2.sumComponentSqrs(); + } + + public static bool operator >=(vec2 v1, vec2 v2) { + return v1.sumComponentSqrs() >= v2.sumComponentSqrs(); + } + + public static bool operator ==(vec2 v1, vec2 v2) { + return + v1.x == v2.x && + v1.y == v2.y; + } + + public static bool operator !=(vec2 v1, vec2 v2) { + return !(v1 == v2); + } + + public static vec2 scale(vec2 vector, double magnitude) { + if (magnitude < 0) { + throw new ArgumentOutOfRangeException("magnitude", magnitude, NEGATIVE_magnitude); + } + + if (vector == new vec2(0, 0)) { + throw new ArgumentException(ORIGIN_VECTOR_magnitude, "vector"); + } + + return vector * (magnitude / vector.magnitude); + } + + public vec2 scale(double magnitude) { + return vec2.scale(this, magnitude); + } + + public static double dotProduct(vec2 v1, vec2 v2) { + return + v1.x * v2.x + + v1.y * v2.y; + } + + public double dotProduct(vec2 other) { + return dotProduct(this, other); + } + + public static vec2 normalize(vec2 v1) { + if (double.IsInfinity(v1.magnitude)) { + v1 = normalizeSpecialCasesOrOrigional(v1); + + if (v1.isNaN()) { + throw new normalizeVectorException(NORMALIZE_Inf); + } + } + + if (v1.magnitude == 0) { + throw new normalizeVectorException(NORMALIZE_0); + } + + if (v1.isNaN()) { + throw new normalizeVectorException(NORMALIZE_NaN); + } + + return normalizeOrNaN(v1); + } + + public static vec2 normalizeOrDefault(vec2 v1) { + v1 = normalizeSpecialCasesOrOrigional(v1); + + if (v1.magnitude == 0) { + return origin; + } + + if (v1.isNaN()) { + return NaN; + } + + return normalizeOrNaN(v1); + } + + public vec2 normalize() { + return normalize(this); + } + + public vec2 normalizeOrDefault() { + return normalizeOrDefault(this); + } + + private static vec2 normalizeOrNaN(vec2 v1) { + double inverse = 1 / v1.magnitude; + + return new vec2( + v1.x * inverse, + v1.y * inverse); + } + + private static vec2 normalizeSpecialCasesOrOrigional(vec2 v1) { + if (double.IsInfinity(v1.magnitude)) { + var x = v1.x == 0 ? 0 : v1.x == -0 ? -0 : double.IsPositiveInfinity(v1.x) ? 1 : double.IsNegativeInfinity(v1.x) ? -1 : double.NaN; + var y = v1.y == 0 ? 0 : v1.y == -0 ? -0 : double.IsPositiveInfinity(v1.y) ? 1 : double.IsNegativeInfinity(v1.y) ? -1 : double.NaN; + + return new vec2(x, y); + } + + return v1; + } + + public static vec2 interpolate(vec2 v1, vec2 v2, double control, bool allowExtrapolation) { + if (!allowExtrapolation && (control > 1 || control < 0)) { + throw new ArgumentOutOfRangeException( + "control", + control, + INTERPOLATION_RANGE + "\n" + ARGUMENT_VALUE + control); + } + + return new vec2( + v1.x * (1 - control) + v2.x * control, + v1.y * (1 - control) + v2.y * control); + } + + public static vec2 interpolate(vec2 v1, vec2 v2, double control) { + return interpolate(v1, v2, control, false); + } + + public vec2 interpolate(vec2 other, double control) { + return interpolate(this, other, control); + } + + public vec2 interpolate(vec2 other, double control, bool allowExtrapolation) { + return interpolate(this, other, control); + } + + public static double distance(vec2 v1, vec2 v2) { + return Math.Sqrt( + (v1.x - v2.x) * (v1.x - v2.x) + + (v1.y - v2.y) * (v1.y - v2.y)); + } + + public double distance(vec2 other) { + return distance(this, other); + } + + public static double angle(vec2 v1, vec2 v2) { + if (v1 == v2) { + return 0; + } + + return + Math.Acos( + Math.Min(1.0f, normalizeOrDefault(v1).dotProduct(normalizeOrDefault(v2)))); + } + + public double angle(vec2 other) { + return angle(this, other); + } + + public static vec2 max(vec2 v1, vec2 v2) { + return v1 >= v2 ? v1 : v2; + } + + public vec2 max(vec2 other) { + return max(this, other); + } + + public static vec2 min(vec2 v1, vec2 v2) { + return v1 <= v2 ? v1 : v2; + } + + public vec2 min(vec2 other) { + return min(this, other); + } + + public static vec2 rotate(vec2 v1, double rad) { + double x = (v1.x * Math.Cos(rad)) - (v1.y * Math.Sin(rad)); + double y = (v1.x * Math.Sin(rad)) + (v1.y * Math.Cos(rad)); + return new vec2(x, y); + } + + public vec2 rotate(double rad) { + return rotate(this, rad); + } + + public static vec2 rotate(vec2 v1, double xOff, double yOff, double rad) { + double x = (v1.x * Math.Cos(rad)) - (v1.y * Math.Sin(rad)) + (xOff * (1 - Math.Cos(rad)) + yOff * Math.Sin(rad)); + double y = (v1.x * Math.Sin(rad)) + (v1.y * Math.Cos(rad)) + (yOff * (1 - Math.Cos(rad)) - xOff * Math.Sin(rad)); + return new vec2(x, y); + } + + public vec2 rotate(double xOff, double yOff, double rad) { + return rotate(this, xOff, yOff, rad); + } + + public static vec2 projection(vec2 v1, vec2 v2) { + return new vec2(v2 * (v1.dotProduct(v2) / Math.Pow(v2.magnitude, 2))); + } + + public vec2 projection(vec2 direction) { + return projection(this, direction); + } + + public static vec2 rejection(vec2 v1, vec2 v2) { + return v1 - v1.projection(v2); + } + + public vec2 rejection(vec2 direction) { + return rejection(this, direction); + } + + public vec2 reflection(vec2 reflector) { + this = vec2.reflection(this, reflector); + return this; + } + + public static vec2 reflection(vec2 v1, vec2 v2) { + if (Math.Abs(Math.Abs(v1.angle(v2)) - Math.PI / 2) < Double.Epsilon) { + return -v1; + } + + vec2 retval = new vec2(2 * v1.projection(v2) - v1); + return retval.scale(v1.magnitude); + } + + public static Double abs(vec2 v1) { + return v1.magnitude; + } + + public double abs() { + return this.magnitude; + } + + public static double sumComponents(vec2 v1) { + return v1.x + v1.y; + } + + public double sumComponents() { + return sumComponents(this); + } + + public static double sumComponentSqrs(vec2 v1) { + vec2 v2 = sqrComponents(v1); + return v2.sumComponents(); + } + + public double sumComponentSqrs() { + return sumComponentSqrs(this); + } + + public static vec2 powComponents(vec2 v1, double power) { + return new vec2( + Math.Pow(v1.x, power), + Math.Pow(v1.y, power)); + } + + public vec2 powComponents(double power) { + return powComponents(this, power); + } + + public static vec2 sqrtComponents(vec2 v1) { + return new vec2( + Math.Sqrt(v1.x), + Math.Sqrt(v1.y)); + } + + public vec2 sqrtComponents() { + return sqrtComponents(this); + } + + public static vec2 sqrComponents(vec2 v1) { + return new vec2( + v1.x * v1.x, + v1.y * v1.y); + } + + public vec2 sqrComponents() { + return sqrComponents(this); + } + + public static vec2 round(vec2 v1) { + return new vec2(Math.Round(v1.x), Math.Round(v1.y)); + } + + public static vec2 round(vec2 v1, int digits) { + return new vec2(Math.Round(v1.x, digits), Math.Round(v1.y, digits)); + } + + public static vec2 round(vec2 v1, MidpointRounding mode) { + return new vec2(Math.Round(v1.x, mode), Math.Round(v1.y, mode)); + } + + public static vec2 round(vec2 v1, int digits, MidpointRounding mode) { + return new vec2(Math.Round(v1.x, digits, mode), Math.Round(v1.y, digits, mode)); + } + + public vec2 round() { + return new vec2(Math.Round(this.x), Math.Round(this.y)); + } + + public vec2 round(int digits) { + return new vec2(Math.Round(this.x, digits), Math.Round(this.y, digits)); + } + + public vec2 round(MidpointRounding mode) { + return new vec2(Math.Round(this.x, mode), Math.Round(this.y, mode)); + } + + public vec2 round(int digits, MidpointRounding mode) { + return new vec2(Math.Round(this.x, digits, mode), Math.Round(this.y, digits, mode)); + } + + public override string ToString() { + return this.ToString(null, null); + } + + public string ToVerbString() { + string output = null; + + if (this.isUnitVector()) { + output += UNIT_VECTOR; + } + else { + output += POSITIONAL_VECTOR; + } + + output += string.Format("( x={0}, y={1} )", this.x, this.y); + output += magnitude + this.magnitude; + + return output; + } + + public string ToString(string format, IFormatProvider formatProvider) { + if (format == null || format == "") { + return string.Format("({0}, {1})", this.x, this.y); + } + + char firstChar = format[0]; + string remainder = null; + + if (format.Length > 1) { + remainder = format.Substring(1); + } + + switch (firstChar) { + case 'x': return this.x.ToString(remainder, formatProvider); + case 'y': return this.y.ToString(remainder, formatProvider); + default: + return String.Format( + "({0}, {1})", + this.x.ToString(format, formatProvider), + this.y.ToString(format, formatProvider)); + } + } + + public override int GetHashCode() { + unchecked { + var hashCode = this.x.GetHashCode(); + hashCode = (hashCode * 397) ^ this.y.GetHashCode(); + return hashCode; + } + } + + public override bool Equals(object other) { + if (other is vec2) { + return other.Equals(this); + } + else { + return false; + } + } + + public bool Equals(object other, double tolerance) { + if (other is vec2) { + return this.Equals((vec2)other, tolerance); + } + return false; + } + + public bool Equals(vec2 other) { + return + this.x.Equals(other.x) && + this.y.Equals(other.y); + } + + public bool Equals(vec2 other, double tolerance) { + return + this.x.almostEqualsWithAbsTolerance(other.x, tolerance) && + this.y.almostEqualsWithAbsTolerance(other.y, tolerance); + } + + public int CompareTo(vec2 other) { + if (this < other) { + return -1; + } + + if (this > other) { + return 1; + } + + return 0; + } + + public int CompareTo(object other) { + if (other is vec2) { + return this.CompareTo((vec2)other); + } + + throw new ArgumentException( + NON_VECTOR_COMPARISON + "\n" + ARGUMENT_TYPE + other.GetType().ToString(), + "other"); + } + + public int CompareTo(vec2 other, double tolerance) { + var bothInfinite = double.IsInfinity(this.sumComponentSqrs()) && double.IsInfinity(other.sumComponentSqrs()); + + if (this.Equals(other, tolerance) || bothInfinite) { + return 0; + } + + if (this < other) { + return -1; + } + + return 1; + } + + public int CompareTo(object other, double tolerance) { + if (other is vec2) { + return this.CompareTo((vec2)other, tolerance); + } + + throw new ArgumentException( + NON_VECTOR_COMPARISON + "\n" + ARGUMENT_TYPE + other.GetType().ToString(), + "other"); + } + + public static bool isUnitVector(vec2 v1, double tolerance) { + return v1.magnitude.almostEqualsWithAbsTolerance(1, tolerance); + } + + public static bool isUnitVector(vec2 v1) { + return v1.magnitude == 1; + } + + public bool isUnitVector() { + return isUnitVector(this); + } + + public bool isUnitVector(double tolerance) { + return isUnitVector(this, tolerance); + } + + public static bool isNaN(vec2 v1) { + return double.IsNaN(v1.x) || double.IsNaN(v1.y); + } + + public bool isNaN() { + return isNaN(this); + } + + public static readonly vec2 origin = new vec2(0, 0); + public static readonly vec2 right = new vec2(1, 0); + public static readonly vec2 left = new vec2(-1, 0); + public static readonly vec2 down = new vec2(0, 1); + public static readonly vec2 up = new vec2(0, -1); + + + private const string NORMALIZE_NaN = "Cannot normalize a vector when it's magnitude is NaN"; + private const string NORMALIZE_0 = "Cannot normalize a vector when it's magnitude is zero"; + private const string NORMALIZE_Inf = "Cannot normalize a vector when it's magnitude is infinite except under special conditions"; + private const string TWO_COMPONENTS = "Array must contain exactly two components (x, y)"; + private const string INTERPOLATION_RANGE = "Control parameter must be a value between 0 & 1"; + private const string NON_VECTOR_COMPARISON = "Cannot compare a vec2 to a non-vec2"; + private const string ARGUMENT_TYPE = "The argument provided is a type of "; + private const string ARGUMENT_VALUE = "The argument provided has a value of "; + private const string ARGUMENT_LENGTH = "The argument provided has a length of "; + private const string NEGATIVE_magnitude = "The magnitude of a vec2 must be a positive value, (i.e. greater than 0)"; + private const string ORIGIN_VECTOR_magnitude = "Cannot change the magnitude of vec2(0, 0)"; + + private const string UNIT_VECTOR = "Unit vector composing of "; + private const string POSITIONAL_VECTOR = "Positional vector composing of "; + private const string MAGNITUDE = " of magnitude "; + + public static readonly vec2 minValue = new vec2(Double.MinValue, Double.MinValue); + public static readonly vec2 maxValue = new vec2(Double.MaxValue, Double.MaxValue); + public static readonly vec2 epsilon = new vec2(Double.Epsilon, Double.Epsilon); + public static readonly vec2 zero = origin; + public static readonly vec2 NaN = new vec2(double.NaN, double.NaN); + } +} \ No newline at end of file diff --git a/src/JuicyGraphics/math/vec3.cs b/src/JuicyGraphics/math/vec3.cs new file mode 100644 index 0000000..96b56c6 --- /dev/null +++ b/src/JuicyGraphics/math/vec3.cs @@ -0,0 +1,956 @@ +using System; +using System.ComponentModel; +using System.Xml.Serialization; + +namespace JuicyGraphics.Mathematics { + using Exceptions; + + [ImmutableObject(true), Serializable] + public struct vec3 + : IComparable, IComparable, IEquatable, IFormattable { + + private readonly double _x; + private readonly double _y; + private readonly double _z; + + public vec3(double x, double y, double z) { + _x = x; + _y = y; + _z = z; + } + + public vec3(double[] xyz) { + if (xyz.Length == 3) { + _x = xyz[0]; + _y = xyz[1]; + _z = xyz[2]; + } + else { + throw new ArgumentException(THREE_COMPONENTS); + } + } + + public vec3(vec3 v1) { + _x = v1.x; + _y = v1.y; + _z = v1.z; + } + + public double x { + get { + return _x; + } + } + + public double y { + get { + return _y; + } + } + + public double z { + get { + return _z; + } + } + + public vec2 xx { + get { + return new vec2(_x, _x); + } + } + + public vec2 xy { + get { + return new vec2(_x, _y); + } + } + + public vec2 yx { + get { + return new vec2(_y, _x); + } + } + + public vec2 yy { + get { + return new vec2(_y, _y); + } + } + + public vec3 xxx { + get { + return new vec3(_x, _x, _x); + } + } + + public vec3 xxy { + get { + return new vec3(_x, _x, _y); + } + } + + public vec3 xxz { + get { + return new vec3(_x, _x, _z); + } + } + + public vec3 xyx { + get { + return new vec3(_x, _y, _x); + } + } + + public vec3 xyy { + get { + return new vec3(_x, _y, _y); + } + } + + public vec3 xyz { + get { + return new vec3(_x, _y, _z); + } + } + + public vec3 xzx { + get { + return new vec3(_x, _z, _x); + } + } + + public vec3 xzy { + get { + return new vec3(_x, _z, _y); + } + } + + public vec3 xzz { + get { + return new vec3(_x, _z, _z); + } + } + + public vec3 yxx { + get { + return new vec3(_y, _x, _x); + } + } + + public vec3 yxy { + get { + return new vec3(_y, _x, _y); + } + } + + public vec3 yxz { + get { + return new vec3(_y, _x, _z); + } + } + + public vec3 yyx { + get { + return new vec3(_y, _y, _x); + } + } + + public vec3 yyy { + get { + return new vec3(_y, _y, _y); + } + } + + public vec3 yyz { + get { + return new vec3(_y, _y, _z); + } + } + + public vec3 yzx { + get { + return new vec3(_y, _z, _x); + } + } + + public vec3 yzy { + get { + return new vec3(_y, _z, _y); + } + } + + public vec3 yzz { + get { + return new vec3(_y, _z, _z); + } + } + + public vec3 zxx { + get { + return new vec3(_z, _x, _x); + } + } + + public vec3 zxy { + get { + return new vec3(_z, _x, _y); + } + } + + public vec3 zxz { + get { + return new vec3(_z, _x, _z); + } + } + + public vec3 zyx { + get { + return new vec3(_z, _y, _x); + } + } + + public vec3 zyy { + get { + return new vec3(_z, _y, _y); + } + } + + public vec3 zyz { + get { + return new vec3(_z, _y, _z); + } + } + + public vec3 zzx { + get { + return new vec3(_z, _z, _x); + } + } + + public vec3 zzy { + get { + return new vec3(_z, _z, _y); + } + } + + public vec3 zzz { + get { + return new vec3(_z, _z, _z); + } + } + + public vec3 normal { + get { + return normalize(); + } + } + + public double magnitude { + get { + return Math.Sqrt(sumComponentSqrs()); + } + } + + [XmlIgnore] + public double[] array { + get { + return new[] { _x, _y, _z }; + } + } + + public double this[int index] { + get { + switch (index) { + case 0: + return x; + case 1: + return y; + case 2: + return z; + default: + throw new ArgumentException(THREE_COMPONENTS, "index"); + } + } + } + + public static vec3 operator +(vec3 v1, vec3 v2) { + return new vec3( + v1.x + v2.x, + v1.y + v2.y, + v1.z + v2.z); + } + + public static vec3 operator -(vec3 v1, vec3 v2) { + return new vec3( + v1.x - v2.x, + v1.y - v2.y, + v1.z - v2.z); + } + + public static vec3 operator *(vec3 v1, double s2) { + return + new vec3( + v1.x * s2, + v1.y * s2, + v1.z * s2); + } + + public static vec3 operator *(double s1, vec3 v2) { + return v2 * s1; + } + + public static vec3 operator /(vec3 v1, double s2) { + return new vec3( + v1.x / s2, + v1.y / s2, + v1.z / s2); + } + + public static vec3 operator -(vec3 v1) { + return new vec3( + -v1.x, + -v1.y, + -v1.z); + } + + public static vec3 operator +(vec3 v1) { + return new vec3( + +v1.x, + +v1.y, + +v1.z); + } + + public static bool operator <(vec3 v1, vec3 v2) { + return v1.sumComponentSqrs() < v2.sumComponentSqrs(); + } + + public static bool operator >(vec3 v1, vec3 v2) { + return v1.sumComponentSqrs() > v2.sumComponentSqrs(); + } + + public static bool operator <=(vec3 v1, vec3 v2) { + return v1.sumComponentSqrs() <= v2.sumComponentSqrs(); + } + + public static bool operator >=(vec3 v1, vec3 v2) { + return v1.sumComponentSqrs() >= v2.sumComponentSqrs(); + } + + public static bool operator ==(vec3 v1, vec3 v2) { + return + v1.x == v2.x && + v1.y == v2.y && + v1.z == v2.z; + } + + public static bool operator !=(vec3 v1, vec3 v2) { + return !(v1 == v2); + } + + public static vec3 scale(vec3 vector, double magnitude) { + if (magnitude < 0) { + throw new ArgumentOutOfRangeException("magnitude", magnitude, NEGATIVE_magnitude); + } + + if (vector == new vec3(0, 0, 0)) { + throw new ArgumentException(ORIGIN_VECTOR_magnitude, "vector"); + } + + return vector * (magnitude / vector.magnitude); + } + + public vec3 scale(double magnitude) { + return vec3.scale(this, magnitude); + } + + public static vec3 crossProduct(vec3 v1, vec3 v2) { + return + new vec3( + v1.y * v2.z - v1.z * v2.y, + v1.z * v2.x - v1.x * v2.z, + v1.x * v2.y - v1.y * v2.x); + } + + public vec3 crossProduct(vec3 other) { + return crossProduct(this, other); + } + + public static double dotProduct(vec3 v1, vec3 v2) { + return + v1.x * v2.x + + v1.y * v2.y + + v1.z * v2.z; + } + + public double dotProduct(vec3 other) { + return dotProduct(this, other); + } + + public static double mixedProduct(vec3 v1, vec3 v2, vec3 v3) { + return dotProduct(crossProduct(v1, v2), v3); + } + + public double mixedProduct(vec3 other_v1, vec3 other_v2) { + return dotProduct(crossProduct(this, other_v1), other_v2); + } + + public static vec3 normalize(vec3 v1) { + if (double.IsInfinity(v1.magnitude)) { + v1 = normalizeSpecialCasesOrOrigional(v1); + + if (v1.isNaN()) { + throw new normalizeVectorException(NORMALIZE_Inf); + } + } + + if (v1.magnitude == 0) { + throw new normalizeVectorException(NORMALIZE_0); + } + + if (v1.isNaN()) { + throw new normalizeVectorException(NORMALIZE_NaN); + } + + return normalizeOrNaN(v1); + } + + public static vec3 normalizeOrDefault(vec3 v1) { + v1 = normalizeSpecialCasesOrOrigional(v1); + + if (v1.magnitude == 0) { + return origin; + } + + if (v1.isNaN()) { + return NaN; + } + + return normalizeOrNaN(v1); + } + + public vec3 normalize() { + return normalize(this); + } + + public vec3 normalizeOrDefault() { + return normalizeOrDefault(this); + } + + private static vec3 normalizeOrNaN(vec3 v1) { + double inverse = 1 / v1.magnitude; + + return new vec3( + v1.x * inverse, + v1.y * inverse, + v1.z * inverse); + } + + private static vec3 normalizeSpecialCasesOrOrigional(vec3 v1) { + if (double.IsInfinity(v1.magnitude)) { + var x = v1.x == 0 ? 0 : v1.x == -0 ? -0 : double.IsPositiveInfinity(v1.x) ? 1 : double.IsNegativeInfinity(v1.x) ? -1 : double.NaN; + var y = v1.y == 0 ? 0 : v1.y == -0 ? -0 : double.IsPositiveInfinity(v1.y) ? 1 : double.IsNegativeInfinity(v1.y) ? -1 : double.NaN; + var z = v1.z == 0 ? 0 : v1.z == -0 ? -0 : double.IsPositiveInfinity(v1.z) ? 1 : double.IsNegativeInfinity(v1.z) ? -1 : double.NaN; + + return new vec3(x, y, z); + } + + return v1; + } + + public static vec3 interpolate(vec3 v1, vec3 v2, double control, bool allowExtrapolation) { + if (!allowExtrapolation && (control > 1 || control < 0)) { + throw new ArgumentOutOfRangeException( + "control", + control, + INTERPOLATION_RANGE + "\n" + ARGUMENT_VALUE + control); + } + + return new vec3( + v1.x * (1 - control) + v2.x * control, + v1.y * (1 - control) + v2.y * control, + v1.z * (1 - control) + v2.z * control); + } + + public static vec3 interpolate(vec3 v1, vec3 v2, double control) { + return interpolate(v1, v2, control, false); + } + + public vec3 interpolate(vec3 other, double control) { + return interpolate(this, other, control); + } + + public vec3 interpolate(vec3 other, double control, bool allowExtrapolation) { + return interpolate(this, other, control); + } + + public static double distance(vec3 v1, vec3 v2) { + return Math.Sqrt( + (v1.x - v2.x) * (v1.x - v2.x) + + (v1.y - v2.y) * (v1.y - v2.y) + + (v1.z - v2.z) * (v1.z - v2.z)); + } + + public double distance(vec3 other) { + return distance(this, other); + } + + public static double angle(vec3 v1, vec3 v2) { + if (v1 == v2) { + return 0; + } + + return + Math.Acos( + Math.Min(1.0f, normalizeOrDefault(v1).dotProduct(normalizeOrDefault(v2)))); + } + + public double angle(vec3 other) { + return angle(this, other); + } + + public static vec3 max(vec3 v1, vec3 v2) { + return v1 >= v2 ? v1 : v2; + } + + public vec3 max(vec3 other) { + return max(this, other); + } + + public static vec3 min(vec3 v1, vec3 v2) { + return v1 <= v2 ? v1 : v2; + } + + public vec3 min(vec3 other) { + return min(this, other); + } + + public static vec3 yaw(vec3 v1, double rad) { + return rotateY(v1, rad); + } + + public vec3 yaw(double rad) { + return yaw(this, rad); + } + + public static vec3 pitch(vec3 v1, double rad) { + return rotateX(v1, rad); + } + + public vec3 pitch(double rad) { + return pitch(this, rad); + } + + public static vec3 roll(vec3 v1, double rad) { + return rotateZ(v1, rad); + } + + public vec3 roll(double rad) { + return roll(this, rad); + } + + public static vec3 rotateX(vec3 v1, double rad) { + double x = v1.x; + double y = (v1.y * Math.Cos(rad)) - (v1.z * Math.Sin(rad)); + double z = (v1.y * Math.Sin(rad)) + (v1.z * Math.Cos(rad)); + return new vec3(x, y, z); + } + + public vec3 rotateX(double rad) { + return rotateX(this, rad); + } + + public static vec3 rotateY(vec3 v1, double rad) { + double x = (v1.z * Math.Sin(rad)) + (v1.x * Math.Cos(rad)); + double y = v1.y; + double z = (v1.z * Math.Cos(rad)) - (v1.x * Math.Sin(rad)); + return new vec3(x, y, z); + } + + public vec3 rotateY(double rad) { + return rotateY(this, rad); + } + + public static vec3 rotateZ(vec3 v1, double rad) { + double x = (v1.x * Math.Cos(rad)) - (v1.y * Math.Sin(rad)); + double y = (v1.x * Math.Sin(rad)) + (v1.y * Math.Cos(rad)); + double z = v1.z; + return new vec3(x, y, z); + } + + public vec3 rotateZ(double rad) { + return rotateZ(this, rad); + } + + public static vec3 rotateX(vec3 v1, double yOff, double zOff, double rad) { + double x = v1.x; + double y = (v1.y * Math.Cos(rad)) - (v1.z * Math.Sin(rad)) + (yOff * (1 - Math.Cos(rad)) + zOff * Math.Sin(rad)); + double z = (v1.y * Math.Sin(rad)) + (v1.z * Math.Cos(rad)) + (zOff * (1 - Math.Cos(rad)) - yOff * Math.Sin(rad)); + return new vec3(x, y, z); + } + + public vec3 rotateX(double yOff, double zOff, double rad) { + return rotateX(this, yOff, zOff, rad); + } + + public static vec3 rotateY(vec3 v1, double xOff, double zOff, double rad) { + double x = (v1.z * Math.Sin(rad)) + (v1.x * Math.Cos(rad)) + (xOff * (1 - Math.Cos(rad)) - zOff * Math.Sin(rad)); + double y = v1.y; + double z = (v1.z * Math.Cos(rad)) - (v1.x * Math.Sin(rad)) + (zOff * (1 - Math.Cos(rad)) + xOff * Math.Sin(rad)); + return new vec3(x, y, z); + } + + public vec3 rotateY(double xOff, double zOff, double rad) { + return rotateY(this, xOff, zOff, rad); + } + + public static vec3 rotateZ(vec3 v1, double xOff, double yOff, double rad) { + double x = (v1.x * Math.Cos(rad)) - (v1.y * Math.Sin(rad)) + (xOff * (1 - Math.Cos(rad)) + yOff * Math.Sin(rad)); + double y = (v1.x * Math.Sin(rad)) + (v1.y * Math.Cos(rad)) + (yOff * (1 - Math.Cos(rad)) - xOff * Math.Sin(rad)); + double z = v1.z; + return new vec3(x, y, z); + } + + public vec3 rotateZ(double xOff, double yOff, double rad) { + return rotateZ(this, xOff, yOff, rad); + } + + public static vec3 projection(vec3 v1, vec3 v2) { + return new vec3(v2 * (v1.dotProduct(v2) / Math.Pow(v2.magnitude, 2))); + } + + public vec3 projection(vec3 direction) { + return projection(this, direction); + } + + public static vec3 rejection(vec3 v1, vec3 v2) { + return v1 - v1.projection(v2); + } + + public vec3 rejection(vec3 direction) { + return rejection(this, direction); + } + + public vec3 reflection(vec3 reflector) { + this = vec3.reflection(this, reflector); + return this; + } + + public static vec3 reflection(vec3 v1, vec3 v2) { + if (Math.Abs(Math.Abs(v1.angle(v2)) - Math.PI / 2) < Double.Epsilon) { + return -v1; + } + + vec3 retval = new vec3(2 * v1.projection(v2) - v1); + return retval.scale(v1.magnitude); + } + + public static Double abs(vec3 v1) { + return v1.magnitude; + } + + public double abs() { + return magnitude; + } + + public static double sumComponents(vec3 v1) { + return v1.x + v1.y + v1.z; + } + + public double sumComponents() { + return sumComponents(this); + } + + public static double sumComponentSqrs(vec3 v1) { + vec3 v2 = sqrComponents(v1); + return v2.sumComponents(); + } + + public double sumComponentSqrs() { + return sumComponentSqrs(this); + } + + public static vec3 powComponents(vec3 v1, double power) { + return new vec3( + Math.Pow(v1.x, power), + Math.Pow(v1.y, power), + Math.Pow(v1.z, power)); + } + + public vec3 powComponents(double power) { + return powComponents(this, power); + } + + public static vec3 sqrtComponents(vec3 v1) { + return new vec3( + Math.Sqrt(v1.x), + Math.Sqrt(v1.y), + Math.Sqrt(v1.z)); + } + + public vec3 sqrtComponents() { + return sqrtComponents(this); + } + + public static vec3 sqrComponents(vec3 v1) { + return new vec3( + v1.x * v1.x, + v1.y * v1.y, + v1.z * v1.z); + } + + public vec3 sqrComponents() { + return sqrComponents(this); + } + + public static vec3 round(vec3 v1) { + return new vec3(Math.Round(v1.x), Math.Round(v1.y), Math.Round(v1.z)); + } + + public static vec3 round(vec3 v1, int digits) { + return new vec3(Math.Round(v1.x, digits), Math.Round(v1.y, digits), Math.Round(v1.z, digits)); + } + + public static vec3 round(vec3 v1, MidpointRounding mode) { + return new vec3(Math.Round(v1.x, mode), Math.Round(v1.y, mode), Math.Round(v1.z, mode)); + } + + public static vec3 round(vec3 v1, int digits, MidpointRounding mode) { + return new vec3(Math.Round(v1.x, digits, mode), Math.Round(v1.y, digits, mode), Math.Round(v1.z, digits, mode)); + } + + public vec3 round() { + return new vec3(Math.Round(x), Math.Round(y), Math.Round(z)); + } + + public vec3 round(int digits) { + return new vec3(Math.Round(x, digits), Math.Round(y, digits), Math.Round(z, digits)); + } + + public vec3 round(MidpointRounding mode) { + return new vec3(Math.Round(x, mode), Math.Round(y, mode), Math.Round(z, mode)); + } + + public vec3 round(int digits, MidpointRounding mode) { + return new vec3(Math.Round(x, digits, mode), Math.Round(y, digits, mode), Math.Round(z, digits, mode)); + } + + public override string ToString() { + return ToString(null, null); + } + + public string ToVerbString() { + string output = null; + + if (isUnitVector()) { + output += UNIT_VECTOR; + } + else { + output += POSITIONAL_VECTOR; + } + + output += string.Format("( x={0}, y={1}, z={2} )", x, y, z); + output += magnitude + magnitude; + + return output; + } + + public string ToString(string format, IFormatProvider formatProvider) { + if (format == null || format == "") { + return string.Format("({0}, {1}, {2})", x, y, z); + } + + char firstChar = format[0]; + string remainder = null; + + if (format.Length > 1) { + remainder = format.Substring(1); + } + + switch (firstChar) { + case 'x': return x.ToString(remainder, formatProvider); + case 'y': return y.ToString(remainder, formatProvider); + case 'z': return z.ToString(remainder, formatProvider); + default: + return String.Format( + "({0}, {1}, {2})", + x.ToString(format, formatProvider), + y.ToString(format, formatProvider), + z.ToString(format, formatProvider)); + } + } + + public override int GetHashCode() { + unchecked { + var hashCode = _x.GetHashCode(); + hashCode = (hashCode * 397) ^ _y.GetHashCode(); + hashCode = (hashCode * 397) ^ _z.GetHashCode(); + return hashCode; + } + } + + public override bool Equals(object other) { + if (other is vec3) { + return other.Equals(this); + } + else { + return false; + } + } + + public bool Equals(object other, double tolerance) { + if (other is vec3) { + return Equals((vec3)other, tolerance); + } + return false; + } + + public bool Equals(vec3 other) { + return + x.Equals(other.x) && + y.Equals(other.y) && + z.Equals(other.z); + } + + public bool Equals(vec3 other, double tolerance) { + return + x.almostEqualsWithAbsTolerance(other.x, tolerance) && + y.almostEqualsWithAbsTolerance(other.y, tolerance) && + z.almostEqualsWithAbsTolerance(other.z, tolerance); + } + + public int CompareTo(vec3 other) { + if (this < other) { + return -1; + } + + if (this > other) { + return 1; + } + + return 0; + } + + public int CompareTo(object other) { + if (other is vec3) { + return CompareTo((vec3)other); + } + + throw new ArgumentException( + NON_VECTOR_COMPARISON + "\n" + ARGUMENT_TYPE + other.GetType().ToString(), + "other"); + } + + public int CompareTo(vec3 other, double tolerance) { + var bothInfinite = double.IsInfinity(sumComponentSqrs()) && double.IsInfinity(other.sumComponentSqrs()); + + if (Equals(other, tolerance) || bothInfinite) { + return 0; + } + + if (this < other) { + return -1; + } + + return 1; + } + + public int CompareTo(object other, double tolerance) { + if (other is vec3) { + return CompareTo((vec3)other, tolerance); + } + + throw new ArgumentException( + NON_VECTOR_COMPARISON + "\n" + ARGUMENT_TYPE + other.GetType().ToString(), + "other"); + } + public static bool isUnitVector(vec3 v1, double tolerance) { + return v1.magnitude.almostEqualsWithAbsTolerance(1, tolerance); + } + + public static bool isUnitVector(vec3 v1) { + return v1.magnitude == 1; + } + + public bool isUnitVector() { + return isUnitVector(this); + } + + public bool isUnitVector(double tolerance) { + return isUnitVector(this, tolerance); + } + + public static bool isBackFace(vec3 normal, vec3 lineOfSight) { + return normal.dotProduct(lineOfSight) < 0; + } + + public bool isBackFace(vec3 lineOfSight) { + return isBackFace(this, lineOfSight); + } + + public static bool isPerpendicular(vec3 v1, vec3 v2, double tolerance) { + v1 = normalizeSpecialCasesOrOrigional(v1); + v2 = normalizeSpecialCasesOrOrigional(v2); + + if (v1 == zero || v2 == zero) { + return false; + } + + return v1.dotProduct(v2).almostEqualsWithAbsTolerance(0, tolerance); + } + + public static bool isPerpendicular(vec3 v1, vec3 v2) { + v1 = normalizeSpecialCasesOrOrigional(v1); + v2 = normalizeSpecialCasesOrOrigional(v2); + + if (v1 == zero || v2 == zero) { + return false; + } + + return v1.dotProduct(v2).Equals(0); + } + + public bool isPerpendicular(vec3 other) { + return isPerpendicular(this, other); + } + + public bool isPerpendicular(vec3 other, double tolerance) { + return isPerpendicular(this, other, tolerance); + } + + public static bool isNaN(vec3 v1) { + return double.IsNaN(v1.x) || double.IsNaN(v1.y) || double.IsNaN(v1.z); + } + + public bool isNaN() { + return isNaN(this); + } + + public static readonly vec3 origin = new vec3(0, 0, 0); + public static readonly vec3 xAxis = new vec3(1, 0, 0); + public static readonly vec3 yAxis = new vec3(0, 1, 0); + public static readonly vec3 zAxis = new vec3(0, 0, 1); + + private const string NORMALIZE_NaN = "Cannot normalize a vector when it's magnitude is NaN"; + private const string NORMALIZE_0 = "Cannot normalize a vector when it's magnitude is zero"; + private const string NORMALIZE_Inf = "Cannot normalize a vector when it's magnitude is infinite except under special conditions"; + private const string THREE_COMPONENTS = "Array must contain exactly three components , (x,y,z)"; + private const string INTERPOLATION_RANGE = "Control parameter must be a value between 0 & 1"; + private const string NON_VECTOR_COMPARISON = "Cannot compare a vec3 to a non-vec3"; + private const string ARGUMENT_TYPE = "The argument provided is a type of "; + private const string ARGUMENT_VALUE = "The argument provided has a value of "; + private const string ARGUMENT_LENGTH = "The argument provided has a length of "; + private const string NEGATIVE_magnitude = "The magnitude of a vec3 must be a positive value, (i.e. greater than 0)"; + private const string ORIGIN_VECTOR_magnitude = "Cannot change the magnitude of vec3(0,0,0)"; + + private const string UNIT_VECTOR = "Unit vector composing of "; + private const string POSITIONAL_VECTOR = "Positional vector composing of "; + private const string MAGNITUDE = " of magnitude "; + + public static readonly vec3 minValue = new vec3(Double.MinValue, Double.MinValue, Double.MinValue); + public static readonly vec3 maxValue = new vec3(Double.MaxValue, Double.MaxValue, Double.MaxValue); + public static readonly vec3 epsilon = new vec3(Double.Epsilon, Double.Epsilon, Double.Epsilon); + public static readonly vec3 zero = origin; + public static readonly vec3 NaN = new vec3(double.NaN, double.NaN, double.NaN); + } +} \ No newline at end of file diff --git a/src/JuicyGraphics/renderer/graphicalObjects/gridBackground.cs b/src/JuicyGraphics/renderer/graphicalObjects/gridBackground.cs index c4237e4..a7c7501 100644 --- a/src/JuicyGraphics/renderer/graphicalObjects/gridBackground.cs +++ b/src/JuicyGraphics/renderer/graphicalObjects/gridBackground.cs @@ -1,17 +1,11 @@ -using System.Numerics; -using System.Windows.Forms; -using SharpGL.Shaders; +using SharpGL.Shaders; using SharpGL; -using SharpGL.Enumerations; -using System.Reflection; -using System.IO; using System.Collections.Generic; -using System; using SharpGL.VertexBuffers; namespace Graphics.Objects { class gridBackground : iGraphicalObject { - + VertexBuffer vbo = new VertexBuffer(); VertexBufferArray vao = new VertexBufferArray(); ShaderProgram gridRender = new ShaderProgram(); diff --git a/src/JuicyGraphics/renderer/stain.cs b/src/JuicyGraphics/renderer/stain.cs new file mode 100644 index 0000000..d7e7e36 --- /dev/null +++ b/src/JuicyGraphics/renderer/stain.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using JuicyGraphics.mathematics; + +namespace Graphics { + class stain { + class edgeElement { + public edgeElement() { + + } + } + } +} diff --git a/src/JuicyGraphics/renderer/stainGraphicTexture.cs b/src/JuicyGraphics/renderer/stainGraphicTexture.cs new file mode 100644 index 0000000..2dd2c47 --- /dev/null +++ b/src/JuicyGraphics/renderer/stainGraphicTexture.cs @@ -0,0 +1,10 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace JuicyGraphics.JuicyGraphics.renderer { + class stainGraphicTexture { + } +} diff --git a/src/SharpGL/OpenGL.cs b/src/SharpGL/OpenGL.cs index 53503f4..d255245 100644 --- a/src/SharpGL/OpenGL.cs +++ b/src/SharpGL/OpenGL.cs @@ -1,6 +1,5 @@ using System; using System.Diagnostics; -using System.ComponentModel; using System.Runtime.InteropServices; using SharpGL.RenderContextProviders; using SharpGL.Version;