public static double GetRotationAngle(Vector3D axis, Vector3D startNormal, Vector3D endNormal) { if (startNormal.IsSame(endNormal)) return 0; if (startNormal.IsSame(-endNormal)) return 180; var cross = startNormal.Cross(axis); return cross.IsSame(endNormal) ? 90 : -90; }
public static double GetRotationAngle(Vector3D axis, Vector3D startNormal, Vector3D endNormal) { if (startNormal.IsSame(endNormal)) return Direction.Zero; if (startNormal.IsSame(-endNormal)) return Direction.Twice; var cross = startNormal.Cross(axis); return cross.IsSame(endNormal) ? Direction.Clockwise : Direction.CounterClockwise; }
public Direction(Vector3D front, Vector3D up) { Origin = new Point3D(0, 0, 0); Front = front; Back = -Front; Up = up; Down = -Up; Right = up.Cross(front); Left = -Right; All = new[] { Front, Back, Right, Left, Up, Down }; }
/// <summary> /// The three points p0, p0 + u and p0 + v make up a triangle. If 'divisions' is 1 and 'doQuad' is false,<para/> /// exactly this triangle will be added to the mesh. If 'divisions' is larger than 1, the triangle will be subdivided.<para/> /// If 'doQuad' is true, the triangle is expanded to a parallelogram using the fourth point p0 + u + v. /// </summary> public static void AddTriangles(MeshGeometry3D mesh, int divisions, Point3D p0, Vector3D u, Vector3D v, double tu0, double tu1, bool doQuad = true) { TextureTransform tt = new TextureTransform(0, divisions, tu0, tu1, 1, 0); Vector3D du = u / (double)divisions; Vector3D dv = v / (double)divisions; Vector3D n = u.Cross(v); n.Normalize(); for (int iv = 0; iv < divisions; iv++) { int iuMax = doQuad ? divisions : divisions - iv; for (int iu = 0; iu < iuMax; iu++) { Point3D p1 = p0 + iu * du + iv * dv; Point3D p2 = p1 + du; Point3D p3 = p1 + dv; Point3D p4 = p2 + dv; mesh.Positions.Add(p1); mesh.Normals.Add(n); mesh.TextureCoordinates.Add(tt.Transform(iu, iv)); mesh.Positions.Add(p2); mesh.Normals.Add(n); mesh.TextureCoordinates.Add(tt.Transform(iu + 1, iv)); mesh.Positions.Add(p3); mesh.Normals.Add(n); mesh.TextureCoordinates.Add(tt.Transform(iu, iv + 1)); int i = mesh.Positions.Count - 3; AddTriangleIndices(mesh, i, i + 1, i + 2); bool doUpperTriangle = doQuad ? true : iu < iuMax - 1; if (doUpperTriangle) { mesh.Positions.Add(p4); mesh.Normals.Add(n); mesh.TextureCoordinates.Add(tt.Transform(iu + 1, iv + 1)); AddTriangleIndices(mesh, i + 1, i + 3, i + 2); continue; } } } }
public static Transform3D Rotate(Vector3D axis, Point3D point, Vector3D startNormal, Vector3D endNormal) { var angle = GetRotationAngle(axis, startNormal, endNormal); var cross = startNormal.Cross(axis); return Rotate(axis, point, angle); }
public static Transform3D GetRotationTransform(Point3D point, Vector3D startNormal, Vector3D endNormal) { var axis = startNormal.Cross(endNormal); return GetRotationTransform(axis, point, startNormal, endNormal); }
public static List<double> RayMeshIntersections(Point3D orig, Vector3D dir, MeshGeometry3D mesh, bool frontFacesOnly) { List<double> result = new List<double>(); if (mesh == null || !dir.IsValid()) return result; double epsilon = 1E-9; Int32Collection indices = mesh.TriangleIndices; Point3DCollection positions = mesh.Positions; for (int i = 0; i < indices.Count; i += 3) { Point3D vert0 = positions[indices[i]]; Point3D vert1 = positions[indices[i + 1]]; Point3D vert2 = positions[indices[i + 2]]; //--- find vectors for two edges sharing vert0 Vector3D edge1 = vert1 - vert0; Vector3D edge2 = vert2 - vert0; //--- begin calculating determinant also used to calculate U parameter Vector3D pvec = dir.Cross(edge2); //--- if determinant is near zero ray lies in plane of triangle double det = edge1.Dot(pvec); if (det < epsilon) { if (frontFacesOnly) continue; else if (det > -epsilon) continue; } double inv_det = 1.0 / det; //--- calculate distance from vert0 to ray origin Vector3D tvec = orig - vert0; //--- calculate U parameter and test bounds double u = tvec.Dot(pvec) * inv_det; if (u < 0.0 || u > 1.0) continue; //--- prepare to test V parameter Vector3D qvec = tvec.Cross(edge1); //--- calculate V parameter and test bounds double v = dir.Dot(qvec) * inv_det; if (v < 0.0 || u + v > 1.0) continue; //--- calculate t scale parameters, ray intersects triangle double t = edge2.Dot(qvec) * inv_det; result.Add(t); } return result; }