/// <summary> /// Returns the angle to another vector. /// </summary> /// <remarks> /// The order of the directions plays a role. /// </remarks> /// <returns>Value between -PI and + PI.</returns> public double getAngle(Vertex dir, Vertex viewDir) { Vertex thisNomalized = new Vertex(this); thisNomalized.Normalize(); Vertex viewDirNormalized = new Vertex(viewDir); viewDirNormalized.Normalize(); double dotProduct = thisNomalized.ScalarProduct(viewDirNormalized); double arc = Math.Acos(dotProduct); // We construct three points from the two directions. // Which are then checked, to see how they are. Vertex vec1 = new Vertex(this); Vertex vec2 = new Vertex(); Vertex vec3 = new Vertex(dir); try { if (vec1.areClockwise(vec2, vec3, viewDir)) { arc *= -1; } return(arc); } // The points lie on a straight line. catch (InvalidOperationException) { return(arc); } }
public virtual void Read(BinaryReader stream) { centre = new Vertex(stream.ReadSingle(), stream.ReadSingle(), stream.ReadSingle()); directionX = new Vertex(stream.ReadSingle(), stream.ReadSingle(), stream.ReadSingle()); directionY = new Vertex(stream.ReadSingle(), stream.ReadSingle(), stream.ReadSingle()); directionZ = new Vertex(stream.ReadSingle(), stream.ReadSingle(), stream.ReadSingle()); // The X axis in SharpGL is always (1, 0, 0). xAxis = new Vertex(1, 0, 0); float angleX = xAxis.ScalarProduct(directionX); yAxis = new Vertex(0, 1, 0); float angleY = yAxis.ScalarProduct(directionY); zAxis = new Vertex(0, 0, 1); float angleZ = zAxis.ScalarProduct(directionZ); angleX = (float)System.Math.Asin(angleX); angleY = (float)System.Math.Asin(angleY); angleZ = (float)System.Math.Asin(angleZ); angleX = (180 * angleX) / (float)Math.PI; angleY = (180 * angleY) / (float)Math.PI; angleZ = (180 * angleZ) / (float)Math.PI; rotate = new Vertex(-angleX, -angleY, -angleZ); xAxis = xAxisGL = directionX; yAxis = zAxisGL = directionY; zAxis = yAxisGL = directionZ; xAxisGL.X = -xAxisGL.X; }
/// <summary> /// Tests the order of the points. /// /// Seen in the direction, indicated by the third parameter. /// </summary> /// <param name = "p1"> First point. </param> /// <param name = "p2"> Second point. </param> /// <param name = "viewDir"> View direction from which the sense of rotation should be calculated. </param> /// <exception cref="InvalidOperationException">if the points lie on a line</exception> public bool areClockwise(Vertex p1, Vertex p2, Vertex viewDir) { Vertex u = p2 - this; u.Normalize(); Vertex v = p1 - this; v.Normalize(); Vertex w = u.VectorProduct(v); double test = w.ScalarProduct(viewDir); if (Math.Abs(test) < 0.000001) { throw new InvalidOperationException("All points are on one line!"); } return(test < 0); }
/// <summary> /// This function tests to see if a ray interesects the polygon. /// </summary> /// <param name="ray">The ray you want to test.</param> /// <param name="pointOfIntersection">The actual point of intersection (if any).</param> /// <returns>The distance from the origin of the ray to the intersection, or -1 if there /// is no intersection.</returns> public Intersection TestIntersection(Ray ray) { Intersection intersect = new Intersection(); // This code came from jgt intersect_triangle code (search dogpile for it). foreach (Face face in faces) { // Assert that it's a triangle. if (face.Count != 3) { continue; } // Find the point of intersection upon the plane, as a point 't' along // the ray. Vertex point1OnPlane = vertices[face.Indices[0].Vertex]; Vertex point2OnPlane = vertices[face.Indices[1].Vertex]; Vertex point3OnPlane = vertices[face.Indices[2].Vertex]; Vertex midpointOpp1 = (point2OnPlane + point3OnPlane) / 2; Vertex midpointOpp2 = (point1OnPlane + point3OnPlane) / 2; Vertex midpointOpp3 = (point1OnPlane + point2OnPlane) / 2; Vertex planeNormal = face.GetSurfaceNormal(this); Vertex diff = point1OnPlane - ray.origin; float s1 = diff.ScalarProduct(planeNormal); float s2 = ray.direction.ScalarProduct(planeNormal); if (s2 == 0) { continue; } float t = s1 / s2; if (t < 0) { continue; } float denomintor = planeNormal.ScalarProduct(ray.direction); if (denomintor < 0.00001f && denomintor > -0.00001f) { continue; // doesn't intersect the plane. } // Vertex v = point1OnPlane - ray.origin; // float t = (v.ScalarProduct(planeNormal)) / denomintor; // Now we can get the point of intersection. Vertex vIntersect = ray.origin + (ray.direction * t); // Do my cool test. Vertex vectorTo1 = vIntersect - point1OnPlane; Vertex vectorTo2 = vIntersect - point2OnPlane; Vertex vectorTo3 = vIntersect - point3OnPlane; Vertex vectorMidTo1 = midpointOpp1 - point1OnPlane; Vertex vectorMidTo2 = midpointOpp2 - point2OnPlane; Vertex vectorMidTo3 = midpointOpp3 - point3OnPlane; if (vectorTo1.Magnitude() > vectorMidTo1.Magnitude()) { continue; } if (vectorTo2.Magnitude() > vectorMidTo2.Magnitude()) { continue; } if (vectorTo3.Magnitude() > vectorMidTo3.Magnitude()) { continue; } if (intersect.closeness == -1 || t < intersect.closeness) { // It's f*****g intersection city man intersect.point = vIntersect; intersect.intersected = true; intersect.normal = planeNormal; intersect.closeness = t; } #region The Old Raytracing code //// Get the three vertices in the face. //Vertex v1 = vertices[face.Indices[0].Vertex]; //Vertex v2 = vertices[face.Indices[1].Vertex]; //Vertex v3 = vertices[face.Indices[2].Vertex]; //// Find the vectors for the two edges of the tri that share v1. //Vertex edge1 = v2 - v1; //Vertex edge2 = v3 - v1; //// Begin calculating the determinant, also used to calculate U parameter. //Vertex pVector = ray.direction.VectorProduct(edge2); //float determinant = edge1.ScalarProduct(pVector); //// If the determinant is less than zero, it's behind the triangle i.e. //// the back face. If it's very close to zero (errorvalue) it on the plane. //float errorvalue = 0.000001f; //if(determinant < errorvalue && determinant > -errorvalue) // continue; //// Calculate the distance from vertex 1 to ray origin. //Vertex tVector = ray.origin - v1; //// Calculate the U parameter and test bounds. //float u = tVector.ScalarProduct(pVector); //if(u < 0 || u > determinant) // continue; //// Prepare to test V parameter. //Vertex qVector = tVector.VectorProduct(edge1); //// Calculate the v parameter and test bounds. //float v = ray.direction.ScalarProduct(qVector); //if(v < 0 || v > determinant) // continue; //// Calculate t, scale parameters. //float t = edge2.ScalarProduct(qVector); //float inverseDeterminant = 1.0f / determinant; //t *= inverseDeterminant; //u *= inverseDeterminant; //v *= inverseDeterminant; //// Now we have a point of intersection. Yeah. Let's got some //// magnitude into the action. //Vertex pointOfIntersection = new Vertex(t, u, v); //// OK! We've got an intersection, find how far away it it by simple //// stuff: make a vector from the origin and the intersection, and //// get it's magnitude. //Vertex vOriginToIntersection = pointOfIntersection - ray.origin; //float magnitude = (float)vOriginToIntersection.Magnitude(); //// Is this magnitude is smaller (closer) than any we've found so far? //if(intersect.closeness == -1 || magnitude < intersect.closeness) //{ // // This is the closest intersection yet, so fill in the // // intersect structure. // intersect.point.Set(t, u, v); // intersect.intersected = true; // intersect.normal = face.GetSurfaceNormal(this); // intersect.closeness = magnitude; //} #endregion } return(intersect); }
/// <summary> /// Rotates this vertex around an axel /// </summary> /// <param name="n">The vertex to rotate</param> /// <param name="a">The amount to rotate by (angle)</param> /// <param name="v">The axel to rotate around</param> /// <returns></returns> public static Vertex RotateAroundAxis(this Vertex n, float a, Vertex v) { return v*(float) Math.Cos(a) + ( n * v.ScalarProduct(n) * (1 - (float) Math.Cos(a)) + (n.VectorProduct(v)*(float) Math.Sin(a))); }