/// <summary> /// Can build side: Input1: Block at side, Input2: Base block /// </summary> public static List<CustomBlockData> GenerateModel(List<BoundingBox> boxes, BlockSource source, Point3 blockPos, bool removeCoveredFaces, IGeometryGeneratorSource i) { BlockData currentBlock = source.GetData(blockPos); Vector3[] norms = new Vector3[] { new Vector3(1, 0, 0), new Vector3(-1, 0, 0), new Vector3(0, 1, 0), new Vector3(0, -1, 0), new Vector3(0, 0, 1), new Vector3(0, 0, -1) }; Dictionary<Vector3, Dictionary<float, List<Face>>> faces = new Dictionary<Vector3, Dictionary<float, List<Face>>>(); //Vector3 key: normal //float key: value of normal component //Foreach bounding box foreach (BoundingBox bb in boxes) { //Foreach normal (Minecraft normals) foreach (Vector3 normal in norms) { //Get the face for the normal Face face = GetFace(bb, normal); face.TextureTag = bb.TextureTag; //Store it using the important Normal component float val = face.GetNormalValue(); if (float.IsNaN(val)) continue; Dictionary<float, List<Face>> dict; if (faces.ContainsKey(normal)) { dict = faces[normal]; } else { dict = new Dictionary<float, List<Face>>(); faces.Add(normal, dict); } if (dict.ContainsKey(val)) dict[val].Add(face); else dict.Add(val, new List<Face>() { face }); } } List<CustomBlockData> datas = new List<CustomBlockData>(); //Foreach normal foreach (KeyValuePair<Vector3, Dictionary<float, List<Face>>> pair in faces) { //Foreach normal component foreach (KeyValuePair<float, List<Face>> pair2 in pair.Value) { //Check if we should build the side if(pair2.Key == 0 && (pair.Key.X == -1 || pair.Key.Y == -1 || pair.Key.Z == -1)) //- sides { Point3 dir3 = pair.Key.ToPoint3(); Point3 atSide = blockPos + dir3; BlockData atSideBlock = source.GetData(atSide); if (!i.CanBuildSide(currentBlock, atSideBlock, blockPos, atSide)) { continue; } } if (pair2.Key == 1 && (pair.Key.X == 1 || pair.Key.Y == 1 || pair.Key.Z == 1)) //+ sides { Point3 dir3 = pair.Key.ToPoint3(); Point3 atSide = blockPos + dir3; BlockData atSideBlock = source.GetData(atSide); if (!i.CanBuildSide(currentBlock, atSideBlock, blockPos, atSide)) { continue; } } //pair2.Value contains the faces of the current Normal and Normal component value //Let's calculate what we can see: GpcPolygon polygon = new GpcPolygon(); foreach(Face face in pair2.Value) { GpcPolygon addPoly = new GpcPolygon(); addPoly.AddContour(new GpcVertexList(face.ConvertToPointList()), false); polygon = polygon.Clip(GpcOperation.Union, addPoly); } //Remove the invisible parts Vector3 inverseNormal = -pair.Key; if (faces.ContainsKey(inverseNormal) && removeCoveredFaces) { if (faces[inverseNormal].ContainsKey(pair2.Key)) //There are faces, which make this face invisible { GpcPolygon invisible = new GpcPolygon(); foreach (Face face2 in faces[inverseNormal][pair2.Key]) { GpcPolygon addPoly = new GpcPolygon(); addPoly.AddContour(new GpcVertexList(face2.ConvertToPointList()), false); invisible = invisible.Clip(GpcOperation.Union, addPoly); } polygon = polygon.Clip(GpcOperation.Difference, invisible); //Remove the invisible parts } } //Create the face if (polygon.NofContours == 0) continue; foreach (GpcVertexList polys in polygon.Contour) { List<PolygonPoint> points = new List<PolygonPoint>(); foreach (GpcVertex vert in polys.Vertex) { points.Add(new PolygonPoint(vert.X, vert.Y)); } Polygon triangulatorPoly = new Polygon(points); //MAGIC :D Triangulator.Triangulate(triangulatorPoly); foreach (DelaunayTriangle tri in triangulatorPoly.Triangles) { CustomBlockData bd = new CustomBlockData(); bd.IsOneTriangle = true; bd.Texture = i.GetTexture(pair2.Value[0]); bd.Vertex1 = ConvertToVertexPosition(tri.Points[0], pair.Key, pair2.Key); bd.Vertex2 = ConvertToVertexPosition(tri.Points[1], pair.Key, pair2.Key); bd.Vertex3 = ConvertToVertexPosition(tri.Points[2], pair.Key, pair2.Key); Vector2[] uvs = new Vector2[]{ new Vector2(tri.Points[0].Xf, tri.Points[0].Yf), new Vector2(tri.Points[1].Xf, tri.Points[1].Yf), new Vector2(tri.Points[2].Xf, tri.Points[2].Yf) }; uvs = i.GetUVsForTriangle(uvs, pair2.Value[0]); bd.UV1 = uvs[0]; bd.UV2 = uvs[1]; bd.UV3 = uvs[2]; bd.Normal = pair.Key; datas.Add(bd); } } } } return datas; }
private static GpcPolygon gpc_polygon_ToPolygon(gpc_polygon gpc_polygon) { GpcPolygon polygon = new GpcPolygon(); polygon.NofContours = gpc_polygon.num_contours; polygon.ContourIsHole = new bool[polygon.NofContours]; polygon.Contour = new GpcVertexList[polygon.NofContours]; short[] holeShort = new short[polygon.NofContours]; IntPtr ptr = gpc_polygon.hole; if (holeShort.Length > 0) { Marshal.Copy(gpc_polygon.hole, holeShort, 0, polygon.NofContours); for (int i = 0; i < polygon.NofContours; i++) polygon.ContourIsHole[i] = (holeShort[i] != 0); ptr = gpc_polygon.contour; for (int i = 0; i < polygon.NofContours; i++) { gpc_vertex_list gpc_vtx_list = (gpc_vertex_list)Marshal.PtrToStructure(ptr, typeof(gpc_vertex_list)); polygon.Contour[i] = new GpcVertexList(); polygon.Contour[i].NofVertices = gpc_vtx_list.num_vertices; polygon.Contour[i].Vertex = new GpcVertex[polygon.Contour[i].NofVertices]; IntPtr ptr2 = gpc_vtx_list.vertex; for (int j = 0; j < polygon.Contour[i].NofVertices; j++) { gpc_vertex gpc_vtx = (gpc_vertex)Marshal.PtrToStructure(ptr2, typeof(gpc_vertex)); polygon.Contour[i].Vertex[j].X = gpc_vtx.x; polygon.Contour[i].Vertex[j].Y = gpc_vtx.y; ptr2 = (IntPtr)(((int)ptr2) + Marshal.SizeOf(gpc_vtx)); } ptr = (IntPtr)(((int)ptr) + Marshal.SizeOf(gpc_vtx_list)); } } return polygon; }
private static gpc_polygon PolygonTo_gpc_polygon(GpcPolygon polygon) { gpc_polygon gpc_pol = new gpc_polygon(); gpc_pol.num_contours = polygon.NofContours; int[] hole = new int[polygon.NofContours]; for (int i = 0; i < polygon.NofContours; i++) hole[i] = (polygon.ContourIsHole[i] ? 1 : 0); if (hole.Length > 0) { gpc_pol.hole = Marshal.AllocCoTaskMem(polygon.NofContours * Marshal.SizeOf(hole[0])); Marshal.Copy(hole, 0, gpc_pol.hole, polygon.NofContours); gpc_pol.contour = Marshal.AllocCoTaskMem(polygon.NofContours * Marshal.SizeOf(new gpc_vertex_list())); IntPtr ptr = gpc_pol.contour; for (int i = 0; i < polygon.NofContours; i++) { gpc_vertex_list gpc_vtx_list = new gpc_vertex_list(); gpc_vtx_list.num_vertices = polygon.Contour[i].NofVertices; gpc_vtx_list.vertex = Marshal.AllocCoTaskMem(polygon.Contour[i].NofVertices * Marshal.SizeOf(new gpc_vertex())); IntPtr ptr2 = gpc_vtx_list.vertex; for (int j = 0; j < polygon.Contour[i].NofVertices; j++) { gpc_vertex gpc_vtx = new gpc_vertex(); gpc_vtx.x = polygon.Contour[i].Vertex[j].X; gpc_vtx.y = polygon.Contour[i].Vertex[j].Y; Marshal.StructureToPtr(gpc_vtx, ptr2, false); ptr2 = (IntPtr)(((int)ptr2) + Marshal.SizeOf(gpc_vtx)); } Marshal.StructureToPtr(gpc_vtx_list, ptr, false); ptr = (IntPtr)(((int)ptr) + Marshal.SizeOf(gpc_vtx_list)); } } return gpc_pol; }
public static void SavePolygon(string filename, bool writeHoleFlags, GpcPolygon polygon) { gpc_polygon gpc_polygon = GpcWrapper.PolygonTo_gpc_polygon(polygon); IntPtr fp = fopen(filename, "wb"); gpc_write_polygon(fp, writeHoleFlags ? ((int)1) : ((int)0), ref gpc_polygon); fclose(fp); GpcWrapper.Free_gpc_polygon(gpc_polygon); }
public static GpcTristrip PolygonToTristrip(GpcPolygon polygon) { gpc_tristrip gpc_strip = new gpc_tristrip(); gpc_polygon gpc_pol = GpcWrapper.PolygonTo_gpc_polygon(polygon); gpc_polygon_to_tristrip(ref gpc_pol, ref gpc_strip); GpcTristrip tristrip = GpcWrapper.gpc_strip_ToTristrip(gpc_strip); GpcWrapper.Free_gpc_polygon(gpc_pol); GpcWrapper.gpc_free_tristrip(ref gpc_strip); return tristrip; }
public static GpcTristrip ClipToTristrip(GpcOperation operation, GpcPolygon subject_polygon, GpcPolygon clip_polygon) { gpc_tristrip gpc_strip = new gpc_tristrip(); gpc_polygon gpc_subject_polygon = GpcWrapper.PolygonTo_gpc_polygon(subject_polygon); gpc_polygon gpc_clip_polygon = GpcWrapper.PolygonTo_gpc_polygon(clip_polygon); gpc_tristrip_clip(operation, ref gpc_subject_polygon, ref gpc_clip_polygon, ref gpc_strip); GpcTristrip tristrip = GpcWrapper.gpc_strip_ToTristrip(gpc_strip); GpcWrapper.Free_gpc_polygon(gpc_subject_polygon); GpcWrapper.Free_gpc_polygon(gpc_clip_polygon); GpcWrapper.gpc_free_tristrip(ref gpc_strip); return tristrip; }
public static GpcPolygon Clip(GpcOperation operation, GpcPolygon subject_polygon, GpcPolygon clip_polygon) { gpc_polygon gpc_polygon = new gpc_polygon(); gpc_polygon gpc_subject_polygon = GpcWrapper.PolygonTo_gpc_polygon(subject_polygon); gpc_polygon gpc_clip_polygon = GpcWrapper.PolygonTo_gpc_polygon(clip_polygon); gpc_polygon_clip(operation, ref gpc_subject_polygon, ref gpc_clip_polygon, ref gpc_polygon); GpcPolygon polygon = GpcWrapper.gpc_polygon_ToPolygon(gpc_polygon); GpcWrapper.Free_gpc_polygon(gpc_subject_polygon); GpcWrapper.Free_gpc_polygon(gpc_clip_polygon); GpcWrapper.gpc_free_polygon(ref gpc_polygon); return polygon; }
public GpcTristrip ClipToTristrip(GpcOperation operation, GpcPolygon polygon) { return GpcWrapper.ClipToTristrip(operation, this, polygon); }