/// <summary> /// Generates a uniform distributed random sample on the given triangle using /// two random variables x1 and x2. /// </summary> public static V3d Triangle(Triangle3d t, double x1, double x2) { return(Triangle(t.P0, t.P1, t.P2, x1, x2)); }
public DistLine3Triangle3(Line3d LineIn, Triangle3d TriangleIn) { this.triangle = TriangleIn; this.line = LineIn; }
/// <summary> /// Generates a uniform distributed random sample on the given triangle using /// two random series (seriesIndex, seriesIndex + 1). /// </summary> public static V3d Triangle(Triangle3d t, IRandomSeries rnd, int seriesIndex) { return(Triangle(t.P0, t.P1, t.P2, rnd.UniformDouble(seriesIndex), rnd.UniformDouble(seriesIndex + 1))); }
public DistPoint3Triangle3(Vector3D PointIn, Triangle3d TriangleIn) { point = PointIn; triangle = TriangleIn; }
public static Plane3d FromTriangle(Triangle3d t) { Plane3d result = new Plane3d(Vector3L.Cross(t.m_point1 - t.m_point0, t.m_point2 - t.m_point0), t.m_point0); return(result); }
public DistSegment3Triangle3(Segment3d SegmentIn, Triangle3d TriangleIn) { this.triangle = TriangleIn; this.segment = SegmentIn; }
public void CodeTriangle3d(ref Triangle3d v) { CodeV3d(ref v.P0); CodeV3d(ref v.P1); CodeV3d(ref v.P2); }
public void CodeTriangle3d(ref Triangle3d v) { AddValue(v.ToString()); }
public void CodeTriangle3d(ref Triangle3d v) { throw new NotImplementedException(); }
/// <summary> /// An array getter, optimized by reusing mappings. /// </summary> /// <param name="triangleIndex">The triangle index offset.</param> /// <param name="positionComponent">The position component.</param> /// <param name="count">Number of triangles.</param> public Triangle3d[] Get3d(string positionComponent, uint triangleIndex, uint count) { Triangle3d[] data = new Triangle3d[count]; Get(positionComponent, triangleIndex, data); return(data); }
public override void Selected(SelectionType button) { nullifyHitPos = true; transform.parent.SendMessage("Selected", button, SendMessageOptions.DontRequireReceiver); if (button == SelectionType.SELECTALL) { BlockMove = true; } else { MeshFilter mf = GetComponent <MeshFilter>(); Mesh mesh = mf.sharedMesh; currentHit = transform.InverseTransformPoint(AppState.instance.lastHitPosition); Vector3d target = currentHit; System.Random rand = new System.Random(); int count = 0; // // The algorithm will find local optima - repeat until you get the tru optima // but limit the interation using a count // Int32 current = 0; while (count < dmesh.VertexCount) { count++; // // choose a random starting point // current = rand.Next(0, dmesh.VertexCount); Vector3d vtx = dmesh.GetVertex(current); double currentDist = vtx.DistanceSquared(target); // // find the ring of triangles around the current point // int iter = 0; while (true) { iter++; // throw new InvalidOperationException("Meh One Ring operation invalid : " + res.ToString()); // // Interate through the vertices in the one Ring and find the clost to the target point // bool flag = false; foreach (Int32 v in dmesh.VtxVerticesItr(current)) { Vector3d thisVtx = dmesh.GetVertex(v); double thisDist = thisVtx.DistanceSquared(target); if (thisDist < currentDist) { flag = true; current = v; vtx = thisVtx; currentDist = thisDist; } } // // if the current point as closest - then have a local optima // if (!flag) { break; } } // // we now have a local optima // to check for a global optima look to see if hit is contained by one of the triangles in the one ring // bool f2 = false; foreach (Int32 t in dmesh.VtxTrianglesItr(current)) { Index3i tri = dmesh.GetTriangle(t); Triangle3d triangle = new Triangle3d( dmesh.GetVertex(tri.a), dmesh.GetVertex(tri.b), dmesh.GetVertex(tri.c) ); double[] xs = new double[3] { triangle.V0.x, triangle.V1.x, triangle.V2.x }; double[] ys = new double[3] { triangle.V0.y, triangle.V1.y, triangle.V2.y }; double[] zs = new double[3] { triangle.V0.z, triangle.V1.z, triangle.V2.z }; if ( target.x >= xs.Min() && target.x <= xs.Max() && target.y >= ys.Min() && target.y <= ys.Max() && target.z >= zs.Min() && target.z <= zs.Max() ) { f2 = true; currentHitTri = tri; } } // // if we found on triamgle that contain the current hit then we have finished // if (f2) { break; } } if (count >= dmesh.VertexCount) { // // This is the unoptimized verion but it is guaranteed to find a solution if one exits // current = -1; float currentDist = float.MaxValue; if (currentHit != null) { for (int i = 0; i < mesh.vertices.Length; i++) { Vector3 vtx = mesh.vertices[i]; float dist = (currentHit - vtx).sqrMagnitude; if (dist < currentDist) { current = i; currentDist = dist; } } } // // Check that the closet vertex to the point is an actual solution // bool f2 = false; foreach (Int32 t in dmesh.VtxTrianglesItr(current)) { Index3i tri = dmesh.GetTriangle(t); Triangle3d triangle = new Triangle3d( dmesh.GetVertex(tri.a), dmesh.GetVertex(tri.b), dmesh.GetVertex(tri.c) ); double[] xs = new double[3] { triangle.V0.x, triangle.V1.x, triangle.V2.x }; double[] ys = new double[3] { triangle.V0.y, triangle.V1.y, triangle.V2.y }; double[] zs = new double[3] { triangle.V0.z, triangle.V1.z, triangle.V2.z }; if ( target.x >= xs.Min() && target.x <= xs.Max() && target.y >= ys.Min() && target.y <= ys.Max() && target.z >= zs.Min() && target.z <= zs.Max() ) { f2 = true; currentHitTri = tri; } } // // if we found on triamgle that contain the current hit then we have finished // if (!f2) { Debug.LogError(" Mesh Vertex Search : No Solution Found"); return; } } selectedVertex = current; sphere = GameObject.CreatePrimitive(PrimitiveType.Sphere); sphere.transform.position = transform.TransformPoint(mesh.vertices[current]); sphere.transform.localScale = new Vector3(0.1f, 0.1f, 0.1f); sphere.transform.parent = transform; } }
/// <summary> /// Gets triangle. /// </summary> /// <param name="index">The triangle index.</param> /// <param name="positionComponent">The component where we look for position, must be /// Vector2f format.</param> /// <remarks>This is not performance wise getter.</remarks> public void Get(uint index, Triangle3d storage) { Get(CommonComponents.Position, index, storage); }
internal void AddTriangle( BspTreeBuilder builder, int tiMul3, ref Triangle3d tr, V3d normal) { var htr = (V3d.Dot(m_normal, tr.P0 - m_point), V3d.Dot(m_normal, tr.P1 - m_point), V3d.Dot(m_normal, tr.P2 - m_point)); var signs = new[] { htr.Item1, htr.Item2, htr.Item3 }.AggregateSigns(builder.m_absoluteEpsilon); if (signs == Signs.Zero) { m_zeroList.Add(tiMul3); } else if ((signs & Signs.Negative) == Signs.None) { AddTriangle(builder, tiMul3, ref tr, normal, ref m_positiveTree); } else if ((signs & Signs.Positive) == Signs.None) { AddTriangle(builder, tiMul3, ref tr, normal, ref m_negativeTree); } else { // the triangle straddles the separating plane var positivePoints = new List <BspSplitPoint>(4); var negativePoints = new List <BspSplitPoint>(4); V3d firstPoint = tr.P0; double firstHeight = htr.Item1; bool firstPositive = firstHeight > 0.0; if (firstPositive) { positivePoints.Add(new BspSplitPoint(firstPoint, 0, 0.0)); } else { negativePoints.Add(new BspSplitPoint(firstPoint, 0, 0.0)); } V3d startPoint = firstPoint; double startHeight = firstHeight; bool startPositive = firstPositive; int start = 0; int end = 1; while (end < 3) { V3d endPoint = tr[end]; double endHeight = htr.Get(end); bool endPositive = endHeight > 0.0; if (startPositive != endPositive) { V3d direction = endPoint - startPoint; double t = -startHeight / V3d.Dot(m_normal, direction); V3d newPoint = startPoint + t * direction; // note, that the same split point (reference!) is // added to both lists! var sp = new BspSplitPoint(newPoint, start, t); positivePoints.Add(sp); negativePoints.Add(sp); } if (endPositive) { positivePoints.Add(new BspSplitPoint(endPoint, end, 0.0)); } else { negativePoints.Add(new BspSplitPoint(endPoint, end, 0.0)); } start = end; startPoint = endPoint; startHeight = endHeight; startPositive = endPositive; end++; } if (startPositive != firstPositive) { V3d direction = firstPoint - startPoint; double t = -startHeight / V3d.Dot(m_normal, direction); V3d newPoint = startPoint + t * direction; var sp = new BspSplitPoint(newPoint, start, t); positivePoints.Add(sp); negativePoints.Add(sp); } // in order to ensure that all fragments of a triangle are // consecutively stored, we walk through the two point lists // twice. for this we need a store of the triangle indices int[] positiveIndices = new int[2]; int[] negativeIndices = new int[2]; // first pass: generate the cloned triangles (fragments) and // the resulting triangle indices if (positivePoints.Count > 2) { for (int i = 1; i < positivePoints.Count - 1; i++) { positiveIndices[i - 1] = builder.AddClonedTriangle(tiMul3, positivePoints[0], positivePoints[i], positivePoints[i + 1]); } } if (negativePoints.Count > 2) { for (int i = 1; i < negativePoints.Count - 1; i++) { negativeIndices[i - 1] = builder.AddClonedTriangle(tiMul3, negativePoints[0], negativePoints[i], negativePoints[i + 1]); } } // second pass: add the fragments (with the triangle // indices) to the BSP-tree if (positivePoints.Count > 2) { for (int i = 0; i < positivePoints.Count - 2; i++) { AddTriangle(builder, positiveIndices[i], ref m_positiveTree); } } if (negativePoints.Count > 2) { for (int i = 0; i < negativePoints.Count - 2; i++) { AddTriangle(builder, negativeIndices[i], ref m_negativeTree); } } } }
public DistTriangle3Triangle3(Triangle3d Triangle0in, Triangle3d Triangle1in) { this.triangle0 = Triangle0in; this.triangle1 = Triangle1in; }
/// <summary> /// Obtains a collection of triangles. /// </summary> /// <param name="index">The base index.</param> /// <param name="count">Number of triangles.</param> /// <returns>The triangle collection.</returns> public Triangle3d[] Get(uint index, uint count) { Triangle3d[] data = new Triangle3d[count]; Get(index, data); return(data); }
bool IntersectsSegment(ref Plane3d plane, ref Triangle3d triangle, Vector3D end0, Vector3D end1) { // Compute the 2D representations of the triangle vertices and the // segment endpoints relative to the plane of the triangle. Then // compute the intersection in the 2D space. // Project the triangle and segment onto the coordinate plane most // aligned with the plane normal. int maxNormal = 0; double fmax = Math.Abs(plane.Normal.x); double absMax = Math.Abs(plane.Normal.y); if (absMax > fmax) { maxNormal = 1; fmax = absMax; } absMax = Math.Abs(plane.Normal.z); if (absMax > fmax) { maxNormal = 2; } Triangle2d projTri = new Triangle2d(); Vector2D projEnd0 = Vector2D.Zero, projEnd1 = Vector2D.Zero; int i; if (maxNormal == 0) { // Project onto yz-plane. for (i = 0; i < 3; ++i) { projTri[i] = triangle[i].yz; projEnd0.x = end0.y; projEnd0.y = end0.z; projEnd1.x = end1.y; projEnd1.y = end1.z; } } else if (maxNormal == 1) { // Project onto xz-plane. for (i = 0; i < 3; ++i) { projTri[i] = triangle[i].xz; projEnd0.x = end0.x; projEnd0.y = end0.z; projEnd1.x = end1.x; projEnd1.y = end1.z; } } else { // Project onto xy-plane. for (i = 0; i < 3; ++i) { projTri[i] = triangle[i].xy; projEnd0.x = end0.x; projEnd0.y = end0.y; projEnd1.x = end1.x; projEnd1.y = end1.y; } } Segment2d projSeg = new Segment2d(projEnd0, projEnd1); IntrSegment2Triangle2 calc = new IntrSegment2Triangle2(projSeg, projTri); if (!calc.Find()) { return(false); } Vector2dTuple2 intr = new Vector2dTuple2(); if (calc.Type == IntersectionType.Segment) { Result = IntersectionResult.Intersects; Type = IntersectionType.Segment; Quantity = 2; intr.V0 = calc.Point0; intr.V1 = calc.Point1; } else { Debug.Assert(calc.Type == IntersectionType.Point); //"Intersection must be a point\n"; Result = IntersectionResult.Intersects; Type = IntersectionType.Point; Quantity = 1; intr.V0 = calc.Point0; } // Unproject the segment of intersection. if (maxNormal == 0) { double invNX = ((double)1) / plane.Normal.x; for (i = 0; i < Quantity; ++i) { double y = intr[i].x; double z = intr[i].y; double x = invNX * (plane.Constant - plane.Normal.y * y - plane.Normal.z * z); Points[i] = new Vector3D(x, y, z); } } else if (maxNormal == 1) { double invNY = ((double)1) / plane.Normal.y; for (i = 0; i < Quantity; ++i) { double x = intr[i].x; double z = intr[i].y; double y = invNY * (plane.Constant - plane.Normal.x * x - plane.Normal.z * z); Points[i] = new Vector3D(x, y, z); } } else { double invNZ = ((double)1) / plane.Normal.z; for (i = 0; i < Quantity; ++i) { double x = intr[i].x; double y = intr[i].y; double z = invNZ * (plane.Constant - plane.Normal.x * x - plane.Normal.y * y); Points[i] = new Vector3D(x, y, z); } } return(true); }
// [RMS] this only tests some basic cases... public static void test_RayBoxIntersect() { Random rand = new Random(316136327); // check that box hit works for (int ii = 0; ii < 1000; ++ii) { // generate random triangle Triangle3d t = new Triangle3d(rand.PointInRange(10), rand.PointInRange(10), rand.PointInRange(10)); AxisAlignedBox3d bounds = new AxisAlignedBox3d(t.V0); bounds.Contain(t.V1); bounds.Contain(t.V2); Vector3d c = (t.V0 + t.V1 + t.V2) / 3.0; for (int jj = 0; jj < 1000; ++jj) { Vector3d d = rand.Direction(); Ray3d ray = new Ray3d(c - 100 * d, d); IntrRay3AxisAlignedBox3 bhit = new IntrRay3AxisAlignedBox3(ray, bounds); Debug.Assert(bhit.Find()); IntrRay3Triangle3 thit = new IntrRay3Triangle3(ray, t); Debug.Assert(thit.Find()); Debug.Assert(bhit.RayParam0 < thit.RayParameter); } } int N = 100; for (int ii = 0; ii < N; ++ii) { // generate random boxes Vector3d c = rand.PointInRange(10); Vector3d e = rand.PositivePoint(); AxisAlignedBox3d aabox = new AxisAlignedBox3d(c - e, c + e); Box3d obox = new Box3d(c, Vector3d.AxisX, Vector3d.AxisY, Vector3d.AxisZ, e); double r = aabox.DiagonalLength; // center-out tests for (int jj = 0; jj < N; ++jj) { Ray3d ray = new Ray3d(c, rand.Direction()); assert_same_hit(aabox, obox, ray, true); } // outside-in tests for (int jj = 0; jj < N; ++jj) { Vector3d p = c + 2 * r * rand.Direction(); Ray3d ray = new Ray3d(p, (c - p).Normalized); assert_same_hit(aabox, obox, ray, true); } } // random rays int hits = 0; int InnerN = 1000; for (int ii = 0; ii < N; ++ii) { // generate random boxe Vector3d c = rand.PointInRange(10); Vector3d e = rand.PositivePoint(); // every tenth box, set an axis to degenerate if (ii % 10 == 0) { e[rand.Next() % 3] = 0; } AxisAlignedBox3d aabox = new AxisAlignedBox3d(c - e, c + e); Box3d obox = new Box3d(c, Vector3d.AxisX, Vector3d.AxisY, Vector3d.AxisZ, e); double r = aabox.DiagonalLength; TrivialBox3Generator boxgen = new TrivialBox3Generator() { Box = obox }; boxgen.Generate(); DMesh3 mesh = new DMesh3(); boxgen.MakeMesh(mesh); for (int i = 0; i < InnerN; ++i) { Vector3d target = c + rand.PointInRange(r); Vector3d o = c + rand.PointInRange(10 * r); Ray3d ray = new Ray3d(o, (target - o).Normalized); assert_same_hit(aabox, obox, ray, false); int hitT = MeshQueries.FindHitTriangle_LinearSearch(mesh, ray); bool bMeshHit = (hitT != DMesh3.InvalidID); if (bMeshHit) { ++hits; } IntrRay3AxisAlignedBox3 aabbhit = new IntrRay3AxisAlignedBox3(ray, aabox); Debug.Assert(aabbhit.Find() == bMeshHit); Debug.Assert(aabbhit.Test() == bMeshHit); } } System.Console.WriteLine("hit {0} of {1} rays", hits, N * InnerN); }
public IntrTriangle3Triangle3(Triangle3d t0, Triangle3d t1) { triangle0 = t0; triangle1 = t1; }
/// <summary> /// Draws the triangle. /// </summary> /// <param name="triangle">Triangle.</param> /// <param name="color">Color.</param> /// <param name="duration">Duration.</param> public static void DrawTriangle(Triangle3d triangle, Color color, float duration) { DrawLine(triangle.lineA, color, duration); DrawLine(triangle.lineB, color, duration); DrawLine(triangle.lineC, color, duration); }
bool GetCoplanarIntersection(ref Plane3d plane, ref Triangle3d tri0, ref Triangle3d tri1) { // Project triangles onto coordinate plane most aligned with plane // normal. int maxNormal = 0; double fmax = Math.Abs(plane.Normal.x); double absMax = Math.Abs(plane.Normal.y); if (absMax > fmax) { maxNormal = 1; fmax = absMax; } absMax = Math.Abs(plane.Normal.z); if (absMax > fmax) { maxNormal = 2; } Triangle2d projTri0 = new Triangle2d(), projTri1 = new Triangle2d(); int i; if (maxNormal == 0) { // Project onto yz-plane. for (i = 0; i < 3; ++i) { projTri0[i] = tri0[i].yz; projTri1[i] = tri1[i].yz; } } else if (maxNormal == 1) { // Project onto xz-plane. for (i = 0; i < 3; ++i) { projTri0[i] = tri0[i].xz; projTri1[i] = tri1[i].xz; } } else { // Project onto xy-plane. for (i = 0; i < 3; ++i) { projTri0[i] = tri0[i].xy; projTri1[i] = tri1[i].xy; } } // 2D triangle intersection routines require counterclockwise ordering. Vector2D save; Vector2D edge0 = projTri0[1] - projTri0[0]; Vector2D edge1 = projTri0[2] - projTri0[0]; if (edge0.DotPerp(edge1) < (double)0) { // Triangle is clockwise, reorder it. save = projTri0[1]; projTri0[1] = projTri0[2]; projTri0[2] = save; } edge0 = projTri1[1] - projTri1[0]; edge1 = projTri1[2] - projTri1[0]; if (edge0.DotPerp(edge1) < (double)0) { // Triangle is clockwise, reorder it. save = projTri1[1]; projTri1[1] = projTri1[2]; projTri1[2] = save; } IntrTriangle2Triangle2 intr = new IntrTriangle2Triangle2(projTri0, projTri1); if (!intr.Find()) { return(false); } PolygonPoints = new Vector3D[intr.Quantity]; // Map 2D intersections back to the 3D triangle space. Quantity = intr.Quantity; if (maxNormal == 0) { double invNX = ((double)1) / plane.Normal.x; for (i = 0; i < Quantity; i++) { double y = intr.Points[i].x; double z = intr.Points[i].y; double x = invNX * (plane.Constant - plane.Normal.y * y - plane.Normal.z * z); PolygonPoints[i] = new Vector3D(x, y, z); } } else if (maxNormal == 1) { double invNY = ((double)1) / plane.Normal.y; for (i = 0; i < Quantity; i++) { double x = intr.Points[i].x; double z = intr.Points[i].y; double y = invNY * (plane.Constant - plane.Normal.x * x - plane.Normal.z * z); PolygonPoints[i] = new Vector3D(x, y, z); } } else { double invNZ = ((double)1) / plane.Normal.z; for (i = 0; i < Quantity; i++) { double x = intr.Points[i].x; double y = intr.Points[i].y; double z = invNZ * (plane.Constant - plane.Normal.x * x - plane.Normal.y * y); PolygonPoints[i] = new Vector3D(x, y, z); } } Result = IntersectionResult.Intersects; Type = IntersectionType.Polygon; return(true); }
/// <summary> /// Splits the quad into two triangles. Note, corners ABCD are assumed to be /// in order. /// </summary> /// <param name="a">Corner A.</param> /// <param name="b">Corner B.</param> /// <param name="c">Corner C.</param> /// <param name="d">Corner D.</param> /// <param name="t1">Triangle 1.</param> /// <param name="t2">Triangle 1.</param> public static void SplitQuad(Vector3 a, Vector3 b, Vector3 c, Vector3 d, out Triangle3d t1, out Triangle3d t2) { float diagonal1 = (a - c).sqrMagnitude; float diagonal2 = (b - d).sqrMagnitude; if (diagonal1 < diagonal2) { t1 = new Triangle3d(a, b, c); t2 = new Triangle3d(a, c, d); } else { t1 = new Triangle3d(a, b, d); t2 = new Triangle3d(b, c, d); } }
static void SplitBVHNode(BVHNode node, Mesh3d model, int depth) { if (depth-- <= 0) // Decrements depth { return; } if (node.m_children == null) { // Only split if this node contains triangles if (node.m_triangles.Count > 0) { node.m_children = new BVHNode[8]; Vector3L c = node.m_bounds.m_pos; Vector3L e = node.m_bounds.GetHalfSize() * 0.5f; node.m_children[0].m_bounds = new AABB3d(c + new Vector3L(-e.x, +e.y, -e.z), node.m_bounds.GetHalfSize()); node.m_children[1].m_bounds = new AABB3d(c + new Vector3L(+e.x, +e.y, -e.z), node.m_bounds.GetHalfSize()); node.m_children[2].m_bounds = new AABB3d(c + new Vector3L(-e.x, +e.y, +e.z), node.m_bounds.GetHalfSize()); node.m_children[3].m_bounds = new AABB3d(c + new Vector3L(+e.x, +e.y, +e.z), node.m_bounds.GetHalfSize()); node.m_children[4].m_bounds = new AABB3d(c + new Vector3L(-e.x, -e.y, -e.z), node.m_bounds.GetHalfSize()); node.m_children[5].m_bounds = new AABB3d(c + new Vector3L(+e.x, -e.y, -e.z), node.m_bounds.GetHalfSize()); node.m_children[6].m_bounds = new AABB3d(c + new Vector3L(-e.x, -e.y, +e.z), node.m_bounds.GetHalfSize()); node.m_children[7].m_bounds = new AABB3d(c + new Vector3L(+e.x, -e.y, +e.z), node.m_bounds.GetHalfSize()); } } // If this node was just split if (node.m_children != null && node.m_triangles.Count > 0) { for (int i = 0; i < 8; ++i) { // For each child // Count how many triangles each child will contain //node.m_children[i].numTriangles = 0; for (int j = 0; j < node.m_triangles.Count; ++j) { Triangle3d t = node.m_triangles[j]; if (IntersectionTest3D.Triangle3dWithAABB3d(t, node.m_children[i].m_bounds)) { node.m_children[i].m_triangles.Add(t); } } // if (node.children[i].numTriangles == 0) { // continue; // } // node.children[i].triangles = new int[node.children[i].numTriangles]; // int index = 0; // Add the triangles in the new child arrau // for (int j = 0; j < node.numTriangles; ++j) // { // Triangle t = model.triangles[node.triangles[j]]; // if (TriangleAABB(t, node.children[i].bounds)) { // node.children[i].triangles[index++] = node.triangles[j]; // } // } } //node.numTriangles = 0; //delete[] node.triangles; node.m_triangles.Clear(); // Recurse for (int i = 0; i < 8; ++i) { SplitBVHNode(node.m_children[i], model, depth); } } }