public override void DebugDrawInvalidTriangles() { if (this.Entity != null) { using (List <MyHierarchyComponentBase> .Enumerator enumerator = this.Entity.Hierarchy.Children.GetEnumerator()) { while (enumerator.MoveNext()) { enumerator.Current.Container.Entity.DebugDrawInvalidTriangles(); } } if (this.Entity.Render.GetModel() != null) { int trianglesCount = this.Entity.Render.GetModel().GetTrianglesCount(); for (int i = 0; i < trianglesCount; i++) { MyTriangleVertexIndices triangle = this.Entity.Render.GetModel().GetTriangle(i); if (MyUtils.IsWrongTriangle(this.Entity.Render.GetModel().GetVertex(triangle.I0), this.Entity.Render.GetModel().GetVertex(triangle.I1), this.Entity.Render.GetModel().GetVertex(triangle.I2))) { Vector3 pointFrom = (Vector3)Vector3.Transform(this.Entity.Render.GetModel().GetVertex(triangle.I0), this.Entity.PositionComp.WorldMatrix); Vector3 pointTo = (Vector3)Vector3.Transform(this.Entity.Render.GetModel().GetVertex(triangle.I1), this.Entity.PositionComp.WorldMatrix); Vector3 vector3 = (Vector3)Vector3.Transform(this.Entity.Render.GetModel().GetVertex(triangle.I2), this.Entity.PositionComp.WorldMatrix); MyRenderProxy.DebugDrawLine3D(pointFrom, pointTo, Color.Purple, Color.Purple, false, false); MyRenderProxy.DebugDrawLine3D(pointTo, vector3, Color.Purple, Color.Purple, false, false); MyRenderProxy.DebugDrawLine3D(vector3, pointFrom, Color.Purple, Color.Purple, false, false); Vector3 vector4 = ((pointFrom + pointTo) + vector3) / 3f; MyRenderProxy.DebugDrawLine3D(vector4, vector4 + Vector3.UnitX, Color.Yellow, Color.Yellow, false, false); MyRenderProxy.DebugDrawLine3D(vector4, vector4 + Vector3.UnitY, Color.Yellow, Color.Yellow, false, false); MyRenderProxy.DebugDrawLine3D(vector4, vector4 + Vector3.UnitZ, Color.Yellow, Color.Yellow, false, false); } } } } }
private float?ProcessTriangle(int triangleIndex) { System.Diagnostics.Debug.Assert((int)m_flags != 0); MyTriangle_Vertexes triangle; MyTriangleVertexIndices triangleIndices = m_model.Triangles[triangleIndex]; m_model.GetVertex(triangleIndices.I0, triangleIndices.I2, triangleIndices.I1, out triangle.Vertex0, out triangle.Vertex1, out triangle.Vertex2); Vector3 calculatedTriangleNormal = MyUtils.GetNormalVectorFromTriangle(ref triangle); //We dont want backside intersections if (((int)(m_flags & IntersectionFlags.FLIPPED_TRIANGLES) == 0) && Vector3.Dot(m_line.Direction, calculatedTriangleNormal) > 0) { return(null); } float?distance = MyUtils.GetLineTriangleIntersection(ref m_line, ref triangle); // If intersection occured and if distance to intersection is closer to origin than any previous intersection if ((distance != null) && ((result == null) || (distance.Value < result.Value.Distance))) { // We need to remember original triangleVertexes coordinates (not transformed by world matrix) result = new MyIntersectionResultLineTriangle(ref triangle, ref calculatedTriangleNormal, distance.Value); return(distance.Value); } return(null); }
// Return true if object intersects specified sphere. // This method doesn't return exact point of intersection or any additional data. // We don't look for closest intersection - so we stop on first intersection found. // IMPORTANT: Sphere must be in model space, so don't transform it! public bool GetIntersectionWithSphere(MyModel model, ref BoundingSphere sphere) { // Check if sphere intersects bounding box of this node if (MyUtils.IsBoxIntersectingSphere(ref m_boundingBox, ref sphere) == false) { return(false); } // temporary variable for storing tirngle boundingbox info BoundingBox triangleBoundingBox = new BoundingBox(); // Triangles that are directly in this node for (int i = 0; i < m_triangleIndices.Count; i++) { int triangleIndex = m_triangleIndices[i]; model.GetTriangleBoundingBox(triangleIndex, ref triangleBoundingBox); // First test intersection of triangleVertexes's bounding box with bounding sphere. And only if they overlap or intersect, do further intersection tests. if (MyUtils.IsBoxIntersectingSphere(triangleBoundingBox, ref sphere) == true) { // See that we swaped vertex indices!! MyTriangle_Vertexes triangle; MyTriangleVertexIndices triangleIndices = model.Triangles[triangleIndex]; triangle.Vertex0 = model.GetVertex(triangleIndices.I0); triangle.Vertex1 = model.GetVertex(triangleIndices.I2); triangle.Vertex2 = model.GetVertex(triangleIndices.I1); MyPlane trianglePlane = new MyPlane(ref triangle); if (MyUtils.GetSphereTriangleIntersection(ref sphere, ref trianglePlane, ref triangle) != null) { // If we found intersection we can stop and dont need to look further return(true); } } } // Get intersection with childs of this node if (m_childs != null) { for (int i = 0; i < m_childs.Count; i++) { if (m_childs[i].GetIntersectionWithSphere(model, ref sphere)) { return(true); } } } return(false); }
public void GetTrianglesIntersectingAABB(ref BoundingBox aabb, List <MyTriangle_Vertex_Normal> retTriangles, int maxNeighbourTriangles) { IndexedVector3 min = new IndexedVector3(ref aabb.Min); IndexedVector3 max = new IndexedVector3(ref aabb.Max); AABB gi_aabb = new AABB(ref min, ref max); m_overlappedTriangles.Clear(); MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartProfilingBlock("m_bvh.BoxQuery"); bool res = m_bvh.BoxQuery(ref gi_aabb, m_overlappedTriangles); MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().EndProfilingBlock(); if (res) { MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartProfilingBlock("m_overlappedTriangles"); //foreach (var triangleIndex in m_overlappedTriangles) for (int i = 0; i < m_overlappedTriangles.Count; i++) { var triangleIndex = m_overlappedTriangles[i]; // If we reached end of the buffer of neighbour triangles, we stop adding new ones. This is better behavior than throwing exception because of array overflow. if (retTriangles.Count == maxNeighbourTriangles) { MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().EndProfilingBlock(); return; } MyTriangleVertexIndices triangle = m_model.Triangles[triangleIndex]; MyTriangle_Vertexes triangleVertices = new MyTriangle_Vertexes(); m_model.GetVertex(triangle.I0, triangle.I1, triangle.I2, out triangleVertices.Vertex0, out triangleVertices.Vertex1, out triangleVertices.Vertex2); IndexedVector3 iv0 = new IndexedVector3(ref triangleVertices.Vertex0); IndexedVector3 iv1 = new IndexedVector3(ref triangleVertices.Vertex1); IndexedVector3 iv2 = new IndexedVector3(ref triangleVertices.Vertex2); MyTriangle_Vertex_Normal retTriangle; retTriangle.Vertexes = triangleVertices; retTriangle.Normal = Vector3.Forward; retTriangles.Add(retTriangle); } MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().EndProfilingBlock(); } }
public bool GetIntersectionWithSphere(MyEntity physObject, ref BoundingSphere sphere) { // Transform sphere from world space to object space Matrix worldInv = physObject.GetWorldMatrixInverted(); Vector3 positionInObjectSpace = MyUtils.GetTransform(sphere.Center, ref worldInv); BoundingSphere sphereInObjectSpace = new BoundingSphere(positionInObjectSpace, sphere.Radius); var aabb = BoundingBoxHelper.InitialBox; BoundingBoxHelper.AddSphere(ref sphereInObjectSpace, ref aabb); AABB gi_aabb = new AABB(ref aabb.Min, ref aabb.Max); m_overlappedTriangles.Clear(); if (m_bvh.BoxQuery(ref gi_aabb, m_overlappedTriangles)) { // temporary variable for storing tirngle boundingbox info BoundingBox triangleBoundingBox = new BoundingBox(); // Triangles that are directly in this node for (int i = 0; i < m_overlappedTriangles.Count; i++) { var triangleIndex = m_overlappedTriangles[i]; m_model.GetTriangleBoundingBox(triangleIndex, ref triangleBoundingBox); // First test intersection of triangleVertexes's bounding box with bounding sphere. And only if they overlap or intersect, do further intersection tests. if (MyUtils.IsBoxIntersectingSphere(triangleBoundingBox, ref sphereInObjectSpace) == true) { // See that we swaped vertex indices!! MyTriangle_Vertexes triangle; MyTriangleVertexIndices triangleIndices = m_model.Triangles[triangleIndex]; triangle.Vertex0 = m_model.GetVertex(triangleIndices.I0); triangle.Vertex1 = m_model.GetVertex(triangleIndices.I2); triangle.Vertex2 = m_model.GetVertex(triangleIndices.I1); MyPlane trianglePlane = new MyPlane(ref triangle); if (MyUtils.GetSphereTriangleIntersection(ref sphereInObjectSpace, ref trianglePlane, ref triangle) != null) { // If we found intersection we can stop and dont need to look further return(true); } } } } return(false); }
public override void DebugDrawInvalidTriangles() { base.DebugDrawInvalidTriangles(); foreach (KeyValuePair <Vector3I, MyCubeGridRenderCell> pair in this.m_cubeGrid.Render.RenderData.Cells) { IEnumerator <KeyValuePair <MyCubePart, ConcurrentDictionary <uint, bool> > > enumerator = pair.Value.CubeParts.GetEnumerator(); try { while (enumerator.MoveNext()) { KeyValuePair <MyCubePart, ConcurrentDictionary <uint, bool> > current = enumerator.Current; MyModel model = current.Key.Model; if (model != null) { int trianglesCount = model.GetTrianglesCount(); for (int i = 0; i < trianglesCount; i++) { MyTriangleVertexIndices triangle = model.GetTriangle(i); if (MyUtils.IsWrongTriangle(model.GetVertex(triangle.I0), model.GetVertex(triangle.I1), model.GetVertex(triangle.I2))) { Vector3 pointFrom = Vector3.Transform(model.GetVertex(triangle.I0), (Matrix)this.m_cubeGrid.PositionComp.WorldMatrix); Vector3 pointTo = Vector3.Transform(model.GetVertex(triangle.I1), (Matrix)this.m_cubeGrid.PositionComp.WorldMatrix); Vector3 vector3 = Vector3.Transform(model.GetVertex(triangle.I2), (Matrix)this.m_cubeGrid.PositionComp.WorldMatrix); MyRenderProxy.DebugDrawLine3D(pointFrom, pointTo, Color.Purple, Color.Purple, false, false); MyRenderProxy.DebugDrawLine3D(pointTo, vector3, Color.Purple, Color.Purple, false, false); MyRenderProxy.DebugDrawLine3D(vector3, pointFrom, Color.Purple, Color.Purple, false, false); Vector3 vector4 = ((pointFrom + pointTo) + vector3) / 3f; MyRenderProxy.DebugDrawLine3D(vector4, vector4 + Vector3.UnitX, Color.Yellow, Color.Yellow, false, false); MyRenderProxy.DebugDrawLine3D(vector4, vector4 + Vector3.UnitY, Color.Yellow, Color.Yellow, false, false); MyRenderProxy.DebugDrawLine3D(vector4, vector4 + Vector3.UnitZ, Color.Yellow, Color.Yellow, false, false); } } } } } finally { if (enumerator == null) { continue; } enumerator.Dispose(); } } }
public bool GetIntersectionWithSphere(MyModel model, ref BoundingSphere sphere) { if (this.m_boundingBox.Intersects(ref sphere)) { BoundingBox boundingBox = new BoundingBox(); for (int i = 0; i < this.m_triangleIndices.Count; i++) { int triangleIndex = this.m_triangleIndices[i]; model.GetTriangleBoundingBox(triangleIndex, ref boundingBox); if (boundingBox.Intersects(ref sphere)) { MyTriangle_Vertices vertices; MyTriangleVertexIndices indices = model.Triangles[triangleIndex]; vertices.Vertex0 = model.GetVertex(indices.I0); vertices.Vertex1 = model.GetVertex(indices.I2); vertices.Vertex2 = model.GetVertex(indices.I1); Plane trianglePlane = new Plane(vertices.Vertex0, vertices.Vertex1, vertices.Vertex2); if (MyUtils.GetSphereTriangleIntersection(ref sphere, ref trianglePlane, ref vertices) != null) { return(true); } } } if (this.m_childs != null) { for (int j = 0; j < this.m_childs.Count; j++) { if (this.m_childs[j].GetIntersectionWithSphere(model, ref sphere)) { return(true); } } } } return(false); }
public void GetTrianglesIntersectingSphere(MyModel model, ref BoundingSphere sphere, Vector3?referenceNormalVector, float?maxAngle, List <MyTriangle_Vertex_Normals> retTriangles, int maxNeighbourTriangles) { // Check if sphere intersects bounding box of this node //if (m_boundingBox.Contains(sphere) == ContainmentType.Disjoint) return; if (MyUtils.IsBoxIntersectingSphere(ref m_boundingBox, ref sphere) == false) { return; } // temporary variable for storing tirngle boundingbox info BoundingBox triangleBoundingBox = new BoundingBox(); // Triangles that are directly in this node for (int i = 0; i < m_triangleIndices.Count; i++) { // If we reached end of the buffer of neighbour triangles, we stop adding new ones. This is better behavior than throwing exception because of array overflow. if (retTriangles.Count == maxNeighbourTriangles) { return; } int triangleIndex = m_triangleIndices[i]; model.GetTriangleBoundingBox(triangleIndex, ref triangleBoundingBox); // First test intersection of triangleVertexes's bounding box with bounding sphere. And only if they overlap or intersect, do further intersection tests. if (MyUtils.IsBoxIntersectingSphere(triangleBoundingBox, ref sphere) == true) { //if (m_triangleIndices[value] != ignoreTriangleWithIndex) { // See that we swaped vertex indices!! MyTriangle_Vertexes triangle; MyTriangle_Normals triangleNormals; MyTriangle_Normals triangleBinormals; MyTriangle_Normals triangleTangents; MyTriangleVertexIndices triangleIndices = model.Triangles[triangleIndex]; triangle.Vertex0 = model.GetVertex(triangleIndices.I0); triangle.Vertex1 = model.GetVertex(triangleIndices.I2); triangle.Vertex2 = model.GetVertex(triangleIndices.I1); triangleNormals.Normal0 = model.GetVertexNormal(triangleIndices.I0); triangleNormals.Normal1 = model.GetVertexNormal(triangleIndices.I2); triangleNormals.Normal2 = model.GetVertexNormal(triangleIndices.I1); triangleBinormals.Normal0 = model.GetVertexBinormal(triangleIndices.I0); triangleBinormals.Normal1 = model.GetVertexBinormal(triangleIndices.I2); triangleBinormals.Normal2 = model.GetVertexBinormal(triangleIndices.I1); triangleTangents.Normal0 = model.GetVertexTangent(triangleIndices.I0); triangleTangents.Normal1 = model.GetVertexTangent(triangleIndices.I2); triangleTangents.Normal2 = model.GetVertexTangent(triangleIndices.I1); MyPlane trianglePlane = new MyPlane(ref triangle); if (MyUtils.GetSphereTriangleIntersection(ref sphere, ref trianglePlane, ref triangle) != null) { Vector3 triangleNormal = MyUtils.GetNormalVectorFromTriangle(ref triangle); if ((referenceNormalVector.HasValue == false) || (maxAngle.HasValue == false) || ((MyUtils.GetAngleBetweenVectors(referenceNormalVector.Value, triangleNormal) <= maxAngle))) { MyTriangle_Vertex_Normals retTriangle; retTriangle.Vertexes = triangle; retTriangle.Normals = triangleNormals; retTriangle.Binormals = triangleBinormals; retTriangle.Tangents = triangleTangents; retTriangles.Add(retTriangle); } } } } } // Get intersection with childs of this node if (m_childs != null) { for (int i = 0; i < m_childs.Count; i++) { //m_childs[value].GetTrianglesIntersectingSphere(physObject, ref sphere, referenceNormalVector, maxAngle, ignoreTriangleWithIndex, retTriangles, maxNeighbourTriangles); m_childs[i].GetTrianglesIntersectingSphere(model, ref sphere, referenceNormalVector, maxAngle, retTriangles, maxNeighbourTriangles); } } }
// Finds intersection between line and model, using octree for speedup the lookup. // Another speedup is, that first we check triangles that are directly in the node and then start // checking node's childs. But only if child node instersection is less than last know min distance. MyIntersectionResultLineTriangle?GetIntersectionWithLineRecursive(MyModel model, ref MyLine line, float?minDistanceUntilNow) { // Check if line intersects bounding box of this node and if distance to bounding box is less then last know min distance float?distanceToBoundingBox = MyUtils.GetLineBoundingBoxIntersection(ref line, ref m_boundingBox); if ((distanceToBoundingBox.HasValue == false) || ((minDistanceUntilNow != null) && (minDistanceUntilNow < distanceToBoundingBox.Value))) { return(null); } // Triangles that are directly in this node MyIntersectionResultLineTriangle?foundIntersection = null; // temporary variable for storing tirngle boundingbox info BoundingBox triangleBoundingBox = new BoundingBox(); MinerWars.AppCode.Game.Managers.MyPerformanceCounter.PerCameraDraw.RayCastTrianglesProcessed += m_triangleIndices.Count; for (int i = 0; i < m_triangleIndices.Count; i++) { int triangleIndex = m_triangleIndices[i]; model.GetTriangleBoundingBox(triangleIndex, ref triangleBoundingBox); // First test intersection of triangleVertexes's bounding box with line's bounding box. And only if they overlap or intersect, do further intersection tests. if (MyUtils.IsBoxIntersectingBox(triangleBoundingBox, ref line.BoundingBox) == true) { // See that we swaped vertex indices!! MyTriangle_Vertexes triangle; MyTriangleVertexIndices triangleIndices = model.Triangles[triangleIndex]; triangle.Vertex0 = model.GetVertex(triangleIndices.I0); triangle.Vertex1 = model.GetVertex(triangleIndices.I2); triangle.Vertex2 = model.GetVertex(triangleIndices.I1); float?distance = MyUtils.GetLineTriangleIntersection(ref line, ref triangle); // If intersection occured and if distance to intersection is closer to origin than any previous intersection if ((distance != null) && ((foundIntersection == null) || (distance.Value < foundIntersection.Value.Distance))) { Vector3 calculatedTriangleNormal = MyUtils.GetNormalVectorFromTriangle(ref triangle); // We need to remember original triangleVertexes coordinates (not transformed by world matrix) foundIntersection = new MyIntersectionResultLineTriangle(ref triangle, ref calculatedTriangleNormal, distance.Value); } } } // Get intersection with childs of this node if (m_childs != null) { for (int i = 0; i < m_childs.Count; i++) { MyIntersectionResultLineTriangle?childIntersection = m_childs[i].GetIntersectionWithLineRecursive(model, ref line, (foundIntersection == null) ? (float?)null : foundIntersection.Value.Distance); // If intersection occured and if distance to intersection is closer to origin than any previous intersection foundIntersection = MyIntersectionResultLineTriangle.GetCloserIntersection(ref foundIntersection, ref childIntersection); } } return(foundIntersection); }
public void GetTrianglesIntersectingSphere(ref BoundingSphere sphere, List <MyTriangle_Vertex_Normal> retTriangles, int maxNeighbourTriangles) { Vector3?referenceNormalVector = null; float? maxAngle = null; var aabb = BoundingBoxHelper.InitialBox; BoundingBoxHelper.AddSphere(ref sphere, ref aabb); AABB gi_aabb = new AABB(ref aabb.Min, ref aabb.Max); m_overlappedTriangles.Clear(); // MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartProfilingBlock("m_bvh.BoxQuery"); // This code is called recursively and cause profiler to lag bool res = m_bvh.BoxQuery(ref gi_aabb, m_overlappedTriangles); // MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().EndProfilingBlock(); if (res) { //MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartProfilingBlock("m_overlappedTriangles"); // This code is called recursively and cause profiler to lag // temporary variable for storing tirngle boundingbox info BoundingBox triangleBoundingBox = new BoundingBox(); for (int i = 0; i < m_overlappedTriangles.Count; i++) { var triangleIndex = m_overlappedTriangles[i]; // If we reached end of the buffer of neighbour triangles, we stop adding new ones. This is better behavior than throwing exception because of array overflow. if (retTriangles.Count == maxNeighbourTriangles) { return; } m_model.GetTriangleBoundingBox(triangleIndex, ref triangleBoundingBox); //gi_aabb.CollideTriangleExact // First test intersection of triangleVertexes's bounding box with bounding sphere. And only if they overlap or intersect, do further intersection tests. if (MyUtils.IsBoxIntersectingSphere(triangleBoundingBox, ref sphere) == true) { //if (m_triangleIndices[value] != ignoreTriangleWithIndex) { // See that we swaped vertex indices!! MyTriangle_Vertexes triangle; MyTriangleVertexIndices triangleIndices = m_model.Triangles[triangleIndex]; triangle.Vertex0 = m_model.GetVertex(triangleIndices.I0); triangle.Vertex1 = m_model.GetVertex(triangleIndices.I2); triangle.Vertex2 = m_model.GetVertex(triangleIndices.I1); Vector3 calculatedTriangleNormal = MyUtils.GetNormalVectorFromTriangle(ref triangle); MyPlane trianglePlane = new MyPlane(ref triangle); if (MyUtils.GetSphereTriangleIntersection(ref sphere, ref trianglePlane, ref triangle) != null) { Vector3 triangleNormal = MyUtils.GetNormalVectorFromTriangle(ref triangle); if ((referenceNormalVector.HasValue == false) || (maxAngle.HasValue == false) || ((MyUtils.GetAngleBetweenVectors(referenceNormalVector.Value, triangleNormal) <= maxAngle))) { MyTriangle_Vertex_Normal retTriangle; retTriangle.Vertexes = triangle; retTriangle.Normal = calculatedTriangleNormal; retTriangles.Add(retTriangle); } } } } } //MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().EndProfilingBlock(); } }
public void GetTrianglesIntersectingSphere(ref BoundingSphere sphere, Vector3?referenceNormalVector, float?maxAngle, List <MyTriangle_Vertex_Normals> retTriangles, int maxNeighbourTriangles) { var aabb = BoundingBoxHelper.InitialBox; BoundingBoxHelper.AddSphere(ref sphere, ref aabb); AABB gi_aabb = new AABB(ref aabb.Min, ref aabb.Max); m_overlappedTriangles.Clear(); if (m_bvh.BoxQuery(ref gi_aabb, m_overlappedTriangles)) { // temporary variable for storing tirngle boundingbox info BoundingBox triangleBoundingBox = new BoundingBox(); for (int i = 0; i < m_overlappedTriangles.Count; i++) { var triangleIndex = m_overlappedTriangles[i]; // If we reached end of the buffer of neighbour triangles, we stop adding new ones. This is better behavior than throwing exception because of array overflow. if (retTriangles.Count == maxNeighbourTriangles) { return; } m_model.GetTriangleBoundingBox(triangleIndex, ref triangleBoundingBox); // First test intersection of triangleVertexes's bounding box with bounding sphere. And only if they overlap or intersect, do further intersection tests. if (MyUtils.IsBoxIntersectingSphere(triangleBoundingBox, ref sphere) == true) { //if (m_triangleIndices[value] != ignoreTriangleWithIndex) { // See that we swaped vertex indices!! MyTriangle_Vertexes triangle; MyTriangle_Normals triangleNormals; MyTriangle_Normals triangleBinormals; MyTriangle_Normals triangleTangents; MyTriangleVertexIndices triangleIndices = m_model.Triangles[triangleIndex]; m_model.GetVertex(triangleIndices.I0, triangleIndices.I2, triangleIndices.I1, out triangle.Vertex0, out triangle.Vertex1, out triangle.Vertex2); /* * triangle.Vertex0 = m_model.GetVertex(triangleIndices.I0); * triangle.Vertex1 = m_model.GetVertex(triangleIndices.I2); * triangle.Vertex2 = m_model.GetVertex(triangleIndices.I1); */ triangleNormals.Normal0 = m_model.GetVertexNormal(triangleIndices.I0); triangleNormals.Normal1 = m_model.GetVertexNormal(triangleIndices.I2); triangleNormals.Normal2 = m_model.GetVertexNormal(triangleIndices.I1); if (MinerWars.AppCode.Game.Render.MyRenderConstants.RenderQualityProfile.ForwardRender) { triangleBinormals.Normal0 = triangleNormals.Normal0; triangleBinormals.Normal1 = triangleNormals.Normal1; triangleBinormals.Normal2 = triangleNormals.Normal2; triangleTangents.Normal0 = triangleNormals.Normal0; triangleTangents.Normal1 = triangleNormals.Normal1; triangleTangents.Normal2 = triangleNormals.Normal2; } else { triangleBinormals.Normal0 = m_model.GetVertexBinormal(triangleIndices.I0); triangleBinormals.Normal1 = m_model.GetVertexBinormal(triangleIndices.I2); triangleBinormals.Normal2 = m_model.GetVertexBinormal(triangleIndices.I1); triangleTangents.Normal0 = m_model.GetVertexTangent(triangleIndices.I0); triangleTangents.Normal1 = m_model.GetVertexTangent(triangleIndices.I2); triangleTangents.Normal2 = m_model.GetVertexTangent(triangleIndices.I1); } MyPlane trianglePlane = new MyPlane(ref triangle); if (MyUtils.GetSphereTriangleIntersection(ref sphere, ref trianglePlane, ref triangle) != null) { Vector3 triangleNormal = MyUtils.GetNormalVectorFromTriangle(ref triangle); if ((referenceNormalVector.HasValue == false) || (maxAngle.HasValue == false) || ((MyUtils.GetAngleBetweenVectors(referenceNormalVector.Value, triangleNormal) <= maxAngle))) { MyTriangle_Vertex_Normals retTriangle; retTriangle.Vertexes = triangle; retTriangle.Normals = triangleNormals; retTriangle.Binormals = triangleBinormals; retTriangle.Tangents = triangleTangents; retTriangles.Add(retTriangle); } } } } } } }
// Finds intersection between line and model, using octree for speedup the lookup. // Another speedup is, that first we check triangles that are directly in the node and then start // checking node's childs. But only if child node instersection is less than last know min distance. VRage.Game.Models.MyIntersectionResultLineTriangle?GetIntersectionWithLineRecursive(MyModel model, ref LineD line, double?minDistanceUntilNow) { // Check if line intersects bounding box of this node and if distance to bounding box is less then last know min distance Line lineF = (Line)line; double?distanceToBoundingBox = MyUtils.GetLineBoundingBoxIntersection(ref lineF, ref m_boundingBox); if ((distanceToBoundingBox.HasValue == false) || ((minDistanceUntilNow != null) && (minDistanceUntilNow < distanceToBoundingBox.Value))) { return(null); } // Triangles that are directly in this node VRage.Game.Models.MyIntersectionResultLineTriangle?foundIntersection = null; // temporary variable for storing tirngle boundingbox info BoundingBox triangleBoundingBox = new BoundingBox(); BoundingBox lineBB = BoundingBox.CreateInvalid(); lineBB = lineBB.Include(line.From); lineBB = lineBB.Include(line.To); for (int i = 0; i < m_triangleIndices.Count; i++) { int triangleIndex = m_triangleIndices[i]; model.GetTriangleBoundingBox(triangleIndex, ref triangleBoundingBox); // First test intersection of triangleVertexes's bounding box with line's bounding box. And only if they overlap or intersect, do further intersection tests. if (triangleBoundingBox.Intersects(ref lineBB)) { // See that we swaped vertex indices!! MyTriangle_Vertices triangle; MyTriangleVertexIndices triangleIndices = model.Triangles[triangleIndex]; triangle.Vertex0 = model.GetVertex(triangleIndices.I0); triangle.Vertex1 = model.GetVertex(triangleIndices.I2); triangle.Vertex2 = model.GetVertex(triangleIndices.I1); double?distance = MyUtils.GetLineTriangleIntersection(ref lineF, ref triangle); // If intersection occured and if distance to intersection is closer to origin than any previous intersection if ((distance != null) && ((foundIntersection == null) || (distance.Value < foundIntersection.Value.Distance))) { Vector3 calculatedTriangleNormal = MyUtils.GetNormalVectorFromTriangle(ref triangle); // We need to remember original triangleVertexes coordinates (not transformed by world matrix) foundIntersection = new VRage.Game.Models.MyIntersectionResultLineTriangle(ref triangle, ref calculatedTriangleNormal, distance.Value); } } } // Get intersection with childs of this node if (m_childs != null) { for (int i = 0; i < m_childs.Count; i++) { VRage.Game.Models.MyIntersectionResultLineTriangle?childIntersection = m_childs[i].GetIntersectionWithLineRecursive(model, ref line, (foundIntersection == null) ? (double?)null : foundIntersection.Value.Distance); // If intersection occured and if distance to intersection is closer to origin than any previous intersection foundIntersection = VRage.Game.Models.MyIntersectionResultLineTriangle.GetCloserIntersection(ref foundIntersection, ref childIntersection); } } return(foundIntersection); }
/// <summary> /// Debug draw of this physics object. /// </summary> public void DebugDraw() { const float alpha = 0.3f; if (!Enabled) { return; } foreach (var primitive in this.rigidBody.GetRBElementList()) { MyRBElementType type = primitive.GetElementType(); switch (type) { case MyRBElementType.ET_BOX: { var box = (MyRBBoxElement)primitive; MyDebugDraw.DrawHiresBoxWireframe( Matrix.CreateScale(box.Size) * box.GetGlobalTransformation(), Color.Green.ToVector3(), alpha); } break; case MyRBElementType.ET_SPHERE: { var sphere = (MyRBSphereElement)primitive; MyDebugDraw.DrawSphereWireframe( Matrix.CreateScale(sphere.Radius) * sphere.GetGlobalTransformation(), Color.Green.ToVector3(), alpha); } break; case MyRBElementType.ET_TRIANGLEMESH: { var triMesh = (MyRBTriangleMeshElement)primitive; var model = triMesh.Model; Matrix transformMatrix = this.rigidBody.Matrix; MyDebugDrawCachedLines.Clear(); // This is just a reserve const int numberOfAddTrianglesInLoop = 3; int triangleIndex = 0; while (true) { //bool finished = triangleIndex >= mesh.GetNumTriangles(); bool finished = triangleIndex >= model.GetTrianglesCount(); if ((MyDebugDrawCachedLines.IsFull(-numberOfAddTrianglesInLoop)) || (finished)) { MyDebugDrawCachedLines.DrawLines(); MyDebugDrawCachedLines.Clear(); } if (finished) { break; } MyTriangleVertexIndices triangle = model.Triangles[triangleIndex]; // We now transform the triangleVertexes into world space (we could keep leave the mesh alone // but at this point 3 vector transforms is probably not a major slow down) Vector3 triVec0 = model.GetVertex(triangle.I0); Vector3 triVec1 = model.GetVertex(triangle.I2); Vector3 triVec2 = model.GetVertex(triangle.I1); // Move triangle into world space Vector3.Transform(ref triVec0, ref transformMatrix, out triVec0); Vector3.Transform(ref triVec1, ref transformMatrix, out triVec1); Vector3.Transform(ref triVec2, ref transformMatrix, out triVec2); MyDebugDrawCachedLines.AddLine(triVec0, triVec1, Color.Green, Color.Green); MyDebugDrawCachedLines.AddLine(triVec1, triVec2, Color.Green, Color.Green); MyDebugDrawCachedLines.AddLine(triVec2, triVec0, Color.Green, Color.Green); /* * MyTriangle_Vertexes tv = new MyTriangle_Vertexes(); * tv.Vertex0 = triVec0; * tv.Vertex1 = triVec1; * tv.Vertex2 = triVec2; * Vector3 calculatedTriangleNormal = MyUtils.GetNormalVectorFromTriangle(ref tv); * Vector3 center = (triVec0 + triVec1 + triVec2)/3.0f; * MyDebugDrawCachedLines.AddLine(center, center + calculatedTriangleNormal * 5, Color.Red, Color.Red); */ //MyDebugDraw.AddDrawTriangle(triVec0, triVec1, triVec2, new Color(0,0.8f, 0, 0.1f)); triangleIndex++; } } break; } } }
public void GetTrianglesIntersectingSphere(MyModel model, ref BoundingSphereD sphere, Vector3?referenceNormalVector, float?maxAngle, List <MyTriangle_Vertex_Normal> retTriangles, int maxNeighbourTriangles) { BoundingSphere sphere2 = (BoundingSphere)sphere; if (this.m_boundingBox.Intersects(ref sphere)) { BoundingBox boundingBox = new BoundingBox(); int num = 0; while (true) { while (true) { if (num >= this.m_triangleIndices.Count) { if (this.m_childs != null) { for (int i = 0; i < this.m_childs.Count; i++) { this.m_childs[i].GetTrianglesIntersectingSphere(model, ref sphere, referenceNormalVector, maxAngle, retTriangles, maxNeighbourTriangles); } } return; } if (retTriangles.Count == maxNeighbourTriangles) { return; } int triangleIndex = this.m_triangleIndices[num]; model.GetTriangleBoundingBox(triangleIndex, ref boundingBox); if (boundingBox.Intersects(ref sphere)) { MyTriangle_Vertices vertices; MyTriangleVertexIndices indices = model.Triangles[triangleIndex]; vertices.Vertex0 = model.GetVertex(indices.I0); vertices.Vertex1 = model.GetVertex(indices.I2); vertices.Vertex2 = model.GetVertex(indices.I1); Vector3 normalVectorFromTriangle = MyUtils.GetNormalVectorFromTriangle(ref vertices); Plane trianglePlane = new Plane(vertices.Vertex0, vertices.Vertex1, vertices.Vertex2); if (MyUtils.GetSphereTriangleIntersection(ref sphere2, ref trianglePlane, ref vertices) != null) { MyTriangle_Vertex_Normal normal; Vector3 vectorB = MyUtils.GetNormalVectorFromTriangle(ref vertices); if ((referenceNormalVector != null) && (maxAngle != null)) { float?nullable2 = maxAngle; if (!((MyUtils.GetAngleBetweenVectors(referenceNormalVector.Value, vectorB) <= nullable2.GetValueOrDefault()) & (nullable2 != null))) { break; } } normal.Vertexes = vertices; normal.Normal = normalVectorFromTriangle; retTriangles.Add(normal); } } break; } num++; } } }
private MyIntersectionResultLineTriangle?GetIntersectionWithLineRecursive(MyModel model, ref Line line, double?minDistanceUntilNow) { double?nullable4; double?nullable1; float? lineBoundingBoxIntersection = MyUtils.GetLineBoundingBoxIntersection(ref line, ref this.m_boundingBox); if (lineBoundingBoxIntersection != null) { nullable1 = new double?((double)lineBoundingBoxIntersection.GetValueOrDefault()); } else { nullable4 = null; nullable1 = nullable4; } double?nullable = nullable1; if (nullable != null) { if (minDistanceUntilNow != null) { nullable4 = minDistanceUntilNow; double num = nullable.Value; if ((nullable4.GetValueOrDefault() < num) & (nullable4 != null)) { goto TR_0000; } } MyIntersectionResultLineTriangle?a = null; BoundingBox boundingBox = new BoundingBox(); BoundingBox box = BoundingBox.CreateInvalid().Include(line.From).Include(line.To); for (int i = 0; i < this.m_triangleIndices.Count; i++) { int triangleIndex = this.m_triangleIndices[i]; model.GetTriangleBoundingBox(triangleIndex, ref boundingBox); if (boundingBox.Intersects(ref box)) { MyTriangle_Vertices vertices; MyTriangleVertexIndices indices = model.Triangles[triangleIndex]; vertices.Vertex0 = model.GetVertex(indices.I0); vertices.Vertex1 = model.GetVertex(indices.I2); vertices.Vertex2 = model.GetVertex(indices.I1); float?lineTriangleIntersection = MyUtils.GetLineTriangleIntersection(ref line, ref vertices); if ((lineTriangleIntersection != null) && ((a == null) || (lineTriangleIntersection.Value < a.Value.Distance))) { Vector3 normalVectorFromTriangle = MyUtils.GetNormalVectorFromTriangle(ref vertices); a = new MyIntersectionResultLineTriangle(triangleIndex, ref vertices, ref normalVectorFromTriangle, lineTriangleIntersection.Value); } } } if (this.m_childs != null) { for (int j = 0; j < this.m_childs.Count; j++) { double?nullable8; if (a != null) { nullable8 = new double?((double)a.Value.Distance); } else { nullable4 = null; nullable8 = nullable4; } MyIntersectionResultLineTriangle?b = this.m_childs[j].GetIntersectionWithLineRecursive(model, ref line, nullable8); a = MyIntersectionResultLineTriangle.GetCloserIntersection(ref a, ref b); } } return(a); } TR_0000: return(null); }