public Triangle3D AddTriangle(Vector3d p1, Vector3d p2, Vector3d p3, Vector3d normal) { var triangle = new Triangle3D { Normal = normal }; var v1 = GetOrCreateVertex(p1); var v2 = GetOrCreateVertex(p2); var v3 = GetOrCreateVertex(p3); var normalTest = new Vector3d(normal.X, normal.Y, normal.Z); triangle.Vertices.Add(v1); triangle.Vertices.Add(v2); triangle.Vertices.Add(v3); triangle.Edges.Add(GetOrCreateEdgeBetween(v1, v2)); triangle.Edges.Add(GetOrCreateEdgeBetween(v2, v3)); triangle.Edges.Add(GetOrCreateEdgeBetween(v3, v1)); triangle.Edges[0].ConnectTriangle(triangle); triangle.Edges[1].ConnectTriangle(triangle); triangle.Edges[2].ConnectTriangle(triangle); v1.ConnectTriangle(triangle); v2.ConnectTriangle(triangle); v3.ConnectTriangle(triangle); triangle.RecomputeNormal(); if (Vector3d.Dot(normalTest, triangle.Normal) < 0) { triangle.FlipDirection(); } return(InternalAddTriangle(triangle)); }
void Update() { if (check || Input.GetKeyDown(KeyCode.Space)) { check = false; Triangle3D t = testPlane.triangle; Camera camera = cam; float theta_Y = camera.fieldOfView * 0.5f; float theta_X = Mathf.Atan(Mathf.Tan(camera.fieldOfView * 0.5f * Mathf.Deg2Rad) * camera.aspect) * Mathf.Rad2Deg; Plane left = new Plane(0, new Vector3(-Mathf.Cos((theta_X) * Mathf.Deg2Rad), 0, -Mathf.Sin((theta_X) * Mathf.Deg2Rad))); Plane right = new Plane(0, new Vector3(-Mathf.Cos((180 - theta_X) * Mathf.Deg2Rad), 0, -Mathf.Sin((180 - theta_X) * Mathf.Deg2Rad))); Plane near = new Plane(-camera.nearClipPlane, Vector3.back); Plane far = new Plane(camera.farClipPlane, Vector3.forward); Plane top = new Plane(0, new Vector3(0, -Mathf.Sin((-theta_Y + 90) * Mathf.Deg2Rad), -Mathf.Cos((-theta_Y + 90) * Mathf.Deg2Rad))); Plane buttom = new Plane(0, new Vector3(0, -Mathf.Sin((theta_Y - 90) * Mathf.Deg2Rad), -Mathf.Cos((theta_Y - 90) * Mathf.Deg2Rad))); List <Triangle3D> ts = Rasterizer.ViewSpaceFrustrumClipping(t, cam); print(buttom.Point(p1.position)); foreach (var go in ts) { TrianglePainter.CreateTrianglePainter(go); } } }
// get index of n-triangle p-oints // generation of indexes for triangle // if some point was used before on other triangle // then we should reuse them, triangles should be glued to each other private int[] getIndexOfNP(Triangle3D n, int i) { // trying to find indexed if they are used in already solved triangles int[] indexOfNP = { unique.IndexOf(n.p1), unique.IndexOf(n.p2), unique.IndexOf(n.p3) }; // if index == -1 then point was't used before // we need to generate index and add it to unique list // also it's new verticle in mesh if (indexOfNP[0] == -1) { unique.Add(n.p1); verticles.Add(mesh3d.triangles[i + 0]); indexOfNP[0] = unique.Count - 1; } if (indexOfNP[1] == -1) { unique.Add(n.p2); verticles.Add(mesh3d.triangles[i + 1]); indexOfNP[1] = unique.Count - 1; } if (indexOfNP[2] == -1) { unique.Add(n.p3); verticles.Add(mesh3d.triangles[i + 2]); indexOfNP[2] = unique.Count - 1; } return(indexOfNP); }
public static void CapMesh(out List<Triangle3D> triangleBucketList, out List<Triangle3D.Vertex> vertexBucketList, Triangle3D.Vertex[] sortedVerts, Transform objectTransform, Transform planeTransform, int triOffset) { triangleBucketList = new List<Triangle3D>(); vertexBucketList = new List<Triangle3D.Vertex>(); if (sortedVerts.Length < 3) { return; } Vector3 planeUp = planeTransform.up; // Project points to the plane and add them to the vertex bucket List<Vector3> projectedPoints = new List<Vector3>(); Matrix4x4 mat = Matrix4x4.TRS(objectTransform.position, Quaternion.Inverse(planeTransform.rotation), Vector3.one); for (int i = 0; i < sortedVerts.Length; i++) { Vector3 planePoint = mat.MultiplyPoint(sortedVerts[i].pos); projectedPoints.Add(new Vector3(planePoint.x, planePoint.z, 0)); vertexBucketList.Add(new Triangle3D.Vertex(objectTransform.InverseTransformPoint(sortedVerts[i].pos))); } // Triangulate int[] indices = Triangulator.Triangulate(projectedPoints.ToArray()); Vector3 average = Vector3.zero; // Calculate planar mapping float maxX = average.x; float minX = average.x; float maxZ = average.y; float minZ = average.y; for (int i = 0; i < projectedPoints.Count; i++) { maxX = Mathf.Max(projectedPoints[i].x, maxX); minX = Mathf.Min(projectedPoints[i].x, minX); maxZ = Mathf.Max(projectedPoints[i].y, maxZ); minZ = Mathf.Min(projectedPoints[i].y, minZ); } float nMaxX = maxX - minX; float nMaxZ = maxZ - minZ; // Created triangles for (int i = 0; i < indices.Length; i += 3) { int idx0 = indices[i + 0]; int idx1 = indices[i + 1]; int idx2 = indices[i + 2]; Vector2 UV1 = new Vector2((projectedPoints[idx0].x - minX) / nMaxX, (projectedPoints[idx0].y - minZ) / nMaxZ); Vector2 UV2 = new Vector2((projectedPoints[idx1].x - minX) / nMaxX, (projectedPoints[idx1].y - minZ) / nMaxZ); Vector2 UV3 = new Vector2((projectedPoints[idx2].x - minX) / nMaxX, (projectedPoints[idx2].y - minZ) / nMaxZ); Vector3 tangent = Vector3.zero; triangleBucketList.Add(new Triangle3D(vertexBucketList, new Triangle3D.Vertex[] { vertexBucketList[idx0], vertexBucketList[idx1], vertexBucketList[idx2] }, new Vector3[] { planeUp, planeUp, planeUp }, new Vector2[] { UV1, UV2, UV3 }, new Vector4[] { new Vector4(tangent.x, tangent.y, tangent.z, 1), new Vector4(tangent.x, tangent.y, tangent.z, 1), new Vector4(tangent.x, tangent.y, tangent.z, 1) }, new int[] { idx0 + triOffset, idx1 + triOffset, idx2 + triOffset }, 0)); } }
public DrawableTriangle(Triangle3D triangle3d) { Texture = Texture.WhitePixel; tri = triangle3d; Width = 500; Height = 600; }
protected void ShowSharp() { Matrix4x4 m1 = new Matrix4x4(); Matrix4x4 m2 = new Matrix4x4(); m1[1, 1] = 1; m1[1, 2] = 2; m1[1, 3] = 3; m1[1, 4] = 4; m1[2, 1] = 1; m1[2, 2] = 2; m1[2, 3] = 3; m1[2, 4] = 8; m1[3, 1] = 1; m1[3, 2] = 2; m1[3, 3] = 3; m1[3, 4] = 4; m1[4, 1] = 3; m1[4, 2] = 2; m1[4, 3] = 1; m1[4, 4] = 4; Matrix4x4 m3 = m1.Mul(m1); triangle = new Triangle3D(new Vector4(0d, -0.5d, 0d, 1d), new Vector4(0.5d, 0d, 0d, 1d), new Vector4(-0.5d, 0d, 0d, 1d)); }
public void drawMesh() { Triangle3D tri = container.draw(); List <Vector3> vertices = new List <Vector3> (); List <int> triangles = new List <int> (); List <Vector2> uvs = new List <Vector2> (); for (int i = 0; i < tri.vertices.Count; i++) { vertices.Add(tri.vertices[i].pos); triangles.Add(i); uvs.Add(Vector2.zero); } // mesh if (mesh == null) { mesh = new Mesh(); mesh.name = "generateMesh"; } mesh.Clear(); mesh.vertices = vertices.ToArray(); mesh.triangles = triangles.ToArray(); mesh.uv = uvs.ToArray(); //mesh.SetIndices(triangles.ToArray(), MeshTopology.Triangles, 0); mesh.RecalculateNormals(); meshFilter.mesh = mesh; }
public void Split(Triangle3D newTriangle, out Triangle3D[] resT) { var res = Triangle3D.SplitPlaneTriangleIntersection(plane, new Triangle3D(newTriangle[0], newTriangle[1], newTriangle[2])); resT = res.ToArray(); }
public void buildFirstUsedTriangles() { // we will iterate through objects on current triangle // and list every that contains at least part of any object // (after only flattening, without normalization) foreach (DynamicObject obj in objects) { // TODO remove that sin rotation // obj.rotation = Mathf.Sin(Time.realtimeSinceStartup); Vector3[] transformedVerticles = getTransformedByObject(obj); // going from end to begining, because we wanna to render first element as last // over every other element // for (int k = 0; k < localMesh.triangles.Length; k += 3) { for (int k = triangles.Length - 3; k >= 0; k -= 3) { if (usedTriangles.Contains(k)) { continue; } Triangle3D triangle = new Triangle3D(transformedVerticles[triangles[k + 0]], transformedVerticles[triangles[k + 1]], transformedVerticles[triangles[k + 2]]); if (triangle.isOnTexture()) { usedTriangles.Add(k); } } } }
public BSPTreeNode right; // smaller than splitting plane public BSPTreeNode(Triangle3D tri, T val) { triangles = new List <BSPTriangle>(); triangles.Add(new BSPTriangle(tri, val)); plane = new Plane3D(); plane.Set3Points(tri[0], tri[1], tri[2]); }
public bool checkForOutsiders() { List <int> usedTringlesAfterNormalization = new List <int>(); foreach (DynamicObject obj in objects) { Vector3[] transformedVerticles = getTransformedByObject(obj); foreach (int k in usedTriangles) { Triangle3D triangle = new Triangle3D(transformedVerticles[triangles[k + 0]], transformedVerticles[triangles[k + 1]], transformedVerticles[triangles[k + 2]]); if (!usedTringlesAfterNormalization.Contains(k) && triangle.isOnTexture()) { // that triangle is on texture, we should keep him usedTringlesAfterNormalization.Add(k); } else { // that triangle is outside texture, we may consider removing him // but it can be used in different objects } } } bool same = usedTriangles.Count == usedTringlesAfterNormalization.Count; usedTriangles = usedTringlesAfterNormalization; return(same); }
/// renvoie un nouveau triangle presque identique : on a change la taille par rapport a son centre, en pourcentage /// ex: 1 : la taille reste la meme /// ex: 0.5 : la taille est divisee par 2 public Triangle3D getScaled(float f01) { var lNewTri = new Triangle3D(this); lNewTri.scale(f01); return(lNewTri); }
void BuildRecursivly(BinNode <List <Triangle3D> > node) { if (node.data.Count <= 1) { return; } Triangle3D main = node.data[0]; Plane plane = new Plane(main.a, main.normal); for (int i = 1; i < node.data.Count; i++) { Triangle3D go = node.data[i]; float fa = Helper.SnapToZero(plane.Point(go.a)); float fb = Helper.SnapToZero(plane.Point(go.b)); float fc = Helper.SnapToZero(plane.Point(go.c)); if (fa >= 0 && fb >= 0 && fc >= 0) { if (node.right == null) { node.right = new BinNode <List <Triangle3D> >(new List <Triangle3D>()); node.right.data = new List <Triangle3D>(); } node.right.data.Add(go); } else if (fa <= 0 && fb <= 0 && fc <= 0) { if (node.left == null) { node.left = new BinNode <List <Triangle3D> >(new List <Triangle3D>()); node.left.data = new List <Triangle3D>(); } node.left.data.Add(go); } else { List <Triangle3D> ts = Rasterizer.ClipTriangle(go, plane); node.data.AddRange(ts); node.data.RemoveAt(i); i--; } } node.data.RemoveRange(1, node.data.Count - 1); if (node.left != null) { BuildRecursivly(node.left); } if (node.right != null) { BuildRecursivly(node.right); } }
/// true si on a 1 edge en commun (non oriente) public bool hasAtLeastOneEdgeInCommon_nonOriented(Triangle3D other) { bool aOK = hasVertex(other.A); bool bOK = hasVertex(other.B); bool c*K = hasVertex(other.C); return((aOK && bOK) || (aOK && c*K) || (bOK && c*K)); }
public Triangle3D(Triangle3D other) { // ceci fait bien une copie des valeurs A = other.A; B = other.B; C = other.C; color = other.color; }
public static Classification ClassifyTriangle(Triangle3D triangle, Plane plane, out Classification[] classes, float e) { if (triangle == null) { classes = null; return(Classification.UNDEFINED); } return(ClassifyPoints(triangle.pos, plane, out classes, e)); }
//用于将三角形于视锥体平面裁剪 //平面法向量需要朝向视锥体内部,返回存在于视锥体内的三角形 public static List <Triangle3D> ClipTrinagle_Frustum(Triangle3D triangle, Plane frustumPlane) { List <Triangle3D> result = new List <Triangle3D>(); Vector3 a = triangle.a; Vector3 b = triangle.b; Vector3 c = triangle.c; float fa = Helper.SnapToZero(frustumPlane.Point(a)); float fb = Helper.SnapToZero(frustumPlane.Point(b)); float fc = Helper.SnapToZero(frustumPlane.Point(c)); if ((fa <= 0 && fb <= 0 && fc <= 0)) { return(result); } else if (fa >= 0 && fb >= 0 && fc >= 0) { result.Add(triangle); return(result); } if (fa * fc > 0) { Vector3 tv = b; b = c; c = tv; float tf = fb; fb = fc; fc = tf; } else if (fb * fc > 0) { Vector3 tv = a; a = c; c = tv; float tf = fa; fa = fc; fc = tf; } Vector3 A = Intersection(a, c, frustumPlane); Vector3 B = Intersection(b, c, frustumPlane); if (fa > 0) { result.Add(new Triangle3D(a, b, A, triangle.normal)); result.Add(new Triangle3D(b, A, B, triangle.normal)); } else { result.Add(new Triangle3D(A, B, c, triangle.normal)); } return(result); }
private void PaintTriangle(Graphics g, Triangle3D tri, float contourHeight) { var col = (int)Math.Round(Math.Pow(contourHeight / 255.0f, 1.0f / 1.5f) * 255.0f); using (var p = new Pen(Color.FromArgb(col, col, col))) { this.PaintTriangle(g, tri, contourHeight, p); } }
//vytvori otexturovany trojuhelnik z t, s texturou texture namapovanou podle coords public TexturedTriangle(Triangle3D t,Triangle2D coords,Int32[,] texture) : base(t.V1,t.V2,t.V3) { texcoords = coords; bitmap = texture; width = texture.GetLength(0); height = texture.GetLength(1); port = new Viewport(1,1,width,width); }
public static void drawTriangle(Triangle3D t) { Gl.glVertex3dv(t.u.ToArray()); Gl.glVertex3dv(t.v.ToArray()); Gl.glVertex3dv(t.v.ToArray()); Gl.glVertex3dv(t.w.ToArray()); Gl.glVertex3dv(t.w.ToArray()); Gl.glVertex3dv(t.u.ToArray()); }
void DrawEntity(Entity entity) { Mesh mesh = entity.meshFilter.mesh; Transform objectTransform = entity.transform; Texture2D mainTex = entity.mainTex; for (int i = 0; i < mesh.triangles.Length; i += 3) { int a_index = mesh.triangles[i]; int b_index = mesh.triangles[i + 1]; int c_index = mesh.triangles[i + 2]; TriangleAttribute <Color> colors = new TriangleAttribute <Color>(Color.red, Color.green, Color.blue); TriangleAttribute <Vector2> uvs = new TriangleAttribute <Vector2>(mesh.uv[a_index], mesh.uv[b_index], mesh.uv[c_index]); Vector4 a = V4Point(mesh.vertices[a_index]); Vector4 b = V4Point(mesh.vertices[b_index]); Vector4 c = V4Point(mesh.vertices[c_index]); m_Transform m_objectTransform = new m_Transform(); m_objectTransform.CopyFromTransform(objectTransform); a = m_objectTransform.TransformPoint(a); b = m_objectTransform.TransformPoint(b); c = m_objectTransform.TransformPoint(c); TriangleAttribute <Vector3> pos_worlds = new TriangleAttribute <Vector3>(a, b, c); TriangleAttribute <Vector3> normals = new TriangleAttribute <Vector3>( m_objectTransform.TransformDirection(mesh.normals[a_index]), m_objectTransform.TransformDirection(mesh.normals[b_index]), m_objectTransform.TransformDirection(mesh.normals[c_index])); m_Transform cam_t = new m_Transform(); cam_t.CopyFromTransform(cam.transform); a = cam_t.InverseTransformPoint(a); b = cam_t.InverseTransformPoint(b); c = cam_t.InverseTransformPoint(c); Matrix4x4 p = GetProjectionMatrix(cam); Matrix4x4 negetive = Matrix4x4.identity; negetive.m22 = -1; Matrix4x4 total = p * negetive; a = ClipSpaceToScreenSpace(total * V4Point(a), pixelWidth, pixelHeight); b = ClipSpaceToScreenSpace(total * V4Point(b), pixelWidth, pixelHeight); c = ClipSpaceToScreenSpace(total * V4Point(c), pixelWidth, pixelHeight); a.z = a.w; b.z = b.w; c.z = c.w; Triangle3D triangle = new Triangle3D(a, b, c); //z值为摄像机空间z坐标 DrawTriangle(colorBuffer, triangle, colors, uvs, pos_worlds, normals, mainTex); } }
protected static void WriteTriangle(StreamWriter w, Triangle3D t) { w.WriteLine(string.Format("facet normal {0}", GetVectorSTR(t.Normal))); w.WriteLine("outer loop"); w.WriteLine(string.Format(" vertex {0} ", GetVectorSTR(t.Point1.Position))); w.WriteLine(string.Format(" vertex {0} ", GetVectorSTR(t.Point2.Position))); w.WriteLine(string.Format(" vertex {0} ", GetVectorSTR(t.Point3.Position))); w.WriteLine("endloop"); w.WriteLine("endfacet"); }
public bool checkForOutsidersAndNotCommons() { List <int> usedTringlesAfterNormalization = new List <int>(); List <int> usedTringlesWithCommon = new List <int>(); foreach (DynamicObject obj in objects) { Vector3[] transformedVerticles = getTransformedByObject(obj); foreach (int k in usedTriangles) { Triangle3D triangle = new Triangle3D(transformedVerticles[triangles[k + 0]], transformedVerticles[triangles[k + 1]], transformedVerticles[triangles[k + 2]]); if (!usedTringlesAfterNormalization.Contains(k) && triangle.isOnTexture()) { // that triangle is on texture, we should keep him usedTringlesAfterNormalization.Add(k); } else { // that triangle is outside texture, we may consider removing him // but it can be used in different objects } } } // looking for triangles that only one point common with any other triangle foreach (int k in usedTriangles) { int[] indexesK = { triangles[k + 0], triangles[k + 1], triangles[k + 2] }; if (haveCommonPoints(indexesK, k) || k == 0) { usedTringlesWithCommon.Add(k); } } bool same = usedTriangles.Count == usedTringlesWithCommon.Count; if (!same) { Debug.Log("checkForOutsiders " + usedTriangles.Count + " " + usedTringlesAfterNormalization.Count + " " + usedTringlesWithCommon.Count); } usedTriangles = usedTringlesWithCommon; return(same); }
public static List <Triangle3D> SplitPlaneTriangleIntersection(Vector3D planeNormal, Vector3D planePoint, Vector3D p1, Vector3D p2, Vector3D p3) { Plane3D plane = new Plane3D(planeNormal, planePoint); var triangle = new Triangle3D(p1, p2, p3); var res = SplitPlaneTriangleIntersection(plane, triangle); return(res); }
public static List <Triangle3D> ToSAM_Triangle3Ds(this Mesh mesh) { List <Triangle3D> result = new List <Triangle3D>(); for (int i = 0; i < mesh.NumTriangles; i++) { Triangle3D triangle3D = mesh.get_Triangle(i).ToSAM(); result.Add(triangle3D); } return(result); }
public void Insert(Triangle3D t, T val) { if (node == null) { node = new BSPTreeNode(t, val); } else { node.Insert(t, val); } }
public static Triangle3D Transform(this Transform transform, Triangle3D triangle3D, bool convertUnits = true) { if (transform == null || triangle3D == null) return null; if (transform.IsIdentity) return new Triangle3D(triangle3D); List<Point3D> point3Ds = triangle3D.GetPoints(); return new Triangle3D(Transform(transform, point3Ds[0], convertUnits), Transform(transform, point3Ds[1], convertUnits), Transform(transform, point3Ds[2], convertUnits)); }
public override bool Equals(object obj) { if (!(obj is Triangle3D)) { return(false); } Triangle3D other = (Triangle3D)obj; return(a.Equals(other.a) && b.Equals(other.b) && c.Equals(other.c)); }
private bool isNeighbour(Triangle3D n, List <Triangle3D> list) { foreach (Triangle3D p in list) { if (n.isNeighbour(p)) { return(true); } } return(false); }
private static Model3D CreateTriangleModel(Triangle3D triangle, Material material, double maxZ) { var points = new Point3DCollection(triangle.Points.Select(p => new System.Windows.Media.Media3D.Point3D(p.X, p.Y, maxZ - p.Z))); var geometry = new MeshGeometry3D { Positions = points }; return(new GeometryModel3D { Geometry = geometry, Material = material, BackMaterial = material }); }
public void TestPlaneCut() { /* * (2.7, 0.0, 0.0), (3.0, 1.0, 0.0), (2.5, 0.5, 0.0)) with plane Plane normal: (0, 1, 0) dist -0.50000005960464478 */ Triangle3D tri = new Triangle3D(new Vector3D(2.7, 0.0, 0.0), new Vector3D(3.0, 1.0, 0.0), new Vector3D(2.5, 0.5, 0.0)); Plane3D planeD = new Plane3D(new Vector3D(0, 1, 0), -0.50000005960464478); var res = Triangle3D.SplitPlaneTriangleIntersection(planeD, tri); Assert.True(res.Count == 2); Assert.True(res[0].ComputeArea() > 0.001); Assert.True(res[1].ComputeArea() > 0.001); }
public static void SortMesh(Mesh targetMesh, Triangle3D[] triangleBucket, int triangleBucketCount, Transform objectTransform, List <Triangle3D> capTriBucket, List <Triangle3D.Vertex> capVertBucket, bool flip) { Dictionary <int, int> vertCache = new Dictionary <int, int>(triangleBucketCount * 3); Triangle3D.Vertex vert = null; int vertexBucketCount = 0; Vector3[] vertexBucket = new Vector3[triangleBucketCount * 3]; for (int i = 0; i < triangleBucketCount; i++) { Triangle3D triangle = triangleBucket[i]; for (int j = 0; j < triangle.vertices.Length; j++) { vert = triangle.vertices[j]; int code = vert.GetHashCode(); if (!vertCache.ContainsKey(code)) { vertCache[code] = vertexBucketCount; triangle.vertices[j] = vert; triangle.indices[j] = vertexBucketCount; vertexBucket[vertexBucketCount] = objectTransform.InverseTransformPoint(vert.pos); vertexBucketCount++; } else { triangle.indices[j] = vertCache[code]; } } } int triWithCapCount = triangleBucketCount + capTriBucket.Count; int vertWithCapCount = vertexBucketCount + capVertBucket.Count; Array.Resize <Triangle3D>(ref triangleBucket, triangleBucketCount + capTriBucket.Count); Array.Resize <Vector3>(ref vertexBucket, vertexBucketCount + capVertBucket.Count); int triOff = 0; for (int i = triangleBucketCount; i < triWithCapCount; i++) { triangleBucket[i] = new Triangle3D(capTriBucket[triOff++], vertexBucketCount, flip); } int vertOff = 0; for (int i = vertexBucketCount; i < vertWithCapCount; i++) { vertexBucket[i] = capVertBucket[vertOff++].pos; } CreateNewMesh(targetMesh, triangleBucket, vertexBucket); }
public static void SetEdge(int indexA, int indexB, ClassificationUtil.Classification[] classes, Triangle3D triangle) { bool found = false; if(classes[indexA] == ClassificationUtil.Classification.COINCIDING && classes[indexB] == ClassificationUtil.Classification.COINCIDING) { foreach(Vector3[] edges in MeshSlicer.debugEdges) { if(edges[0] == triangle.vertices[indexA].pos && edges[1] == triangle.vertices[indexB].pos || edges[1] == triangle.vertices[indexA].pos && edges[0] == triangle.vertices[indexB].pos) { found = true; break; } } if(!found) { MeshSlicer.debugEdges.Add(new Vector3[] { triangle.vertices[indexA].pos, triangle.vertices[indexB].pos }); } } }
public Triangle3D(Triangle3D triangle3D, int offset, bool flip) { _meshVertices = triangle3D.meshVertices; _subMeshGroup = triangle3D.subMeshGroup; if (flip) { _vertices = new Vertex[] { triangle3D.vertices[2], triangle3D.vertices[1], triangle3D.vertices[0] }; _uvs = new Vector2[] { triangle3D.uvs[2], triangle3D.uvs[1], triangle3D.uvs[0] }; _indices = new int[] { triangle3D.indices[2] + offset, triangle3D.indices[1] + offset, triangle3D.indices[0] + offset }; _normals = new Vector3[] { -triangle3D.normals[2], -triangle3D.normals[1], -triangle3D.normals[0] }; _tangents = new Vector4[] { triangle3D.tangents[2], triangle3D.tangents[1], triangle3D.tangents[0] }; } else { _vertices = new Vertex[] { triangle3D.vertices[0], triangle3D.vertices[1], triangle3D.vertices[2] }; _uvs = new Vector2[] { triangle3D.uvs[0], triangle3D.uvs[1], triangle3D.uvs[2] }; _indices = new int[] { triangle3D.indices[0] + offset, triangle3D.indices[1] + offset, triangle3D.indices[2] + offset }; _normals = new Vector3[] { triangle3D.normals[0], triangle3D.normals[1], triangle3D.normals[2] }; _tangents = new Vector4[] { triangle3D.tangents[0], triangle3D.tangents[1], triangle3D.tangents[2] }; } }
public static void CreateNewMeshSimple(Mesh targetMesh, Triangle3D[] triangle3D, Vector3[] vertices) { int triLength = 0; int[] tris = new int[triangle3D.Length * 3]; Vector2[] uvs = new Vector2[vertices.Length]; Vector3[] normals = new Vector3[vertices.Length]; Vector4[] tangents = new Vector4[vertices.Length]; Triangle3D triangle; int idxV0; int idxV1; int idxV2; Vector2[] triUvs; Vector3[] triNormals; Vector4[] triTangents; for (int i = 0; i < triangle3D.Length; i++) { triangle = triangle3D[i]; idxV0 = triangle.indices[0]; idxV1 = triangle.indices[1]; idxV2 = triangle.indices[2]; triUvs = triangle.uvs; triNormals = triangle.normals; triTangents = triangle.tangents; tris[triLength++] = idxV0; tris[triLength++] = idxV1; tris[triLength++] = idxV2; uvs[idxV0] = triUvs[0]; uvs[idxV1] = triUvs[1]; uvs[idxV2] = triUvs[2]; normals[idxV0] = triNormals[0]; normals[idxV1] = triNormals[1]; normals[idxV2] = triNormals[2]; tangents[idxV0] = triTangents[0]; tangents[idxV1] = triTangents[1]; tangents[idxV2] = triTangents[2]; } targetMesh.Clear(); targetMesh.vertices = vertices; targetMesh.triangles = tris; targetMesh.normals = normals; targetMesh.uv = uvs; targetMesh.tangents = tangents; }
public static Triangle3D[] SplitTriangleWithPlane(Triangle3D triangle, Plane plane, float e, out ClassificationUtil.Classification side, bool cap) { ClassificationUtil.Classification[] classes; side = ClassificationUtil.ClassifyTriangle(triangle, plane, out classes, e); if(side != ClassificationUtil.Classification.STRADDLE) { if(cap) { SetEdge(0, 1, classes, triangle.pos); SetEdge(1, 2, classes, triangle.pos); SetEdge(2, 0, classes, triangle.pos); } return null; } //int iA; Triangle3D.Vertex pA; Vector3 normA; Vector2 uvA; //Vector4 tA; uint aLength = 0; int[] indicesA = new int[4]; Triangle3D.Vertex[] verticesA = new Triangle3D.Vertex[4]; Vector3[] normalsA = new Vector3[4]; Vector2[] uvsA = new Vector2[4]; Vector4[] tangentsA = new Vector4[4]; int iB; Triangle3D.Vertex pB; Vector3 normB; Vector2 uvB; Vector4 tB; uint bLength = 0; int[] indicesB = new int[4]; Triangle3D.Vertex[] verticesB = new Triangle3D.Vertex[4]; Vector3[] normalsB = new Vector3[4]; Vector2[] uvsB = new Vector2[4]; Vector4[] tangentsB = new Vector4[4]; float sideA; float sideB; Intersection isect; Vector2 newUV; List<Vector3> cVerts = new List<Vector3> (); int[] indices = new int[] { triangle.idxV0, triangle.idxV1, triangle.idxV2 }; Triangle3D.Vertex[] points = new Triangle3D.Vertex[] { triangle.v0, triangle.v1, triangle.v2 }; Vector3[] normals = new Vector3[] { triangle.nv0, triangle.nv1, triangle.nv2 }; Vector2[] uvs = new Vector2[] { triangle.uv0, triangle.uv1, triangle.uv2 }; Vector4[] tangents = new Vector4[] { triangle.tv0, triangle.tv1, triangle.tv2 }; float[] distance = new float[3]; for(int i = 0; i < points.Length; i++) { distance[i] = plane.GetDistanceToPoint(points[i].pos); } for(int i = 0; i < points.Length; i++) { int j = (i + 1) % points.Length; //iA = indices[i]; iB = indices[j]; pA = points[i]; pB = points[j]; uvA = uvs[i]; uvB = uvs[j]; normA = normals[i]; normB = normals[j]; //tA = tangents[i]; tB = tangents[j]; sideA = distance[i]; sideB = distance[j]; if(sideB > e) { if(sideA < -e) { isect = Intersection.LinePlane(pA.pos, pB.pos, plane, e, null); if(isect.status != Intersection.IntersectionType.INTERSECTION) { plane.distance += Mathf.Epsilon; return SplitTriangleWithPlane(triangle, new Plane (plane.normal, plane.distance + 1.0f), e, out side, cap); } // New vertex was created int newIndex = triangle.meshVertices.Count; triangle.meshVertices.Add(new Triangle3D.Vertex (isect.vert)); indicesA[aLength] = newIndex; indicesB[bLength] = newIndex; verticesA[aLength] = new Triangle3D.Vertex (isect.vert); verticesB[bLength] = new Triangle3D.Vertex (isect.vert); newUV = InterpolateUV(uvA, uvB, isect.alpha); uvsA[aLength] = newUV; uvsB[bLength] = newUV; tangentsA[aLength] = tB; tangentsB[bLength] = tB; normalsA[aLength] = Vector3.Lerp(normA, normB, isect.alpha); normalsB[bLength] = Vector3.Lerp(normA, normB, isect.alpha); aLength++; bLength++; if(!cVerts.Contains(isect.vert)) { cVerts.Add(isect.vert); } } indicesA[aLength] = iB; verticesA[aLength] = pB; uvsA[aLength] = uvB; normalsA[aLength] = normB; tangentsA[aLength] = tB; aLength++; } else if(sideB < -e) { if(sideA > e) { isect = Intersection.LinePlane(pA.pos, pB.pos, plane, e, null); if(isect.status != Intersection.IntersectionType.INTERSECTION) { return SplitTriangleWithPlane(triangle, new Plane(plane.normal, plane.distance + 1.0f), e, out side, cap); } // New vertex was created int newIndex = triangle.meshVertices.Count; triangle.meshVertices.Add(new Triangle3D.Vertex (isect.vert)); indicesA[aLength] = newIndex; indicesB[bLength] = newIndex; verticesA[aLength] = new Triangle3D.Vertex (isect.vert); verticesB[bLength] = new Triangle3D.Vertex (isect.vert); newUV = InterpolateUV(uvA, uvB, isect.alpha); uvsA[aLength] = newUV; uvsB[bLength] = newUV; tangentsA[aLength] = tB; tangentsB[bLength] = tB; normalsA[aLength] = Vector3.Lerp(normA, normB, isect.alpha); normalsB[bLength] = Vector3.Lerp(normA, normB, isect.alpha); aLength++; bLength++; if(!cVerts.Contains(isect.vert)) { cVerts.Add(isect.vert); } } indicesB[bLength] = iB; verticesB[bLength] = pB; uvsB[bLength] = uvB; normalsB[bLength] = normB; tangentsB[bLength] = tB; bLength++; } else { indicesA[aLength] = iB; verticesA[aLength] = pB; uvsA[aLength] = uvB; normalsA[aLength] = normB; tangentsA[aLength] = tB; aLength++; indicesB[bLength] = iB; verticesB[bLength] = pB; uvsB[bLength] = uvB; normalsB[bLength] = normB; tangentsB[bLength] = tB; bLength++; cVerts.Add(pB.pos); if(!cVerts.Contains(pB.pos)) { cVerts.Add(pB.pos); } } } for(int i = 0; i < cVerts.Count - 1; i++) { MeshSlicer.debugEdges.Add(new Vector3[] { cVerts[i], cVerts[i + 1] }); } Triangle3D[] tris; if(aLength > 3 || bLength > 3) { tris = new Triangle3D[3]; } else { tris = new Triangle3D[2]; } tris[0] = new Triangle3D (triangle.meshVertices, new Triangle3D.Vertex[] { verticesA[0], verticesA[1], verticesA[2] }, new Vector3[] { normalsA[0], normalsA[1], normalsA[2] }, new Vector2[] { uvsA[0], uvsA[1], uvsA[2] }, new Vector4[] { tangentsA[0], tangentsA[1], tangentsA[2] }, new int[] { indicesA[0], indicesA[1], indicesA[2] }, triangle.subMeshGroup); tris[1] = new Triangle3D (triangle.meshVertices, new Triangle3D.Vertex[] { verticesB[0], verticesB[1], verticesB[2] }, new Vector3[] { normalsB[0], normalsB[1], normalsB[2] }, new Vector2[] { uvsB[0], uvsB[1], uvsB[2] }, new Vector4[] { tangentsB[0], tangentsB[1], tangentsB[2] }, new int[] { indicesB[0], indicesB[1], indicesB[2] }, triangle.subMeshGroup); if(aLength > 3) { tris[2] = new Triangle3D (triangle.meshVertices, new Triangle3D.Vertex[] { verticesA[0], verticesA[2], verticesA[3] }, new Vector3[] { normalsA[0], normalsA[2], normalsA[3] }, new Vector2[] { uvsA[0], uvsA[2], uvsA[3] }, new Vector4[] { tangentsA[0], tangentsA[2], tangentsA[3] }, new int[] { indicesA[0], indicesA[2], indicesA[3] }, triangle.subMeshGroup); } else if(bLength > 3) { tris[2] = new Triangle3D (triangle.meshVertices, new Triangle3D.Vertex[] { verticesB[0], verticesB[2], verticesB[3] }, new Vector3[] { normalsB[0], normalsB[2], normalsB[3] }, new Vector2[] { uvsB[0], uvsB[2], uvsB[3] }, new Vector4[] { tangentsB[0], tangentsB[2], tangentsB[3] }, new int[] { indicesB[0], indicesB[2], indicesB[3] }, triangle.subMeshGroup); } return tris; }
public void runIndoorTest() { device = new IrrlichtDevice(SelectedDriverType, new Dimension2D(800,600), 16, false, true, false); device.EventReceiver = this; device.ResizeAble = true; device.WindowCaption = "Irrlicht.NET indoor test"; // load some textures and meshes ITexture texSydney = device.VideoDriver.GetTexture(@"..\..\media\sydney.bmp"); ITexture texWall = device.VideoDriver.GetTexture(@"..\..\media\wall.jpg"); ITexture texLogo = device.VideoDriver.GetTexture(@"..\..\media\irrlichtlogoaligned.jpg"); Irrlicht.Scene.IAnimatedMesh mesh = device.SceneManager.GetMesh(@"..\..\media\sydney.md2"); if (mesh == null) { System.Windows.Forms.MessageBox.Show( @"Could not load mesh ..\..\media\sydney.md2, exiting.", "Problem starting program"); return; } // add a cube to the scene ISceneNode node = device.SceneManager.AddCubeSceneNode(15, null, -1, new Vector3D(30,-15,0)); node.SetMaterialTexture(0, texWall); node.SetMaterialFlag(Irrlicht.Video.MaterialFlag.LIGHTING, false); // add an animator to the cube to make it rotate ISceneNodeAnimator anim = device.SceneManager.CreateRotationAnimator(new Vector3D(0.2f, 0.2f, 0)); node.AddAnimator(anim); // add animated mesh IAnimatedMeshSceneNode anode = device.SceneManager.AddAnimatedMeshSceneNode(mesh, null, -1); anode.SetMaterialTexture(0, texSydney); anode.SetMaterialFlag(MaterialFlag.LIGHTING, false); anode.Scale = new Vector3D(2,2,2); anode.Position = new Vector3D(0, -20, 0); // add a shadow Shadow = anode.AddShadowVolumeSceneNode(); if (Shadow != null) Shadow.Visible = false; // where no light there no shadow device.SceneManager.AddLightSceneNode(null, new Vector3D(20,100,-50), new Colorf(255,0,0), 200, -1); // add quake 3 level device.FileSystem.AddZipFileArchive("../../media/map-20kdm2.pk3"); IAnimatedMesh q3levelmesh = device.SceneManager.GetMesh("20kdm2.bsp"); ISceneNode q3node = device.SceneManager.AddOctTreeSceneNode(q3levelmesh, null, -1); q3node.Position = new Vector3D(-1370,-130,-1400); // create octtree triangle selector for q3 mesh ITriangleSelector selector = device.SceneManager.CreateOctTreeTriangleSelector( q3levelmesh.GetMesh(0), q3node, 128); // add billboard IBillboardSceneNode bill = device.SceneManager.AddBillboardSceneNode(null, new Dimension2Df(20,20), new Vector3D(0,0,0), -1); bill.SetMaterialType(MaterialType.TRANSPARENT_ADD_COLOR); bill.SetMaterialTexture(0, device.VideoDriver.GetTexture("../../media/particle.bmp")); bill.SetMaterialFlag(MaterialFlag.LIGHTING, false); bill.SetMaterialFlag(MaterialFlag.ZBUFFER, false); // create camera ICameraSceneNode cam = device.SceneManager.AddCameraSceneNodeFPS(null, 100, 300, -1); cam.Position = new Vector3D(20,300,-50); // make cursor invisible device.CursorControl.Visible = false; // create collision animator and add it to the camera ISceneNodeAnimator collAnim = device.SceneManager.CreateCollisionResponseAnimator( selector, cam, new Vector3D(30,50,30), // size of ellipsoid around camera new Vector3D(0, -3, 0), // gravity new Vector3D(0, 50, 0), // translation 0.0005f); // sliding value cam.AddAnimator(collAnim); // load some font and set it into the skin IGUIFont font = device.GUIEnvironment.GetFont("../../media/fonthaettenschweiler.bmp"); device.GUIEnvironment.Skin.Font = font; // add some gui stuff device.GUIEnvironment.AddMessageBox("Hello World", "I'm a Irrlicht.NET MessageBox. Please press SPACE to close me.", true, MessageBoxFlag.OK | MessageBoxFlag.CANCEL, null, -1); // start drawing loop int fps = 0; device.Run(); // fix for a temporary bug where quit messages are not be removed in the queue while(device.Run()) if (device.WindowActive) { device.VideoDriver.BeginScene(true, true, new Color(255,0,0,50)); // draw scene device.SceneManager.DrawAll(); device.GUIEnvironment.DrawAll(); // do some collision testing Line3D line = new Line3D(); line.start = cam.Position; line.end = ((cam.Target - line.start).Normalize() * 1000.0f ) + line.start; Vector3D intersection = new Vector3D(); Triangle3D tri = new Triangle3D(); if (device.SceneManager.SceneCollisionManager.GetCollisionPoint( line, selector, out intersection, out tri)) { bill.Position = intersection; Material mat = new Material(); mat.Lighting = false; device.VideoDriver.SetTransform(TransformationState.WORLD, new Matrix4()); device.VideoDriver.SetMaterial(mat); device.VideoDriver.Draw3DTriangle(tri, new Color(0,255,0,0)); } // draw 2d logo device.VideoDriver.Draw2DImage( texLogo, new Position2D(10,10), new Rect(0,0,88,31), new Rect(new Position2D(0,0),device.VideoDriver.ScreenSize), new Color(0xffffff), false); // draw some text font.Draw("Press 'S' to toggle the visibility of the realtime shadow.", new Position2D(120,20), new Color(100,150,200,200)); device.VideoDriver.EndScene(); if (fps != device.VideoDriver.FPS) { fps = device.VideoDriver.FPS; device.WindowCaption = "Irrlicht.NET test (primitives:" + device.VideoDriver.PrimitiveCountDrawn + ") fps:" + fps; } } }
public static void Main() { Console.WriteLine("v1=(1,1,-2.4)"); Vector3 v1 = new Vector3(1,1,-2.4); Console.WriteLine("v2=(4,5,6)"); Vector3 v2 = new Vector3(4,5,6); Console.WriteLine("v3=(-1,5,2)"); Vector3 v3 = new Vector3(-1,3,-2); Console.Write("v1*v2="); Vector3.CrossProduct(v1,v2).Vypis(); Console.Write("v1.v2="); Console.WriteLine(Vector3.DotProduct(v1,v2)); Console.Write("v1+v2="); (v1+v2).Vypis(); Console.Write("v1-v2="); (v1+v2).Vypis(); Console.Write("|v1|="); Console.WriteLine(v1.Abs()); Console.WriteLine("Normala plochy v1 v2 v3"); Vector3.GetNormVect(v1,v2,v3).Vypis(); Console.WriteLine("v1 perspektiva"); Projection p = new Projection((double)Math.PI/4,1,2.4,66); p.Project(v1).Vypis(); Console.WriteLine("Rozmery projekcni plochy:{0},{1}",p.Width,p.Height); Vector3 v4 = p.Project(v1); Console.WriteLine("z original = -2.4, z projected = {0}",p.ProjectZ(-2.4)); Console.WriteLine("projekceXY v1"); p.ProjectXY(v1).Vypis(); Viewport port = new Viewport(p.Width,p.Height,200,200); Console.WriteLine("souradnice v1 na obrazovce 200X200={0},{1}", port.GetIntX(v4.X),port.GetIntY(v4.Y)); Console.WriteLine("v2d=(1,2),sirka obrazovky = 2,rozliseni x = 200"); Vector2 v2d = new Vector2(1,2); int x = v2d.GetIntX(2,200); Console.WriteLine("x souradnice bodu na obrazovce={0}",x); Console.WriteLine("v2d=(-1,2),sirka obrazovky = 2,rozliseni x = 200"); v2d = new Vector2(-1,2); x = v2d.GetIntX(2,200); Console.WriteLine("x souradnice bodu na obrazovce={0}",x); Console.WriteLine("v2d=(0,2),sirka obrazovky = 2,rozliseni x = 200"); v2d = new Vector2(0,2); x = v2d.GetIntX(2,200); Console.WriteLine("x souradnice bodu na obrazovce={0}",x); Console.WriteLine("Trojuhelnik abc ma vrcholy v1,v2,v3"); Triangle3D abc = new Triangle3D(v1,v2,v3); Console.WriteLine("normalovy vektor k rovine trojuhelniku je"); abc.GetNormVect().Vypis(); Matrix44 matrix1 = new Matrix44(new double[,]{{1,2,3,4},{5,6,7,8}, {9,10,11,12},{13,14,15,16}}); Matrix44 matrix2 = new Matrix44(new double[,]{{3,2,1,0},{0,1,2,3}, {6,8,7,4},{2,3,1,9}}); Console.WriteLine("m1="); matrix1.Vypis(); Console.WriteLine("m2="); matrix2.Vypis(); Console.WriteLine("m1*m2="); Matrix44.Multiply(matrix1,matrix2).Vypis(); Console.WriteLine("Zkouska trideni"); v1.Vypis(); v2.Vypis(); v3.Vypis(); Vector3.SortX(ref v1,ref v2,ref v3); Console.WriteLine("Setrideno podle x:"); v1.Vypis(); v2.Vypis(); v3.Vypis(); Console.WriteLine("Line2D getx gety"); Line2D line2d = new Line2D(v1,v2); Console.WriteLine(line2d.GetX(0)); Console.WriteLine(line2d.GetY(0)); Line3D line3d = new Line3D(v1,v3); v4 = new Vector3(line3d.GetX(v2.Y),v2.Y,line3d.GetZFromY(v2.Y)); v1.Vypis(); v2.Vypis(); v3.Vypis(); v4.Vypis(); Console.WriteLine("interpolace:"); for(int i = 0;i<10;i++) line3d.Interpolate((double)i/(double)10).Vypis(); }
/* // Create a new bitmap. Bitmap bmp = new Bitmap("c:\\fakePhoto.jpg"); // Lock the bitmap's bits. Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height); System.Drawing.Imaging.BitmapData bmpData = bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, bmp.PixelFormat); // Get the address of the first line. IntPtr ptr = bmpData.Scan0; // Declare an array to hold the bytes of the bitmap. int bytes = Math.Abs(bmpData.Stride) * bmp.Height; ��� byte[] rgbValues = new byte[bytes]; // Copy the RGB values into the array. System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes); // Set every third value to 255. A 24bpp bitmap will look red. for (int counter = 2; counter < rgbValues.Length; counter += 3) rgbValues[counter] = 255; // Copy the RGB values back to the bitmap System.Runtime.InteropServices.Marshal.Copy(rgbValues, 0, ptr, bytes); // Unlock the bits. bmp.UnlockBits(bmpData); // Draw the modified image. e.Graphics.DrawImage(bmp, 0, 150); */ /*private void FromBitmap(Bitmap b,Int32[,] pole){ for(int i = 0;i<b.Width;i++) for(int j = 0;j<b.Height;j++){ pole[i,j] = b.GetPixel(i,j).ToArgb(); } } private unsafe Bitmap ToBitmap(Int32[,] pole){ Bitmap b; fixed(int* pp = &pole[0,0]) b= new Bitmap(pole.GetLength(1), pole.GetLength(0),pole.GetLength(1)*4, System.Drawing.Imaging.PixelFormat.Format32bppArgb,(IntPtr)pp); return b; }*/ void OnPaint(object sender, PaintEventArgs e) { //= new Bitmap(e.ClipRectangle.Width, e.ClipRectangle.Height, e.Graphics); //MyUnion union; if((e.ClipRectangle.Height != oldy) || (e.ClipRectangle.Width != oldx)) { pole = new Int32[e.ClipRectangle.Height,e.ClipRectangle.Width]; oldx = e.ClipRectangle.Width; oldy = e.ClipRectangle.Height; }else{Array.Clear(pole, 0, pole.Length);} //byte[] bytes = new byte[b.Width*b.Height*4]; //Int32[,] pole = new Int32[b.Width,b.Height]; Soft3DScreen s = new Soft3DScreen(pole); Triangle3D t3; Triangle2D t2; s.ViewMatrix.Translate(0,0,-5); s.ViewMatrix.RotateX(rx); s.ViewMatrix.RotateY(ry); Vector2 texcoord1 = new Vector2(-1,-1); Vector2 texcoord2 = new Vector2(-1,1); Vector2 texcoord3 = new Vector2(1,-1); Vector3 v1 = new Vector3(-1,-1,-1); Vector3 v2 = new Vector3(-1,1,-1); Vector3 v3 = new Vector3(1,-1,-1); t3 = new Triangle3D(v1,v2,v3); t2 = new Triangle2D(texcoord1,texcoord2,texcoord3); TexturedTriangle ttriangle = new TexturedTriangle(t3,t2,texture); s.DrawTexturedTriangle3d(ttriangle); texcoord1.Set(-1,1); texcoord2.Set(1,1); texcoord3.Set(1,-1); v1.Set(-1,1,-1); v2.Set(1,1,-1); v3.Set(1,-1,-1); t3 = new Triangle3D(v1,v2,v3); t2 = new Triangle2D(texcoord1,texcoord2,texcoord3); ttriangle = new TexturedTriangle(t3,t2,texture); s.DrawTexturedTriangle3d(ttriangle); /* s.ActualColor = Color.White.ToArgb(); v1.Set(-1,1,1); v2.Set(1,1,1); v3.Set(1,-1,1); //t3 = new Triangle3D(v1,v2,v3); s.DrawFilledTriangle3d(v1,v2,v3); v1.Set(-1,1,1); v2.Set(-1,-1,1); v3.Set(1,-1,1); //t3 = new Triangle3D(v1,v2,v3); s.DrawFilledTriangle3d(v1,v2,v3); s.ActualColor = Color.Green.ToArgb(); v1.Set(1,1,1); v2.Set(1,1,-1); v3.Set(1,-1,1); //t3 = new Triangle3D(v1,v2,v3); s.DrawFilledTriangle3d(v1,v2,v3); v1.Set(1,-1,-1); v2.Set(1,1,-1); v3.Set(1,-1,1); //t3 = new Triangle3D(v1,v2,v3); s.DrawFilledTriangle3d(v1,v2,v3); s.ActualColor = Color.Blue.ToArgb(); v1.Set(-1,1,1); v2.Set(-1,1,-1); v3.Set(-1,-1,1); //t3 = new Triangle3D(v1,v2,v3); s.DrawFilledTriangle3d(v1,v2,v3);; v1.Set(-1,-1,-1); v2.Set(-1,1,-1); v3.Set(-1,-1,1); //t3 = new Triangle3D(v1,v2,v3); s.DrawFilledTriangle3d(v1,v2,v3); s.ActualColor = Color.Cyan.ToArgb(); v1.Set(1,1,1); v2.Set(1,1,-1); v3.Set(-1,1,1); //t3 = new Triangle3D(v1,v2,v3); s.DrawFilledTriangle3d(v1,v2,v3); v1.Set(-1,1,-1); v2.Set(-1,1,1); v3.Set(1,1,-1); //t3 = new Triangle3D(v1,v2,v3); s.DrawFilledTriangle3d(v1,v2,v3); s.ActualColor = Color.Orange.ToArgb(); v1.Set(1,-1,1); v2.Set(1,-1,-1); v3.Set(-1,-1,1); //t3 = new Triangle3D(v1,v2,v3); s.DrawFilledTriangle3d(v1,v2,v3); v1.Set(-1,-1,-1); v2.Set(1,-1,-1); v3.Set(-1,-1,1); //t3 = new Triangle3D(v1,v2,v3); s.DrawFilledTriangle3d(v1,v2,v3);*/ Bitmap b = Soft3DBitmap.ToBitmap(pole); e.Graphics.DrawImageUnscaled(b, 0, 0); //e.Graphics.DrawImageUnscaled(texture, 0, 0); }
public static void SortMesh(Mesh targetMesh, Triangle3D[] triangleBucket, int triangleBucketCount, Transform objectTransform, List<Triangle3D> capTriBucket, List<Triangle3D.Vertex> capVertBucket, bool flip) { Dictionary<int, int> vertCache = new Dictionary<int, int>(triangleBucketCount * 3); Triangle3D.Vertex vert = null; int vertexBucketCount = 0; Vector3[] vertexBucket = new Vector3[triangleBucketCount * 3]; for (int i = 0; i < triangleBucketCount; i++) { Triangle3D triangle = triangleBucket[i]; for (int j = 0; j < triangle.vertices.Length; j++) { vert = triangle.vertices[j]; int code = vert.GetHashCode(); if (!vertCache.ContainsKey(code)) { vertCache[code] = vertexBucketCount; triangle.vertices[j] = vert; triangle.indices[j] = vertexBucketCount; vertexBucket[vertexBucketCount] = objectTransform.InverseTransformPoint(vert.pos); vertexBucketCount++; } else { triangle.indices[j] = vertCache[code]; } } } int triWithCapCount = triangleBucketCount + capTriBucket.Count; int vertWithCapCount = vertexBucketCount + capVertBucket.Count; Array.Resize<Triangle3D>(ref triangleBucket, triangleBucketCount + capTriBucket.Count); Array.Resize<Vector3>(ref vertexBucket, vertexBucketCount + capVertBucket.Count); int triOff = 0; for (int i = triangleBucketCount; i < triWithCapCount; i++) { triangleBucket[i] = new Triangle3D(capTriBucket[triOff++], vertexBucketCount, flip); } int vertOff = 0; for (int i = vertexBucketCount; i < vertWithCapCount; i++) { vertexBucket[i] = capVertBucket[vertOff++].pos; } CreateNewMesh(targetMesh, triangleBucket, vertexBucket); }
public static Classification ClassifyTriangle(Triangle3D triangle, Plane plane, out Classification[] classes, float e) { if (triangle == null) { classes = null; return Classification.UNDEFINED; } return ClassifyPoints(triangle.pos, plane, out classes, e); }
public static void CreateNewMesh(Mesh targetMesh, Triangle3D[] triangle3D, Vector3[] vertices) { int subMeshALength = 0; int subMeshBLength = 0; int[] subMeshA = new int[triangle3D.Length * 3]; int[] subMeshB = new int[triangle3D.Length * 3]; int offset = 0; //int[] tris = new int[triangle3D.Length * 3]; Vector2[] uvs = new Vector2[vertices.Length]; Vector3[] normals = new Vector3[vertices.Length]; Vector4[] tangents = new Vector4[vertices.Length]; Triangle3D triangle; int idxV0; int idxV1; int idxV2; Vector2[] triUvs; Vector3[] triNormals; Vector4[] triTangents; for (int i = 0; i < triangle3D.Length; i++) { triangle = triangle3D[i]; idxV0 = triangle.indices[0]; idxV1 = triangle.indices[1]; idxV2 = triangle.indices[2]; triUvs = triangle.uvs; triNormals = triangle.normals; triTangents = triangle.tangents; if (triangle3D[i].subMeshGroup == 0) { subMeshA[subMeshALength++] = idxV0; subMeshA[subMeshALength++] = idxV1; subMeshA[subMeshALength++] = idxV2; } if (triangle3D[i].subMeshGroup == 1) { subMeshB[subMeshBLength++] = idxV0; subMeshB[subMeshBLength++] = idxV1; subMeshB[subMeshBLength++] = idxV2; } uvs[idxV0] = triUvs[0]; uvs[idxV1] = triUvs[1]; uvs[idxV2] = triUvs[2]; normals[idxV0] = triNormals[0]; normals[idxV1] = triNormals[1]; normals[idxV2] = triNormals[2]; tangents[idxV0] = triTangents[0]; tangents[idxV1] = triTangents[1]; tangents[idxV2] = triTangents[2]; offset += 3; } targetMesh.Clear(); targetMesh.subMeshCount = 2; targetMesh.vertices = vertices; targetMesh.SetTriangles(subMeshA, 0); targetMesh.SetTriangles(subMeshB, 1); targetMesh.normals = normals; targetMesh.uv = uvs; targetMesh.tangents = tangents; }
public static Triangle3D[] SplitTriangleWithPlane(Triangle3D triangle, Plane plane, float e, out ClassificationUtil.Classification side) { return SplitTriangleWithPlane(triangle, plane, e, out side, true); }
//vytvori trojuhelnik ze souradnic trojuhelnika t s barvou pcolor public TexturedTriangle(Triangle3D t,Int32 pcolor) : base(t.V1,t.V2,t.V3) { color = pcolor; }
public static SplitMesh GrabMeshOutline(Mesh mesh, Plane cuttingPlane, Transform transform, Transform rotation) { debugPolyLoop = new List<Vector3>(); debugEdgePoints = new List<Vector3>(); debugEdges = new List<Vector3[]>(); debugLoopEdgePoints = new List<Vector3[]>(); int vertCount = mesh.vertexCount; Vector3[] verts = mesh.vertices; Triangle3D.Vertex[] allVerts = new Triangle3D.Vertex[vertCount]; for (int i = 0; i < vertCount; i++) { allVerts[i] = new Triangle3D.Vertex(transform.TransformPoint(verts[i])); } List<Triangle3D.Vertex> allVertList = new List<Triangle3D.Vertex>(); Vector2[] originalUVs = mesh.uv; Vector3[] originalNormals = mesh.normals; Vector4[] originalTangents = mesh.tangents; int triCount = mesh.triangles.Length / 3; Triangle3D[] originalTriangles = new Triangle3D[triCount]; int offset = 0; for (int j = 0; j < mesh.subMeshCount; j++) { uint triOffset = 0; int[] subMeshIndices = mesh.GetTriangles(j); int subMeshTriCount = subMeshIndices.Length / 3; for (int i = 0; i < subMeshTriCount; i++) { int idx0 = subMeshIndices[triOffset + 0]; int idx1 = subMeshIndices[triOffset + 1]; int idx2 = subMeshIndices[triOffset + 2]; if (originalTriangles.Length <= offset) { Debug.Log("Error"); } originalTriangles[offset++] = new Triangle3D(allVertList, new Triangle3D.Vertex[] { allVerts[idx0], allVerts[idx1], allVerts[idx2] }, new Vector3[] { originalNormals[idx0], originalNormals[idx1], originalNormals[idx2] }, new Vector2[] { originalUVs[idx0], originalUVs[idx1], originalUVs[idx2] }, new Vector4[] { originalTangents[idx0], originalTangents[idx1], originalTangents[idx2] }, new int[] { subMeshIndices[triOffset + 0], subMeshIndices[triOffset + 1], subMeshIndices[triOffset + 2] }, j); triOffset += 3; } } if (originalTriangles.Length > 0) { int processedTriCount = 0; Triangle3D[] processedTris = new Triangle3D[originalTriangles.Length * 3]; ClassificationUtil.Classification prevSide = ClassificationUtil.Classification.UNDEFINED; foreach (Triangle3D originalTriangle in originalTriangles) { ClassificationUtil.Classification side; Triangle3D[] splitTriangles = TriangleUtil.SplitTriangleWithPlane(originalTriangle, cuttingPlane, float.Epsilon, out side); if (prevSide != ClassificationUtil.Classification.UNDEFINED && prevSide != side) { } prevSide = side; if (splitTriangles != null) { // Triangle was cut foreach (Triangle3D splitTriangle in splitTriangles) { processedTris[processedTriCount] = splitTriangle; processedTriCount++; } } else { // Triangle was not cut processedTris[processedTriCount] = originalTriangle; processedTriCount++; } } int triangleBucketACount = 0; int triangleBucketBCount = 0; Triangle3D[] triangleBucketA = new Triangle3D[processedTriCount]; Triangle3D[] triangleBucketB = new Triangle3D[processedTriCount]; for (int i = 0; i < processedTriCount; i++) { ClassificationUtil.Classification[] classes; ClassificationUtil.Classification triClass = ClassificationUtil.ClassifyPoints(processedTris[i].pos, cuttingPlane, out classes, float.Epsilon); if (triClass == ClassificationUtil.Classification.FRONT) { triangleBucketA[triangleBucketACount++] = processedTris[i]; } else if (triClass == ClassificationUtil.Classification.BACK) { triangleBucketB[triangleBucketBCount++] = processedTris[i]; } } if (triangleBucketACount == 0 || triangleBucketBCount == 0) { return null; } List<Triangle3D> totalCapTriBucket = new List<Triangle3D>(); List<Triangle3D.Vertex> totalCapVertBucket = new List<Triangle3D.Vertex>(); List<List<Triangle3D.Vertex>> capVertGroups = new List<List<Triangle3D.Vertex>>(); while (debugEdges.Count > 2) { List<Triangle3D> capTriBucket = new List<Triangle3D>(); List<Triangle3D.Vertex> capVertBucket = new List<Triangle3D.Vertex>(); Triangle3D.Vertex[] sortedVerts = GetPolyLoop(ref debugEdges); if (sortedVerts != null) { CapMesh(out capTriBucket, out capVertBucket, sortedVerts, transform, rotation, totalCapTriBucket.Count); } #if false if(capVertBucket.Count > 2) { for(int i = 0; i < capVertBucket.Count - 1; i++) { Debug.DrawLine(transform.TransformPoint(capVertBucket[i].pos), transform.TransformPoint(capVertBucket[i + 1].pos)); } Debug.DrawLine(transform.TransformPoint(capVertBucket[capVertBucket.Count - 1].pos), transform.TransformPoint(capVertBucket[0].pos)); } #endif totalCapTriBucket.AddRange(capTriBucket); totalCapVertBucket.AddRange(capVertBucket); capVertGroups.Add(capVertBucket); } Vector3[] vertexBucket = new Vector3[totalCapVertBucket.Count]; for (int i = 0; i < totalCapVertBucket.Count; i++) { vertexBucket[i] = transform.TransformPoint(totalCapVertBucket[i].pos); } return new SplitMesh(new List<Vector3>(vertexBucket), totalCapTriBucket, capVertGroups); } else { Debug.LogError("Source geometry empty"); return null; } }
public static bool CutTriangleMeshOneSide(Mesh outputMeshes, Mesh sourceMesh, Plane cuttingPlane, Transform transform, Transform rotation, bool frontSide, bool cap) { float epsilon = 0.00001f; hashCheck = new Dictionary<Vector3, int>(); debugPolyLoop = new List<Vector3>(); debugEdgePoints = new List<Vector3>(); debugEdges = new List<Vector3[]>(); debugLoopEdgePoints = new List<Vector3[]>(); int vertCount = sourceMesh.vertexCount; Vector3[] verts = sourceMesh.vertices; Triangle3D.Vertex[] allVerts = new Triangle3D.Vertex[vertCount]; for (int i = 0; i < vertCount; i++) { allVerts[i] = new Triangle3D.Vertex(transform.TransformPoint(verts[i])); } List<Triangle3D.Vertex> allVertList = new List<Triangle3D.Vertex>(); //int[] originalIndices = sourceMesh.triangles; Vector2[] originalUVs = sourceMesh.uv; Vector3[] originalNormals = sourceMesh.normals; Vector4[] originalTangents = sourceMesh.tangents; int triCount = sourceMesh.triangles.Length / 3; Triangle3D[] originalTriangles = new Triangle3D[triCount]; int offset = 0; for (int j = 0; j < sourceMesh.subMeshCount; j++) { uint triOffset = 0; int[] subMeshIndices = sourceMesh.GetTriangles(j); int subMeshTriCount = subMeshIndices.Length / 3; for (int i = 0; i < subMeshTriCount; i++) { int idx0 = subMeshIndices[triOffset + 0]; int idx1 = subMeshIndices[triOffset + 1]; int idx2 = subMeshIndices[triOffset + 2]; originalTriangles[offset++] = new Triangle3D(allVertList, new Triangle3D.Vertex[] { allVerts[idx0], allVerts[idx1], allVerts[idx2] }, new Vector3[] { originalNormals[idx0], originalNormals[idx1], originalNormals[idx2] }, new Vector2[] { originalUVs[idx0], originalUVs[idx1], originalUVs[idx2] }, new Vector4[] { originalTangents[idx0], originalTangents[idx1], originalTangents[idx2] }, new int[] { subMeshIndices[triOffset + 0], subMeshIndices[triOffset + 1], subMeshIndices[triOffset + 2] }, j); triOffset += 3; } } if (originalTriangles.Length > 0) { int processedTriCount = 0; Triangle3D[] processedTris = new Triangle3D[originalTriangles.Length * 3]; ClassificationUtil.Classification prevSide = ClassificationUtil.Classification.UNDEFINED; foreach (Triangle3D originalTriangle in originalTriangles) { ClassificationUtil.Classification side; Triangle3D[] splitTriangles = TriangleUtil.SplitTriangleWithPlane(originalTriangle, cuttingPlane, epsilon, out side, cap); if (prevSide != ClassificationUtil.Classification.UNDEFINED && prevSide != side) { } prevSide = side; if (splitTriangles != null) { foreach (Triangle3D splitTriangle in splitTriangles) { processedTris[processedTriCount] = splitTriangle; processedTriCount++; } } else { processedTris[processedTriCount] = originalTriangle; processedTriCount++; } } //if (!cut) //{ // CloneMesh(sourceMesh, outputMeshes); // return false; //} int triangleBucketCount = 0; Triangle3D[] triangleBucket = new Triangle3D[processedTriCount]; for (int i = 0; i < processedTriCount; i++) { ClassificationUtil.Classification[] classes; ClassificationUtil.Classification triClass = ClassificationUtil.ClassifyPoints(processedTris[i].pos, cuttingPlane, out classes, epsilon); if (triClass == ClassificationUtil.Classification.FRONT && frontSide) { triangleBucket[triangleBucketCount++] = processedTris[i]; } else if (triClass == ClassificationUtil.Classification.BACK && !frontSide) { triangleBucket[triangleBucketCount++] = processedTris[i]; } } if (triangleBucketCount == 0) { outputMeshes.Clear(); return false; } List<Triangle3D> totalCapTriBucket = new List<Triangle3D>(); List<Triangle3D.Vertex> totalCapVertBucket = new List<Triangle3D.Vertex>(); while (cap && debugEdges.Count > 2) { List<Triangle3D> capTriBucket = new List<Triangle3D>(); List<Triangle3D.Vertex> capVertBucket = new List<Triangle3D.Vertex>(); Triangle3D.Vertex[] sortedVerts = GetPolyLoop(ref debugEdges); if (sortedVerts != null) { CapMesh(out capTriBucket, out capVertBucket, sortedVerts, transform, rotation, totalCapTriBucket.Count); } totalCapTriBucket.AddRange(capTriBucket); totalCapVertBucket.AddRange(capVertBucket); } if (triangleBucketCount > 0) { SortMesh(outputMeshes, triangleBucket, triangleBucketCount, transform, totalCapTriBucket, totalCapVertBucket, !frontSide); } return true; } else { return false; } }