public void TestProperties() { TriangleShape t = new TriangleShape(); Assert.AreEqual(new Vector3(), t.Vertex0); Assert.AreEqual(new Vector3(), t.Vertex1); Assert.AreEqual(new Vector3(), t.Vertex2); t.Vertex0 = new Vector3(1, 2, 3); Assert.AreEqual(new Vector3(1, 2, 3), t.Vertex0); Assert.AreEqual(new Vector3(), t.Vertex1); Assert.AreEqual(new Vector3(), t.Vertex2); t.Vertex1 = new Vector3(4, 5, 6); Assert.AreEqual(new Vector3(1, 2, 3), t.Vertex0); Assert.AreEqual(new Vector3(4, 5, 6), t.Vertex1); Assert.AreEqual(new Vector3(), t.Vertex2); t.Vertex2 = new Vector3(9, 7, 8); Assert.AreEqual(new Vector3(1, 2, 3), t.Vertex0); Assert.AreEqual(new Vector3(4, 5, 6), t.Vertex1); Assert.AreEqual(new Vector3(9, 7, 8), t.Vertex2); Assert.IsTrue(Vector3.AreNumericallyEqual(Vector3.Cross(new Vector3(3, 3, 3), new Vector3(8, 5, 5)).Normalized, t.Normal)); // Degenerate triangles can have any normal. Assert.IsTrue(Numeric.AreEqual(1, new TriangleShape().Normal.Length)); }
public void TestIndexer() { TriangleShape t = new TriangleShape(); Assert.AreEqual(new Vector3(), t[0]); Assert.AreEqual(new Vector3(), t[1]); Assert.AreEqual(new Vector3(), t[2]); t[0] = new Vector3(1, 2, 3); Assert.AreEqual(new Vector3(1, 2, 3), t[0]); Assert.AreEqual(new Vector3(), t[1]); Assert.AreEqual(new Vector3(), t[2]); t[1] = new Vector3(4, 5, 6); Assert.AreEqual(new Vector3(1, 2, 3), t[0]); Assert.AreEqual(new Vector3(4, 5, 6), t[1]); Assert.AreEqual(new Vector3(), t[2]); t[2] = new Vector3(7, 8, 9); Assert.AreEqual(new Vector3(1, 2, 3), t[0]); Assert.AreEqual(new Vector3(4, 5, 6), t[1]); Assert.AreEqual(new Vector3(7, 8, 9), t[2]); Assert.AreEqual(t.Vertex0, t[0]); Assert.AreEqual(t.Vertex1, t[1]); Assert.AreEqual(t.Vertex2, t[2]); }
public void SerializationXml() { var a = new TriangleShape(new Vector3(1, 2, 3), new Vector3(4, 5, 6), new Vector3(7, 8, 9)); // Serialize object. var stream = new MemoryStream(); var serializer = new XmlSerializer(typeof(Shape)); serializer.Serialize(stream, a); // Output generated xml. Can be manually checked in output window. stream.Position = 0; var xml = new StreamReader(stream).ReadToEnd(); Trace.WriteLine("Serialized Object:\n" + xml); // Deserialize object. stream.Position = 0; var deserializer = new XmlSerializer(typeof(Shape)); var b = (TriangleShape)deserializer.Deserialize(stream); Assert.AreEqual(a.Vertex0, b.Vertex0); Assert.AreEqual(a.Vertex1, b.Vertex1); Assert.AreEqual(a.Vertex2, b.Vertex2); }
public void Update() { if (Input.GetKeyDown(KeyCode.G)) { RectShape rectShape = new RectShape(); rectShape.position = new Vector3(UnityEngine.Random.Range(-100, 100), UnityEngine.Random.Range(-100, 100)); rectShape.size = new Vector3(UnityEngine.Random.Range(1, 100), UnityEngine.Random.Range(1, 100)); this.ShapeContainer.Shapes.Add(rectShape); } if (Input.GetKeyDown(KeyCode.H)) { CircleShape circleShape = new CircleShape(); circleShape.position = new Vector3(UnityEngine.Random.Range(-100, 100), UnityEngine.Random.Range(-100, 100)); circleShape.radius = UnityEngine.Random.Range(1, 100); this.ShapeContainer.Shapes.Add(circleShape); } if (Input.GetKeyDown(KeyCode.J)) { TriangleShape triangleShape = new TriangleShape(); triangleShape.position1 = new Vector3(UnityEngine.Random.Range(-100, 100), UnityEngine.Random.Range(-100, 100)); triangleShape.position2 = new Vector3(UnityEngine.Random.Range(-100, 100), UnityEngine.Random.Range(-100, 100)); triangleShape.position3 = new Vector3(UnityEngine.Random.Range(-100, 100), UnityEngine.Random.Range(-100, 100)); this.ShapeContainer.Shapes.Add(triangleShape); } }
private Shape GetShape(MouseEventArgs e) { Color color = Color.Black; Rectangle rect = GetRect(e); if (redToolStripMenuItem.Checked) { color = Color.Red; } else if (blueToolStripMenuItem.Checked) { color = Color.Blue; } else if (greenToolStripMenuItem.Checked) { color = Color.Green; } Shape shape; if (ellipseToolStripMenuItem.Checked) { shape = new EllipseShape(color, rect); } else if (triangleToolStripMenuItem.Checked) { shape = new TriangleShape(color, rect); } else { shape = new RectangleShape(color, rect); } return(shape); }
protected override void ConfigureCollidable(TriangleEntry entry, float dt) { TriangleShape shape = entry.Collidable.Shape; mesh.Shape.TriangleMesh.Data.GetTriangle(entry.Index, out shape.vA, out shape.vB, out shape.vC); Matrix3x3 o; Matrix3x3.CreateFromQuaternion(ref mesh.worldTransform.Orientation, out o); Matrix3x3.Transform(ref shape.vA, ref o, out shape.vA); Matrix3x3.Transform(ref shape.vB, ref o, out shape.vB); Matrix3x3.Transform(ref shape.vC, ref o, out shape.vC); Vector3 center; Vector3.Add(ref shape.vA, ref shape.vB, out center); Vector3.Add(ref center, ref shape.vC, out center); Vector3.Multiply(ref center, 1 / 3f, out center); Vector3.Subtract(ref shape.vA, ref center, out shape.vA); Vector3.Subtract(ref shape.vB, ref center, out shape.vB); Vector3.Subtract(ref shape.vC, ref center, out shape.vC); Vector3.Add(ref center, ref mesh.worldTransform.Position, out center); //The bounding box doesn't update by itself. entry.Collidable.worldTransform.Position = center; entry.Collidable.worldTransform.Orientation = Quaternion.Identity; entry.Collidable.UpdateBoundingBoxInternal(dt); }
protected override TriangleCollidable GetOpposingCollidable(int index) { //Construct a TriangleCollidable from the static mesh. TriangleCollidable toReturn = PhysicsResources.GetTriangleCollidable(); TriangleShape shape = toReturn.Shape; mesh.Shape.TriangleMesh.Data.GetTriangle(index, out shape.vA, out shape.vB, out shape.vC); Matrix3x3.Transform(ref shape.vA, ref mesh.worldTransform.LinearTransform, out shape.vA); Matrix3x3.Transform(ref shape.vB, ref mesh.worldTransform.LinearTransform, out shape.vB); Matrix3x3.Transform(ref shape.vC, ref mesh.worldTransform.LinearTransform, out shape.vC); Vector3 center; Vector3.Add(ref shape.vA, ref shape.vB, out center); Vector3.Add(ref center, ref shape.vC, out center); Vector3.Multiply(ref center, 1 / 3f, out center); Vector3.Subtract(ref shape.vA, ref center, out shape.vA); Vector3.Subtract(ref shape.vB, ref center, out shape.vB); Vector3.Subtract(ref shape.vC, ref center, out shape.vC); Vector3.Add(ref center, ref mesh.worldTransform.Translation, out center); //The bounding box doesn't update by itself. toReturn.worldTransform.Position = center; toReturn.worldTransform.Orientation = Quaternion.Identity; toReturn.UpdateBoundingBoxInternal(0); shape.sidedness = mesh.Sidedness; shape.collisionMargin = mobileMesh.Shape.MeshCollisionMargin; return(toReturn); }
public static void CreateITraceableForMesh(List <PlatingMeshData> perMeshInfo, List <Mesh> meshes, int i) { if (meshes[i] != null) { List <IRayTraceable> allPolys = new List <IRayTraceable>(); List <Vector3> positions = new List <Vector3>(); foreach (Face face in meshes[i].Faces) { positions.Clear(); foreach (Vertex vertex in face.VertexIterator()) { positions.Add(vertex.Position); } // We should use the teselator for this if it is greater than 3. Vector3 next = positions[1]; for (int positionIndex = 2; positionIndex < positions.Count; positionIndex++) { TriangleShape triangel = new TriangleShape(positions[0], next, positions[positionIndex], null); allPolys.Add(triangel); next = positions[positionIndex]; } } perMeshInfo[i].traceableData = BoundingVolumeHierarchy.CreateNewHierachy(allPolys); } }
void TryToEscape(TriangleShape triangle, ref Vector3 position) { if (++escapeAttempts == EscapeAttemptPeriod && GetVoronoiRegion(triangle, ref position) == VoronoiRegion.ABC) { escapeAttempts = 0; state = CollisionState.Plane; } }
public void IsTriangleSquareAngle() { double a = 30, b = 50, c = 40; var triangle = new TriangleShape(a, b, c); var isSquareAngle = triangle.IsSquareAngle; Assert.AreEqual(true, isSquareAngle); }
public ShapeDemo(Layer layer) : base(layer) { // You can instantiate shapes instead of using static methods. _triangle = new TriangleShape(); _triangle.Point1 = new Vector2(32, 32); _triangle.Point2 = new Vector2(-32, 32); _triangle.Point3 = new Vector2(-32, -32); _triangle.IsOutline = true; }
public void IsTriangleNotSquareAngle() { double a = 8, b = 7, c = 9; var triangle = new TriangleShape(a, b, c); var isSquareAngle = triangle.IsSquareAngle; Assert.AreEqual(false, isSquareAngle); }
/// <summary> /// Retrieves a Triangle shape from the resource pool. /// </summary> /// <param name="v1">Position of the first vertex.</param> /// <param name="v2">Position of the second vertex.</param> /// <param name="v3">Position of the third vertex.</param> /// <returns>Initialized TriangleShape.</returns> public static TriangleShape GetTriangle(ref Vector3 v1, ref Vector3 v2, ref Vector3 v3) { TriangleShape toReturn = SubPoolTriangleShape.Take(); toReturn.vA = v1; toReturn.vB = v2; toReturn.vC = v3; return(toReturn); }
public void TriangleShapeSquareCalc() { // Геометрическая фигура треугольника var triangle = new TriangleShape(3, 4, 5); // Вычисляется площадь треугольника var square = Calculator.CalculateShapeSquare(triangle); Assert.AreEqual(6d, square); }
/// <summary> /// Returns a resource to the pool. /// </summary> /// <param name="triangle">Triangle to return.</param> public static void GiveBack(TriangleShape triangle) { if (SubPoolTriangleShape == null) { SubPoolTriangleShape = new UnsafeResourcePool <TriangleShape>(); } triangle.collisionMargin = 0; triangle.sidedness = TriangleSidedness.DoubleSided; SubPoolTriangleShape.GiveBack(triangle); }
private bool DoExternalSeparated(TriangleShape triangle, out TinyStructList <ContactData> contactList) { if (GJKToolbox.AreShapesIntersecting(convex, triangle, ref Toolbox.RigidIdentity, ref Toolbox.RigidIdentity, ref localSeparatingAxis)) { state = CollisionState.ExternalNear; return(DoExternalNear(triangle, out contactList)); } TryToEscape(); contactList = new TinyStructList <ContactData>(); return(false); }
public static (List <TriangleShape> floors, List <TriangleShape> walls) GetWallFoorTrianglesForShape( int numSides, double shapeRadius, double shapeAngle, double shapeX, double shapeZ) { List <(double, double)> vertices = new List <(double, double)>(); for (int i = 0; i < numSides; i++) { double angle = 65536d / numSides * i + shapeAngle; (double, double)vertex = MoreMath.AddVectorToPoint(shapeRadius, angle, shapeX, shapeZ); vertices.Add(vertex); } List <((double, double), (double, double), bool)> vertexPairs = new List <((double, double), (double, double), bool)>(); for (int i = 0; i < vertices.Count; i++) { (double v1X, double v1Z) = vertices[i]; (double v2X, double v2Z) = vertices[(i + 1) % vertices.Count]; ushort angle = MoreMath.AngleTo_AngleUnitsRounded(v1X, v1Z, v2X, v2Z); bool xProj = (angle <= 8192) || (angle >= 24576 && angle <= 40960) || (angle >= 57344); vertexPairs.Add(((v1X, v1Z), (v2X, v2Z), xProj)); } List <TriangleShape> wallTris = new List <TriangleShape>(); foreach (var((x1, z1), (x2, z2), proj) in vertexPairs) { double angle = MoreMath.AngleTo_AngleUnits(x1, z1, x2, z2); double projAngle = proj ? 16384 : 0; double projDist = 50 / Math.Sin(MoreMath.AngleUnitsToRadians(angle - projAngle)); (double p1X, double p1Z) = MoreMath.AddVectorToPoint(projDist, projAngle, x1, z1); (double p2X, double p2Z) = MoreMath.AddVectorToPoint(-1 * projDist, projAngle, x1, z1); (double p3X, double p3Z) = MoreMath.AddVectorToPoint(projDist, projAngle, x2, z2); (double p4X, double p4Z) = MoreMath.AddVectorToPoint(-1 * projDist, projAngle, x2, z2); TriangleShape triShape1 = new TriangleShape(p1X, 0, p1Z, p2X, 0, p2Z, p3X, 0, p3Z); TriangleShape triShape2 = new TriangleShape(p2X, 0, p2Z, p3X, 0, p3Z, p4X, 0, p4Z); wallTris.Add(triShape1); wallTris.Add(triShape2); } List <TriangleShape> floorTris = new List <TriangleShape>(); foreach (var((x1, z1), (x2, z2), proj) in vertexPairs) { TriangleShape triShape = new TriangleShape(x1, 0, z1, x2, 0, z2, shapeX, 0, shapeZ); floorTris.Add(triShape); } return(floorTris, wallTris); }
public void Clone() { TriangleShape triangle = new TriangleShape(new Vector3F(1, 2, 3), new Vector3F(2, 3, 4), new Vector3F(4, 5, 6)); TriangleShape clone = triangle.Clone() as TriangleShape; Assert.IsNotNull(clone); Assert.AreEqual(triangle.Vertex0, clone.Vertex0); Assert.AreEqual(triangle.Vertex1, clone.Vertex1); Assert.AreEqual(triangle.Vertex2, clone.Vertex2); Assert.AreEqual(triangle.GetAabb(Pose.Identity).Minimum, clone.GetAabb(Pose.Identity).Minimum); Assert.AreEqual(triangle.GetAabb(Pose.Identity).Maximum, clone.GetAabb(Pose.Identity).Maximum); }
public void IsTriangleSizeEqual() { double a = 14, b = 15, c = 12; var triangle = new TriangleShape(a, b, c); var p = 1 / 2 * (a + b + c); var ExpectedASize = Math.Sqrt(p * (p - a) * (p - b) * (p - c)); var aSize = AreaCalculator.GetAreaSize(triangle); Assert.AreEqual(ExpectedASize, aSize); }
public void IsRectangularTriangle() { // Прямоугольный треугольник var rectTriangle = new TriangleShape(3, 4, 5); Assert.IsTrue(rectTriangle.IsRectangular()); // Простой треугольник var simpleTriangle = new TriangleShape(3, 3, 4); Assert.IsFalse(simpleTriangle.IsRectangular()); }
protected override bool ConfigureLocalTriangle(int i, TriangleShape localTriangleShape, out TriangleIndices indices) { MeshBoundingBoxTreeData data = mesh.Shape.TriangleMesh.Data; int triangleIndex = overlappedTriangles.Elements[i]; TriangleSidedness sidedness; //TODO: Note superhack; don't do this in v2. if (IsQuery) { sidedness = TriangleSidedness.DoubleSided; } else { switch (mesh.Shape.solidity) { case MobileMeshSolidity.Clockwise: sidedness = TriangleSidedness.Clockwise; break; case MobileMeshSolidity.Counterclockwise: sidedness = TriangleSidedness.Counterclockwise; break; case MobileMeshSolidity.DoubleSided: sidedness = TriangleSidedness.DoubleSided; break; default: sidedness = mesh.Shape.SidednessWhenSolid; break; } } localTriangleShape.sidedness = sidedness; localTriangleShape.collisionMargin = 0; indices = new TriangleIndices { A = data.indices[triangleIndex], B = data.indices[triangleIndex + 1], C = data.indices[triangleIndex + 2] }; localTriangleShape.vA = data.vertices[indices.A]; localTriangleShape.vB = data.vertices[indices.B]; localTriangleShape.vC = data.vertices[indices.C]; return(true); }
/// <summary> /// Gets an object which represents a Triangle. /// </summary> /// <returns>An object which represents a square.</returns> public BaseShape GetTriangle() { TriangleShape defaultTriangleShape = new TriangleShape { ShapeIdentifire = ShapeIdGenerator.GenerateUniqued(), XPosition = 50, YPosition = 50, ShapeHeight = 50, ShapeWidth = 100, ShapeColor = "Black" }; return(defaultTriangleShape); }
public void GetMesh() { var t = new TriangleShape(new Vector3F(1, 2, 3), new Vector3F(4, 5, 6), new Vector3F(8, 9, -1)); var m = t.GetMesh(0, 1); Assert.AreEqual(1, m.NumberOfTriangles); Triangle t2 = m.GetTriangle(0); Assert.AreEqual(t.Vertex0, t2.Vertex0); Assert.AreEqual(t.Vertex1, t2.Vertex1); Assert.AreEqual(t.Vertex2, t2.Vertex2); }
int GetSamePointCount(TriangleShape triangle, int[] otherSameIndexArray, int[] mySameIndexArray) { int count = 0; for (int i = 0; i < triangle.PosArray.Length; ++i) { int mySameIndex = 0; if (IsNearWithVertex(triangle.PosArray[i], out mySameIndex)) { mySameIndexArray [count] = mySameIndex; otherSameIndexArray [count++] = i; } } return(count); }
//TODO: Having a specialized triangle-triangle pair test would be nice. Even if it didn't use an actual triangle-triangle test, certain assumptions could still make it speedier and more elegant. //"Closest points between triangles" + persistent manifolding would probably be the best approach (a lot faster than the triangle-convex general case anyway). public override bool GenerateContactCandidates(TriangleShape triangle, out TinyStructList <ContactData> contactList) { if (base.GenerateContactCandidates(triangle, out contactList)) { //The triangle-convex pair test has already rejected contacts whose normals would violate the first triangle's sidedness. //However, since it's a vanilla triangle-convex test, it doesn't know about the sidedness of the other triangle! TriangleShape shape = (TriangleShape)convex; Vector3 normal; //Lots of recalculating ab-bc! Vector3 ab, ac; Vector3.Subtract(ref shape.vB, ref shape.vA, out ab); Vector3.Subtract(ref shape.vC, ref shape.vA, out ac); Vector3.Cross(ref ab, ref ac, out normal); TriangleSidedness sidedness = shape.sidedness; if (sidedness != TriangleSidedness.DoubleSided) { for (int i = contactList.Count - 1; i >= 0; i--) { ContactData item; contactList.Get(i, out item); float dot; Vector3.Dot(ref item.Normal, ref normal, out dot); if (sidedness == TriangleSidedness.Clockwise) { if (dot < 0) { contactList.RemoveAt(i); } } else { if (dot > 0) { contactList.RemoveAt(i); } } } } return(contactList.Count > 0); } return(false); }
private static List <IPrimitive> AddTraceDataForMesh(Mesh mesh, int totalActionCount, ref int currentAction, ref bool needToUpdateProgressReport, ReportProgressRatio reportProgress) { bool continueProcessing; List <IPrimitive> allPolys = new List <IPrimitive>(); List <Vector3> positions = new List <Vector3>(); foreach (Face face in mesh.Faces) { if (false) { MeshFaceTraceable triangle = new MeshFaceTraceable(face); allPolys.Add(triangle); } else { positions.Clear(); foreach (Vertex vertex in face.Vertices()) { positions.Add(vertex.Position); } // We should use the tessellator for this if it is greater than 3. Vector3 next = positions[1]; for (int positionIndex = 2; positionIndex < positions.Count; positionIndex++) { TriangleShape triangle = new TriangleShape(positions[0], next, positions[positionIndex], null); allPolys.Add(triangle); next = positions[positionIndex]; } } if (reportProgress != null) { if ((currentAction % 256) == 0 || needToUpdateProgressReport) { reportProgress(currentAction / (double)totalActionCount, "Creating Trace Polygons", out continueProcessing); needToUpdateProgressReport = false; } currentAction++; } } return(allPolys); }
public static void RenderBounds(DrawEventArgs e, WorldView World, IEnumerable <BvhIterator> allResults) { foreach (var x in allResults) { for (int i = 0; i < 4; i++) { Vector3 bottomStartPosition = Vector3.Transform(x.Bvh.GetAxisAlignedBoundingBox().GetBottomCorner(i), x.TransformToWorld); var bottomStartScreenPos = World.GetScreenPosition(bottomStartPosition); Vector3 bottomEndPosition = Vector3.Transform(x.Bvh.GetAxisAlignedBoundingBox().GetBottomCorner((i + 1) % 4), x.TransformToWorld); var bottomEndScreenPos = World.GetScreenPosition(bottomEndPosition); Vector3 topStartPosition = Vector3.Transform(x.Bvh.GetAxisAlignedBoundingBox().GetTopCorner(i), x.TransformToWorld); var topStartScreenPos = World.GetScreenPosition(topStartPosition); Vector3 topEndPosition = Vector3.Transform(x.Bvh.GetAxisAlignedBoundingBox().GetTopCorner((i + 1) % 4), x.TransformToWorld); var topEndScreenPos = World.GetScreenPosition(topEndPosition); e.Graphics2D.Line(bottomStartScreenPos, bottomEndScreenPos, Color.Black); e.Graphics2D.Line(topStartScreenPos, topEndScreenPos, Color.Black); e.Graphics2D.Line(topStartScreenPos, bottomStartScreenPos, Color.Black); } TriangleShape tri = x.Bvh as TriangleShape; if (tri != null) { for (int i = 0; i < 3; i++) { var vertexPos = tri.GetVertex(i); var screenCenter = Vector3.Transform(vertexPos, x.TransformToWorld); var screenPos = World.GetScreenPosition(screenCenter); e.Graphics2D.Circle(screenPos, 3, Color.Red); } } else { var center = x.Bvh.GetCenter(); var worldCenter = Vector3.Transform(center, x.TransformToWorld); var screenPos2 = World.GetScreenPosition(worldCenter); e.Graphics2D.Circle(screenPos2, 3, Color.Yellow); e.Graphics2D.DrawString($"{x.Depth},", screenPos2.X + 12 * x.Depth, screenPos2.Y); } } }
void OnTriggerEnter2D(Collider2D other) { TriangleShape elem = other.gameObject.GetComponent <TriangleShape>(); if (elem != null) { count++; Debug.Log("is triangle"); if (count == maxcount) { Transform wall = Instantiate(prefab, this.transform.position, this.transform.rotation) as Transform; } } else { Debug.Log("Something other than a square has entered"); } }
protected override bool ConfigureLocalTriangle(int i, TriangleShape localTriangleShape, out TriangleIndices indices) { int triangleIndex = overlappedTriangles.Elements[i]; var data = mesh.Mesh.Data; localTriangleShape.vA = data.vertices[data.indices[triangleIndex]]; localTriangleShape.vB = data.vertices[data.indices[triangleIndex + 1]]; localTriangleShape.vC = data.vertices[data.indices[triangleIndex + 2]]; localTriangleShape.sidedness = mesh.sidedness; localTriangleShape.collisionMargin = 0; indices = new TriangleIndices { A = data.indices[triangleIndex], B = data.indices[triangleIndex + 1], C = data.indices[triangleIndex + 2] }; return(true); }
/// <summary> /// Retrieves a TriangleCollidable from the resource pool. /// </summary> /// <param name="a">First vertex in the triangle.</param> /// <param name="b">Second vertex in the triangle.</param> /// <param name="c">Third vertex in the triangle.</param> /// <returns>Initialized TriangleCollidable.</returns> public static TriangleCollidable GetTriangleCollidable(ref Vector3 a, ref Vector3 b, ref Vector3 c) { if (SubPoolTriangleCollidables == null) { SubPoolTriangleCollidables = new UnsafeResourcePool <TriangleCollidable>(); } TriangleCollidable tri = SubPoolTriangleCollidables.Take(); TriangleShape shape = tri.Shape; shape.vA = a; shape.vB = b; shape.vC = c; RigidTransform identity = RigidTransform.Identity; tri.UpdateBoundingBoxForTransform(ref identity); return(tri); }
public virtual void ProcessTriangle(IndexedVector3[] triangle, int partId, int triangleIndex) { //skip self-collisions if ((m_partIdA == partId) && (m_triangleIndexA == triangleIndex)) { return; } //skip duplicates (disabled for now) //if ((m_partIdA <= partId) && (m_triangleIndexA <= triangleIndex)) // return; //search for shared vertices and edges int numshared = 0; int[] sharedVertsA = new int[] { -1, -1, -1 }; int[] sharedVertsB = new int[] { -1, -1, -1 }; ///skip degenerate triangles float crossBSqr = IndexedVector3.Cross((triangle[1] - triangle[0]), (triangle[2] - triangle[0])).LengthSquared(); if (crossBSqr < m_triangleInfoMap.m_equalVertexThreshold) { return; } float crossASqr = IndexedVector3.Cross((m_triangleVerticesA[1] - m_triangleVerticesA[0]), (m_triangleVerticesA[2] - m_triangleVerticesA[0])).LengthSquared(); ///skip degenerate triangles if (crossASqr < m_triangleInfoMap.m_equalVertexThreshold) { return; } #if false printf("triangle A[0] = (%f,%f,%f)\ntriangle A[1] = (%f,%f,%f)\ntriangle A[2] = (%f,%f,%f)\n", m_triangleVerticesA[0].GetX(),m_triangleVerticesA[0].GetY(),m_triangleVerticesA[0].GetZ(), m_triangleVerticesA[1].GetX(),m_triangleVerticesA[1].GetY(),m_triangleVerticesA[1].GetZ(), m_triangleVerticesA[2].GetX(),m_triangleVerticesA[2].GetY(),m_triangleVerticesA[2].GetZ()); printf("partId=%d, triangleIndex=%d\n",partId,triangleIndex); printf("triangle B[0] = (%f,%f,%f)\ntriangle B[1] = (%f,%f,%f)\ntriangle B[2] = (%f,%f,%f)\n", triangle[0].GetX(),triangle[0].GetY(),triangle[0].GetZ(), triangle[1].GetX(),triangle[1].GetY(),triangle[1].GetZ(), triangle[2].GetX(),triangle[2].GetY(),triangle[2].GetZ()); #endif for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { if ((m_triangleVerticesA[i] - triangle[j]).LengthSquared() < m_triangleInfoMap.m_equalVertexThreshold) { sharedVertsA[numshared] = i; sharedVertsB[numshared] = j; numshared++; ///degenerate case if (numshared >= 3) { return; } } } ///degenerate case if (numshared >= 3) { return; } } switch (numshared) { case 0: { break; } case 1: { //shared vertex break; } case 2: { //shared edge //we need to make sure the edge is in the order V2V0 and not V0V2 so that the signs are correct if (sharedVertsA[0] == 0 && sharedVertsA[1] == 2) { sharedVertsA[0] = 2; sharedVertsA[1] = 0; int tmp = sharedVertsB[1]; sharedVertsB[1] = sharedVertsB[0]; sharedVertsB[0] = tmp; } int hash = GetHash(m_partIdA, m_triangleIndexA); TriangleInfo info = null; if (m_triangleInfoMap.ContainsKey(hash)) { info = m_triangleInfoMap[hash]; } else { info = new TriangleInfo(); m_triangleInfoMap[hash] = info; } int sumvertsA = sharedVertsA[0] + sharedVertsA[1]; int otherIndexA = 3 - sumvertsA; IndexedVector3 edge = new IndexedVector3(m_triangleVerticesA[sharedVertsA[1]] - m_triangleVerticesA[sharedVertsA[0]]); TriangleShape tA = new TriangleShape(m_triangleVerticesA[0], m_triangleVerticesA[1], m_triangleVerticesA[2]); int otherIndexB = 3 - (sharedVertsB[0] + sharedVertsB[1]); TriangleShape tB = new TriangleShape(triangle[sharedVertsB[1]], triangle[sharedVertsB[0]], triangle[otherIndexB]); //btTriangleShape tB(triangle[0],triangle[1],triangle[2]); IndexedVector3 normalA; IndexedVector3 normalB; tA.CalcNormal(out normalA); tB.CalcNormal(out normalB); edge.Normalize(); IndexedVector3 edgeCrossA = IndexedVector3.Normalize(IndexedVector3.Cross(edge, normalA)); { IndexedVector3 tmp = m_triangleVerticesA[otherIndexA] - m_triangleVerticesA[sharedVertsA[0]]; if (IndexedVector3.Dot(edgeCrossA, tmp) < 0) { edgeCrossA *= -1; } } IndexedVector3 edgeCrossB = IndexedVector3.Cross(edge, normalB).Normalized(); { IndexedVector3 tmp = triangle[otherIndexB] - triangle[sharedVertsB[0]]; if (IndexedVector3.Dot(edgeCrossB, tmp) < 0) { edgeCrossB *= -1; } } float angle2 = 0; float ang4 = 0.0f; IndexedVector3 calculatedEdge = IndexedVector3.Cross(edgeCrossA, edgeCrossB); float len2 = calculatedEdge.LengthSquared(); float correctedAngle = 0f; IndexedVector3 calculatedNormalB = normalA; bool isConvex = false; if (len2 < m_triangleInfoMap.m_planarEpsilon) { angle2 = 0.0f; ang4 = 0.0f; } else { calculatedEdge.Normalize(); IndexedVector3 calculatedNormalA = IndexedVector3.Cross(calculatedEdge, edgeCrossA); calculatedNormalA.Normalize(); angle2 = GetAngle(ref calculatedNormalA, ref edgeCrossA, ref edgeCrossB); ang4 = MathUtil.SIMD_PI - angle2; float dotA = IndexedVector3.Dot(normalA, edgeCrossB); ///@todo: check if we need some epsilon, due to floating point imprecision isConvex = (dotA < 0f); correctedAngle = isConvex ? ang4 : -ang4; IndexedQuaternion orn2 = new IndexedQuaternion(calculatedEdge, -correctedAngle); IndexedMatrix rotateMatrix = IndexedMatrix.CreateFromQuaternion(orn2); calculatedNormalB = new IndexedBasisMatrix(orn2) * normalA; } //alternatively use //IndexedVector3 calculatedNormalB2 = quatRotate(orn,normalA); switch (sumvertsA) { case 1: { IndexedVector3 edge1 = m_triangleVerticesA[0] - m_triangleVerticesA[1]; IndexedQuaternion orn = new IndexedQuaternion(edge1, -correctedAngle); IndexedVector3 computedNormalB = MathUtil.QuatRotate(orn, normalA); float bla = IndexedVector3.Dot(computedNormalB, normalB); if (bla < 0) { computedNormalB *= -1; info.m_flags |= TriangleInfoMap.TRI_INFO_V0V1_SWAP_NORMALB; } #if DEBUG_INTERNAL_EDGE if ((computedNormalB - normalB).Length() > 0.0001f) { System.Console.WriteLine("warning: normals not identical"); } #endif//DEBUG_INTERNAL_EDGE info.m_edgeV0V1Angle = -correctedAngle; if (isConvex) { info.m_flags |= TriangleInfoMap.TRI_INFO_V0V1_CONVEX; } break; } case 2: { IndexedVector3 edge1 = m_triangleVerticesA[2] - m_triangleVerticesA[0]; IndexedQuaternion orn = new IndexedQuaternion(edge1, -correctedAngle); IndexedVector3 computedNormalB = MathUtil.QuatRotate(orn, normalA); if (IndexedVector3.Dot(computedNormalB, normalB) < 0) { computedNormalB *= -1; info.m_flags |= TriangleInfoMap.TRI_INFO_V2V0_SWAP_NORMALB; } #if DEBUG_INTERNAL_EDGE if ((computedNormalB - normalB).Length() > 0.0001) { System.Console.WriteLine("warning: normals not identical"); } #endif //DEBUG_INTERNAL_EDGE info.m_edgeV2V0Angle = -correctedAngle; if (isConvex) info.m_flags |= TriangleInfoMap.TRI_INFO_V2V0_CONVEX; break; } case 3: { IndexedVector3 edge1 = m_triangleVerticesA[1] - m_triangleVerticesA[2]; IndexedQuaternion orn = new IndexedQuaternion(edge1, -correctedAngle); IndexedVector3 computedNormalB = MathUtil.QuatRotate(orn, normalA); if (IndexedVector3.Dot(computedNormalB, normalB) < 0) { info.m_flags |= TriangleInfoMap.TRI_INFO_V1V2_SWAP_NORMALB; computedNormalB *= -1; } #if DEBUG_INTERNAL_EDGE if ((computedNormalB - normalB).Length() > 0.0001) { System.Console.WriteLine("warning: normals not identical"); } #endif //DEBUG_INTERNAL_EDGE info.m_edgeV1V2Angle = -correctedAngle; if (isConvex) { info.m_flags |= TriangleInfoMap.TRI_INFO_V1V2_CONVEX; } break; } } break; } default: { // printf("warning: duplicate triangle\n"); break; } } }
public void SerializationBinary() { var a = new TriangleShape(new Vector3F(1, 2, 3), new Vector3F(4, 5, 6), new Vector3F(7, 8, 9)); // Serialize object. var stream = new MemoryStream(); var formatter = new BinaryFormatter(); formatter.Serialize(stream, a); // Deserialize object. stream.Position = 0; var deserializer = new BinaryFormatter(); var b = (TriangleShape)deserializer.Deserialize(stream); Assert.AreEqual(a.Vertex0, b.Vertex0); Assert.AreEqual(a.Vertex1, b.Vertex1); Assert.AreEqual(a.Vertex2, b.Vertex2); }
public void SerializationXml() { var a = new TriangleShape(new Vector3F(1, 2, 3), new Vector3F(4, 5, 6), new Vector3F(7, 8, 9)); // Serialize object. var stream = new MemoryStream(); var serializer = new XmlSerializer(typeof(Shape)); serializer.Serialize(stream, a); // Output generated xml. Can be manually checked in output window. stream.Position = 0; var xml = new StreamReader(stream).ReadToEnd(); Trace.WriteLine("Serialized Object:\n" + xml); // Deserialize object. stream.Position = 0; var deserializer = new XmlSerializer(typeof(Shape)); var b = (TriangleShape)deserializer.Deserialize(stream); Assert.AreEqual(a.Vertex0, b.Vertex0); Assert.AreEqual(a.Vertex1, b.Vertex1); Assert.AreEqual(a.Vertex2, b.Vertex2); }
public void TestIndexer() { TriangleShape t = new TriangleShape(); Assert.AreEqual(new Vector3F(), t[0]); Assert.AreEqual(new Vector3F(), t[1]); Assert.AreEqual(new Vector3F(), t[2]); t[0] = new Vector3F(1, 2, 3); Assert.AreEqual(new Vector3F(1, 2, 3), t[0]); Assert.AreEqual(new Vector3F(), t[1]); Assert.AreEqual(new Vector3F(), t[2]); t[1] = new Vector3F(4, 5, 6); Assert.AreEqual(new Vector3F(1, 2, 3), t[0]); Assert.AreEqual(new Vector3F(4, 5, 6), t[1]); Assert.AreEqual(new Vector3F(), t[2]); t[2] = new Vector3F(7, 8, 9); Assert.AreEqual(new Vector3F(1, 2, 3), t[0]); Assert.AreEqual(new Vector3F(4, 5, 6), t[1]); Assert.AreEqual(new Vector3F(7, 8, 9), t[2]); Assert.AreEqual(t.Vertex0, t[0]); Assert.AreEqual(t.Vertex1, t[1]); Assert.AreEqual(t.Vertex2, t[2]); }
public void TestProperties() { TriangleShape t = new TriangleShape(); Assert.AreEqual(new Vector3F(), t.Vertex0); Assert.AreEqual(new Vector3F(), t.Vertex1); Assert.AreEqual(new Vector3F(), t.Vertex2); t.Vertex0 = new Vector3F(1, 2, 3); Assert.AreEqual(new Vector3F(1, 2, 3), t.Vertex0); Assert.AreEqual(new Vector3F(), t.Vertex1); Assert.AreEqual(new Vector3F(), t.Vertex2); t.Vertex1 = new Vector3F(4, 5, 6); Assert.AreEqual(new Vector3F(1, 2, 3), t.Vertex0); Assert.AreEqual(new Vector3F(4, 5, 6), t.Vertex1); Assert.AreEqual(new Vector3F(), t.Vertex2); t.Vertex2 = new Vector3F(9, 7, 8); Assert.AreEqual(new Vector3F(1, 2, 3), t.Vertex0); Assert.AreEqual(new Vector3F(4, 5, 6), t.Vertex1); Assert.AreEqual(new Vector3F(9, 7, 8), t.Vertex2); Assert.IsTrue(Vector3F.AreNumericallyEqual(Vector3F.Cross(new Vector3F(3, 3, 3), new Vector3F(8, 5, 5)).Normalized, t.Normal)); // Degenerate triangles can have any normal. Assert.IsTrue(Numeric.AreEqual(1, new TriangleShape().Normal.Length)); }
public void TestIndexerException3() { Vector3F v = new TriangleShape()[-1]; }