protected override bool ConfigureTriangle(int i, out TriangleIndices indices) { MeshBoundingBoxTreeData data = mesh.Shape.TriangleMesh.Data; int triangleIndex = overlappedTriangles.Elements[i]; data.GetTriangle(triangleIndex, out localTriangleShape.vA, out localTriangleShape.vB, out localTriangleShape.vC); AffineTransform.Transform(ref localTriangleShape.vA, ref mesh.worldTransform, out localTriangleShape.vA); AffineTransform.Transform(ref localTriangleShape.vB, ref mesh.worldTransform, out localTriangleShape.vB); AffineTransform.Transform(ref localTriangleShape.vC, ref mesh.worldTransform, out localTriangleShape.vC); //In instanced meshes, the bounding box we found in local space could collect more triangles than strictly necessary. //By doing a second pass, we should be able to prune out quite a few of them. BoundingBox triangleAABB; Toolbox.GetTriangleBoundingBox(ref localTriangleShape.vA, ref localTriangleShape.vB, ref localTriangleShape.vC, out triangleAABB); bool toReturn; triangleAABB.Intersects(ref convex.boundingBox, out toReturn); if (!toReturn) { indices = new TriangleIndices(); return false; } 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; }
protected override bool ConfigureTriangle(int i, out TriangleIndices indices) { indices = overlappedTriangles.Elements[i]; terrain.Shape.GetTriangle(ref indices, ref terrain.worldTransform, out localTriangleShape.vA, out localTriangleShape.vB, out localTriangleShape.vC); localTriangleShape.collisionMargin = 0; //Calibrate the sidedness of the triangle such that it's always facing up. //TODO: There's quite a bit of redundancy in here with other systems. Vector3 AB, AC, normal; Vector3.Subtract(ref localTriangleShape.vB, ref localTriangleShape.vA, out AB); Vector3.Subtract(ref localTriangleShape.vC, ref localTriangleShape.vA, out AC); Vector3.Cross(ref AB, ref AC, out normal); Vector3 terrainUp = new Vector3(terrain.worldTransform.LinearTransform.M21, terrain.worldTransform.LinearTransform.M22, terrain.worldTransform.LinearTransform.M23); float dot; Vector3.Dot(ref terrainUp, ref normal, out dot); if (dot > 0) { localTriangleShape.sidedness = TriangleSidedness.Clockwise; } else { localTriangleShape.sidedness = TriangleSidedness.Counterclockwise; } //Unlike other 'instanced' geometries, terrains are almost always axis aligned in some way and/or have low triangle density relative to what they are colliding with. //Instead of performing additional tests, just assume that it's a fairly regular situation. return true; }
protected override bool ConfigureTriangle(int i, out TriangleIndices indices) { int triangleIndex = overlappedTriangles.Elements[i]; mesh.Mesh.Data.GetTriangle(triangleIndex, out localTriangleShape.vA, out localTriangleShape.vB, out localTriangleShape.vC); localTriangleShape.sidedness = mesh.sidedness; localTriangleShape.collisionMargin = 0; indices = new TriangleIndices(); indices.A = mesh.Mesh.Data.indices[triangleIndex]; indices.B = mesh.Mesh.Data.indices[triangleIndex + 1]; indices.C = mesh.Mesh.Data.indices[triangleIndex + 2]; return true; }
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; }
protected override bool ConfigureLocalTriangle(int i, TriangleShape localTriangleShape, out TriangleIndices indices) { TerrainVertexIndices a, b, c; terrain.Shape.GetLocalIndices(overlappedTriangles[i], out a, out b, out c); int terrainWidth = terrain.Shape.Heights.GetLength(0); indices.A = a.ToSequentialIndex(terrainWidth); indices.B = b.ToSequentialIndex(terrainWidth); indices.C = c.ToSequentialIndex(terrainWidth); terrain.Shape.GetLocalPosition(a.ColumnIndex, a.RowIndex, out localTriangleShape.vA); terrain.Shape.GetLocalPosition(b.ColumnIndex, b.RowIndex, out localTriangleShape.vB); terrain.Shape.GetLocalPosition(c.ColumnIndex, c.RowIndex, out localTriangleShape.vC); localTriangleShape.collisionMargin = 0; localTriangleShape.sidedness = terrain.sidedness; //Unlike other 'instanced' geometries, terrains are almost always axis aligned in some way and/or have low triangle density relative to what they are colliding with. //Instead of performing additional tests, just assume that it's a fairly regular situation. return true; }
protected override bool ConfigureLocalTriangle(int i, TriangleShape localTriangleShape, out TriangleIndices indices) { MeshBoundingBoxTreeData data = mesh.Shape.TriangleMesh.Data; int triangleIndex = overlappedTriangles.Elements[i]; localTriangleShape.sidedness = mesh.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; }
protected override bool ConfigureLocalTriangle(int i, TriangleShape localTriangleShape, out TriangleIndices indices) { var data = mesh.Shape.TriangleMesh.Data; int triangleIndex = overlappedTriangles.Elements[i]; TriangleSidedness sidedness; 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; }
private void SetTriangleEdgePointers(TriangleIndices tri) { // Remove the reference to this triangle from all edges foreach (var edge in tri.edges) { edge.triangles.RemoveAll(t => t == tri); } // Then rebuild the edges tri.edges.Clear(); tri.edges.Add(AddEdge(tri.a, tri.b)); tri.edges.Add(AddEdge(tri.b, tri.c)); tri.edges.Add(AddEdge(tri.c, tri.a)); tri.edges[0].triangles.Add(tri); tri.edges[1].triangles.Add(tri); tri.edges[2].triangles.Add(tri); }
/// <summary> /// Add a new triangle with vertices a, b, and c. /// Vertices must be specified in counter-clockwise order when viewed from front. /// </summary> /// <param name="a"></param> /// <param name="b"></param> /// <param name="c"></param> public void AddTriangle(Vector3 a, Vector3 b, Vector3 c) { var newTriangle = new TriangleIndices() { a = AddVertex(a), b = AddVertex(b), c = AddVertex(c) }; if (newTriangle.a != newTriangle.b && newTriangle.b != newTriangle.c && newTriangle.c != newTriangle.a) { triangles.Add(newTriangle); var triangle = triangles[triangles.Count - 1]; SetTriangleEdgePointers(triangle); } else { // Bad triangle = has colinear edges. } }
/// <summary> /// Get all connected triangles that satisfy a certain criteria /// </summary> /// <returns></returns> public TriangleIndices[] GetConnectedTriangles(TriangleIndices triangleIndices, List<TriangleIndices> ignoreIndices, Func<Triangle, bool> dotCriteria) { List<TriangleIndices> connected = new List<TriangleIndices>(); connected.Add(triangleIndices); //ignoreIndices.Add(triangleIndices); foreach (var edge in triangleIndices.edges) { foreach (var otherindex in edge.triangles) { if (ignoreIndices.Contains(otherindex) || connected.Contains(otherindex)) { // Don't need to look at this one } else { var triangle = new Triangle(vertices[otherindex.a], vertices[otherindex.b], vertices[otherindex.c]); var dot = Vector3.Dot(triangle.Plane.Normal, Vector3.UnitZ); if (dotCriteria(triangle)) { // Satisfies criteria, keep the triangle List<TriangleIndices> newIgnore = new List<TriangleIndices>(); newIgnore.AddRange(ignoreIndices); newIgnore.AddRange(connected); var moreconnected = GetConnectedTriangles(otherindex, newIgnore, dotCriteria); //ignoreIndices.AddRange(moreconnected); connected.AddRange(moreconnected); } } } } return connected.ToArray(); }
public List<TriangleIndices> GetConnected(ref List<TriangleIndices> tempTriangles, TriangleIndices first) { List<TriangleIndices> connected = new List<TriangleIndices>(); connected.Add(first); tempTriangles.Remove(first); foreach (var edge in first.edges) { foreach (var tri in edge.triangles) { if (tempTriangles.Contains(tri)) { connected.AddRange(GetConnected(ref tempTriangles, tri)); } } } return connected; }
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]]; //TODO: Note the IsQuery hack to avoid missing contacts. Avoid doing this in v2. localTriangleShape.sidedness = IsQuery ? TriangleSidedness.DoubleSided : mesh.sidedness; localTriangleShape.collisionMargin = 0; indices = new TriangleIndices { A = data.indices[triangleIndex], B = data.indices[triangleIndex + 1], C = data.indices[triangleIndex + 2] }; return(true); }
protected override bool ConfigureTriangle(int i, out TriangleIndices indices) { MeshBoundingBoxTreeData data = mesh.Shape.TriangleMesh.Data; int triangleIndex = overlappedTriangles.Elements[i]; data.GetTriangle(triangleIndex, out localTriangleShape.vA, out localTriangleShape.vB, out localTriangleShape.vC); AffineTransform transform; AffineTransform.CreateFromRigidTransform(ref mesh.worldTransform, out transform); AffineTransform.Transform(ref localTriangleShape.vA, ref transform, out localTriangleShape.vA); AffineTransform.Transform(ref localTriangleShape.vB, ref transform, out localTriangleShape.vB); AffineTransform.Transform(ref localTriangleShape.vC, ref transform, out localTriangleShape.vC); //In instanced meshes, the bounding box we found in local space could collect more triangles than strictly necessary. //By doing a second pass, we should be able to prune out quite a few of them. BoundingBox triangleAABB; Toolbox.GetTriangleBoundingBox(ref localTriangleShape.vA, ref localTriangleShape.vB, ref localTriangleShape.vC, out triangleAABB); bool toReturn; triangleAABB.Intersects(ref convex.boundingBox, out toReturn); if (!toReturn) { indices = new TriangleIndices(); return false; } TriangleSidedness sidedness; 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] }; return true; }
//Generate+scale public void Generate(List <double> parameterList, float scale) { Object3DGenerate(parameterList); if (parameterList == null) { return; } if (parameterList.Count < 1) { return; } numberOfLongitudePoints = (int)Math.Round(parameterList[0]); double deltaU = 1 / (double)numberOfLongitudePoints; List <List <List <double> > > pointList = new List <List <List <double> > >(); for (int iZ = 0; iZ < horizontalBezierCurveList.Count; iZ++) { List <List <double> > slicePointList = new List <List <double> >(); BezierCurve horizontalBezierCurve = horizontalBezierCurveList[iZ]; double z = horizontalBezierCurve.SplineList[0].ControlPointList[0].CoordinateList[2] * scale; for (int iLongitude = 0; iLongitude < numberOfLongitudePoints; iLongitude++) { double uGlobal = iLongitude * deltaU; if (iZ % 2 == 0) { uGlobal += deltaU / 2; } // Shift points in every other layer PointND point = horizontalBezierCurve.GetPoint(uGlobal); double x = point.CoordinateList[0] * scale; double y = point.CoordinateList[1] * scale; slicePointList.Add(new List <double>() { x, y, z }); Vertex3D vertex = new Vertex3D(x, y, z); vertexList.Add(vertex); } pointList.Add(slicePointList); } for (int iZ = 1; iZ < horizontalBezierCurveList.Count; iZ++) { int iSumPrevious = (iZ - 1) * numberOfLongitudePoints; int iSum = iZ * numberOfLongitudePoints; for (int iPhi = 0; iPhi < numberOfLongitudePoints; iPhi++) { if (iZ % 2 == 0) { int i1 = iSumPrevious + iPhi; int i3 = iSum + iPhi; int i2 = iSumPrevious + iPhi + 1; if ((iPhi + 1) >= numberOfLongitudePoints) { i2 -= numberOfLongitudePoints; } TriangleIndices triangleIndices1 = new TriangleIndices(i1, i2, i3); triangleIndicesList.Add(triangleIndices1); i1 = iSum + iPhi; i3 = iSum + iPhi + 1; i2 = iSumPrevious + iPhi + 1; if ((iPhi + 1) >= numberOfLongitudePoints) { i2 -= numberOfLongitudePoints; i3 -= numberOfLongitudePoints; } TriangleIndices triangleIndices2 = new TriangleIndices(i1, i2, i3); triangleIndicesList.Add(triangleIndices2); } else { int i1 = iSumPrevious + iPhi; int i3 = iSum + iPhi + 1; int i2 = iSumPrevious + iPhi + 1; if ((iPhi + 1) >= numberOfLongitudePoints) { i2 -= numberOfLongitudePoints; i3 -= numberOfLongitudePoints; } TriangleIndices triangleIndices1 = new TriangleIndices(i1, i2, i3); triangleIndicesList.Add(triangleIndices1); i1 = iSum + iPhi; i3 = iSum + iPhi + 1; i2 = iSumPrevious + iPhi; if ((iPhi + 1) >= numberOfLongitudePoints) { i3 -= numberOfLongitudePoints; } TriangleIndices triangleIndices2 = new TriangleIndices(i1, i2, i3); triangleIndicesList.Add(triangleIndices2); } } } GenerateTriangleConnectionLists(); ComputeTriangleNormalVectors(); ComputeVertexNormalVectors(); }