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); } Line lineF = (Line)m_line; float?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) && ((m_result == null) || (distance.Value < m_result.Value.Distance))) { // We need to remember original triangleVertexes coordinates (not transformed by world matrix) m_result = new MyIntersectionResultLineTriangle(ref triangle, ref calculatedTriangleNormal, distance.Value); return(distance.Value); } return(null); }
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); } Line lineF = (Line)m_line; float?distance = MyUtils.GetLineTriangleIntersection(ref lineF, ref triangle); if (distance.HasValue) { var result = new MyIntersectionResultLineTriangle(ref triangle, ref calculatedTriangleNormal, distance.Value); m_result.Add(result); } return(distance); }
IPhysicsMesh CreatePhysicsMesh(MyModel model) { IPhysicsMesh physicsMesh = new MyPhysicsMesh(); physicsMesh.SetAABB(model.BoundingBox.Min, model.BoundingBox.Max); for (int v = 0; v < model.GetVerticesCount(); v++) { Vector3 vertex = model.GetVertex(v); Vector3 normal = model.GetVertexNormal(v); Vector3 tangent = model.GetVertexTangent(v); if (model.TexCoords == null) model.LoadTexCoordData(); Vector2 texCoord = model.TexCoords[v].ToVector2(); physicsMesh.AddVertex(vertex, normal, tangent, texCoord); } for (int i = 0; i < model.Indices16.Length; i++) { physicsMesh.AddIndex(model.Indices16[i]); } for (int i = 0; i < model.GetMeshList().Count; i++) { var mesh = model.GetMeshList()[i]; physicsMesh.AddSectionData(mesh.IndexStart, mesh.TriCount, mesh.Material.Name); } return physicsMesh; }
// 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 BoundingSphereD sphere) { // Check if sphere intersects bounding box of this node if (m_boundingBox.Intersects(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 (triangleBoundingBox.Intersects(ref sphere)) { // 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); PlaneD trianglePlane = new PlaneD(triangle.Vertex0, triangle.Vertex1, triangle.Vertex2); 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 GetTrianglesIntersectingSphere(MyModel model, ref BoundingSphereD 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 (m_boundingBox.Intersects(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 (triangleBoundingBox.Intersects(ref sphere)) { //if (m_triangleIndices[value] != ignoreTriangleWithIndex) { // See that we swaped vertex indices!! MyTriangle_Vertexes triangle; MyTriangle_Normals triangleNormals; //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); /* triangleTangents.Normal0 = model.GetVertexTangent(triangleIndices.I0); triangleTangents.Normal1 = model.GetVertexTangent(triangleIndices.I2); triangleTangents.Normal2 = model.GetVertexTangent(triangleIndices.I1); */ PlaneD trianglePlane = new PlaneD(triangle.Vertex0, triangle.Vertex1, triangle.Vertex2); 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.Vertices = triangle; retTriangle.Normals = triangleNormals; // 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 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 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_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); 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 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) ? (double?)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; }
private static void ExtractModelDataForObj( MyModel model, Matrix matrix, List<Vector3> vertices, List<TriangleWithMaterial> triangles, List<Vector2> uvs, ref Vector2 offsetUV, Dictionary<string, MyExportModel.Material> materials, ref int currVerticesCount, Vector3 colorMaskHSV) { if (false == model.HasUV) { model.LoadUV = true; model.UnloadData(); model.LoadData(); } MyExportModel renderModel = new MyExportModel(model); int modelVerticesCount = renderModel.GetVerticesCount(); List<HalfVector2> modelUVs = GetUVsForModel(renderModel, modelVerticesCount); Debug.Assert(modelUVs.Count == modelVerticesCount, "wrong UVs for model"); if (modelUVs.Count != modelVerticesCount) { return; } //we need new material for every HSV and texture combination, therefore we need to create new materials for each model List<MyExportModel.Material> newModelMaterials = CreateMaterialsForModel(materials, colorMaskHSV, renderModel); for (int i = 0; i < modelVerticesCount; ++i) { vertices.Add(Vector3.Transform(model.GetVertex(i), matrix)); Vector2 localUV = modelUVs[i].ToVector2()/model.PatternScale + offsetUV; uvs.Add(new Vector2(localUV.X, -localUV.Y)); } for (int i = 0; i < renderModel.GetTrianglesCount(); ++i) { int matID = -1; for (int j = 0; j < newModelMaterials.Count; ++j) { if (i <= newModelMaterials[j].LastTri) { matID = j; break; } } Debug.Assert(matID != -1, "Triangle with no material"); var t = renderModel.GetTriangle(i); string materialName = "EmptyMaterial"; if (matID != -1) { materialName = newModelMaterials[matID].Name; } triangles.Add(new TriangleWithMaterial() { triangle = new MyTriangleVertexIndices(t.I0 + 1 + currVerticesCount, t.I1 + 1 + currVerticesCount, t.I2 + 1 + currVerticesCount), material = materialName, }); } currVerticesCount += modelVerticesCount; }
HkShape CreateShape(MyModel model, HkShapeType shapeType) { switch(shapeType) { case HkShapeType.Box: Vector3 halfExtents = (model.BoundingBox.Max - model.BoundingBox.Min) / 2; return new HkBoxShape(Vector3.Max(halfExtents - 0.1f, new Vector3(0.05f)), 0.02f); break; case HkShapeType.Sphere: return new HkSphereShape(model.BoundingSphere.Radius); break; case HkShapeType.ConvexVertices: m_tmpVerts.Clear(); for (int i = 0; i < model.GetVerticesCount(); i++) { m_tmpVerts.Add(model.GetVertex(i)); } return new HkConvexVerticesShape(m_tmpVerts.GetInternalArray(), m_tmpVerts.Count, true, 0.1f); break; } throw new InvalidOperationException("This shape is not supported"); }
public void GetTrianglesIntersectingSphere(ref BoundingSphereD sphere, Vector3?referenceNormalVector, float?maxAngle, List <MyTriangle_Vertex_Normals> retTriangles, int maxNeighbourTriangles) { var aabb = BoundingBox.CreateInvalid(); BoundingSphere sphereF = (BoundingSphere)sphere; aabb.Include(ref sphereF); AABB gi_aabb = new AABB(aabb.Min.ToBullet(), aabb.Max.ToBullet()); 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 (triangleBoundingBox.Intersects(ref sphere)) { //if (m_triangleIndices[value] != ignoreTriangleWithIndex) { // See that we swaped vertex indices!! MyTriangle_Vertexes triangle; MyTriangle_Normals triangleNormals; //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); PlaneD trianglePlane = new PlaneD(triangle.Vertex0, triangle.Vertex1, triangle.Vertex2); 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.Vertices = triangle; retTriangle.Normals = triangleNormals; retTriangles.Add(retTriangle); } } } } } } }