public bool EqualsID(BlockData bd) { if (bd == null) return false; return (ID == bd.ID); }
public bool EqualsFull(BlockData bd) { if (bd == null) return false; return (ID == bd.ID && Metadata == bd.Metadata); }
public static bool CanBuild(BlockData data, BlockData me) { if (_blocks[data.GetGlobalID()] == null) return true; if (_blocks[data.GetGlobalID()].IsTransparent()) { return (data.ID != me.ID); } return true; }
public virtual List<CustomBlockData> GenerateModel(byte metadata, BlockData me, BlockData Xpos, BlockData Xneg, BlockData Ypos, BlockData Yneg, BlockData Zpos, BlockData Zneg, BlockSource source, Point3 blockPosition) { return new List<CustomBlockData>(); }
public virtual List<CustomBlockData> GenerateSide(BlockSide side, byte metadata, BlockData me, BlockData Xpos, BlockData Xneg, BlockData Ypos, BlockData Yneg, BlockData Zpos, BlockData Zneg) { return new List<CustomBlockData>(); }
public bool Export(object arg, TaskProgressReport p) { int maxTotalTask = 8; //6 normals + geom build + file write int currentTotalTask = 0; PartTaskProgressReport rep = (PartTaskProgressReport)p; rep.SetTitle("Preparing input data"); rep.Report(); Dictionary<Vector4, BlockRange[]> ranges = new Dictionary<Vector4, BlockRange[]>(); List<CustomBlockData> customData = new List<CustomBlockData>(); Vector3[] normalsToFollow = 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) }; bool[, ,] customBuilt = new bool[_in.BlockIDs.GetLength(0), _in.BlockIDs.GetLength(1), _in.BlockIDs.GetLength(2)]; for (int n = 0; n < normalsToFollow.Length; n++) { Vector3 normal = normalsToFollow[n]; BlockSide normalSide = Block.GetSideFromNormal(normal); Vector2 xy = GetXYByNormal(normal); Point3 xyLength = GetLengthAxisByNormal(normal); //X:x, Y:y, Z:level int xs = _in.BlockIDs.GetLength(xyLength.X); int ys = _in.BlockIDs.GetLength(xyLength.Y); int zs = _in.BlockIDs.GetLength(xyLength.Z); rep.SetTitle("Processing side: " + TranslateNormal(normal)); rep.Report(); for (int lvl = 0; lvl < _in.BlockIDs.GetLength(xyLength.Z); lvl++) { BlockData[,] lvlData = new BlockData[xs, ys]; int partMax = xs * ys; int partProg = 0; for (int a = 0; a < _in.BlockIDs.GetLength(xyLength.X); a++) { for (int b = 0; b < _in.BlockIDs.GetLength(xyLength.Y); b++) { Point3 pos = ConvertLevelAndXYToPos(a, b, lvl, xyLength); if (_in.BlockIDs[pos.X, pos.Y, pos.Z] != 0) { BlockData bd = GetBlockDataAt(pos); uint block = bd.GetGlobalID(); Block bl = Block.Blocks[block]; if (bl != null && !customBuilt[pos.X, pos.Y, pos.Z]) { bool canExportFace = (!_cfg.DontExportOuterFaces && !_cfg.InteriorOnly); if (_cfg.DontExportOuterFaces && CheckFace(pos, normal)) canExportFace = true; else if (_cfg.InteriorOnly && CheckFaceInterior(pos, normal)) canExportFace = true; if (canExportFace) { if (bl.IsFullyCustomModel()) { List<CustomBlockData> dat = bl.GenerateModel(_in.BlockMetadatas[pos.X, pos.Y, pos.Z], bd, GetBlockDataAt(new Point3(pos.X + 1, pos.Y, pos.Z)), GetBlockDataAt(new Point3(pos.X - 1, pos.Y, pos.Z)), GetBlockDataAt(new Point3(pos.X, pos.Y + 1, pos.Z)), GetBlockDataAt(new Point3(pos.X, pos.Y - 1, pos.Z)), GetBlockDataAt(new Point3(pos.X, pos.Y, pos.Z + 1)), GetBlockDataAt(new Point3(pos.X, pos.Y, pos.Z - 1)), this, pos); for (int x = 0; x < dat.Count; x++) { dat[x].Vertex1 += pos.ToVector3(); dat[x].Vertex2 += pos.ToVector3(); dat[x].Vertex3 += pos.ToVector3(); if (!dat[x].IsOneTriangle) dat[x].Vertex4 += pos.ToVector3(); dat[x].Source = bd; } customData.AddRange(dat); customBuilt[pos.X, pos.Y, pos.Z] = true; } else { if (bl.IsFullSide(normalSide)) { if (CanGenerateSide(pos, normal)) { lvlData[a, b] = bd; } } else { List<CustomBlockData> dat = bl.GenerateSide(normalSide, _in.BlockMetadatas[pos.X, pos.Y, pos.Z], bd, GetBlockDataAt(new Point3(pos.X + 1, pos.Y, pos.Z)), GetBlockDataAt(new Point3(pos.X - 1, pos.Y, pos.Z)), GetBlockDataAt(new Point3(pos.X, pos.Y + 1, pos.Z)), GetBlockDataAt(new Point3(pos.X, pos.Y - 1, pos.Z)), GetBlockDataAt(new Point3(pos.X, pos.Y, pos.Z + 1)), GetBlockDataAt(new Point3(pos.X, pos.Y, pos.Z - 1))); for (int x = 0; x < dat.Count; x++) { dat[x].Vertex1 += pos.ToVector3(); dat[x].Vertex2 += pos.ToVector3(); dat[x].Vertex3 += pos.ToVector3(); if (!dat[x].IsOneTriangle) dat[x].Vertex4 += pos.ToVector3(); dat[x].Source = bd; } customData.AddRange(dat); } } } } } partProg++; rep.SetPartPercent((int)(((float)partProg / (float)partMax) * 100f)); rep.Report(); } } rep.SetTitle("Square-angulating level: " + lvl.ToString()); rep.Report(); if (_cfg.OptimizeModel) { List<BlockRange> sq = Squareangulate(lvlData); if (sq.Count > 0) { ranges.Add(new Vector4(normal.X, normal.Y, normal.Z, lvl), sq.ToArray()); } } else { List<BlockRange> converted = new List<BlockRange>(); for (int x = 0; x < lvlData.GetLength(0); x++) { for (int y = 0; y < lvlData.GetLength(1); y++) { BlockData bd = lvlData[x, y]; if (bd == null) continue; BlockRange range = new BlockRange(); range.Block = bd; range.From = new PointF(x, y); range.To = new PointF(x, y); converted.Add(range); } } ranges.Add(new Vector4(normal.X, normal.Y, normal.Z, lvl), converted.ToArray()); } } currentTotalTask++; rep.SetTotalPercent((int)(((float)currentTotalTask / (float)maxTotalTask) * 100f)); rep.Report(); } rep.SetTitle("Building geometry"); rep.Report(); Dictionary<string, DataSet> datas = new Dictionary<string, DataSet>(); int pairIndex = 0; foreach (KeyValuePair<Vector4, BlockRange[]> pair in ranges) { Vector3 normal = new Vector3(pair.Key.X, pair.Key.Y, pair.Key.Z); int level = (int)pair.Key.Level; Vector3 addNormal = new Vector3(normal.X, normal.Y, normal.Z); if (addNormal.X < 0) addNormal.X = 0; if (addNormal.Y < 0) addNormal.Y = 0; if (addNormal.Z < 0) addNormal.Z = 0; for (int x = 0; x < pair.Value.Length; x++) { WriteRange(pair.Value[x], normal, level, addNormal, ref datas); } pairIndex++; rep.SetTotalPercent((int)(((float)pairIndex / (float)ranges.Count) * 100f)); rep.Report(); } for (int x = 0; x < customData.Count; x++) { WriteCustomData(customData[x], ref datas); } rep.SetTotalPercent(100); rep.Report(); if (_cfg.CenterObject) { rep.SetTitle("Centering geometry"); rep.Report(); Vector3 min = new Vector3(0, 0, 0); Vector3 max = new Vector3(0, 0, 0); foreach (KeyValuePair<string, DataSet> pair2 in datas) { foreach (Vector3 v in pair2.Value.verts) { min.X = Math.Min(min.X, v.X); min.Y = Math.Min(min.Y, v.Y); min.Z = Math.Min(min.Z, v.Z); max.X = Math.Max(max.X, v.X); max.Y = Math.Max(max.Y, v.Y); max.Z = Math.Max(max.Z, v.Z); } } Vector3 move = (max - min) / 2; foreach (KeyValuePair<string, DataSet> pair2 in datas) { for (int x = 0; x < pair2.Value.verts.Count; x++) { pair2.Value.verts[x] -= move; } } } currentTotalTask++; rep.SetTotalPercent((int)(((float)currentTotalTask / (float)maxTotalTask) * 100f)); rep.SetTitle("Creating vertex data"); rep.Report(); ProcessedGeometryData geom = new ProcessedGeometryData(); geom.ExportConfig = _cfg; geom.Data = datas.Values.ToList(); //Export model file _outputWriter.Write(_outputFile, geom); //Export textures if (_cfg.ExportTextures) { rep.SetTitle("Exporting textures"); rep.Report(); List<string> failedTextures = new List<string>(); string textureOutput = Path.Combine(Path.GetDirectoryName(_outputFile), _cfg.TextureOutputFolder); ResourcePack rs = new ResourcePack(_cfg.ResourcePack); rs.Open(); foreach (KeyValuePair<string, DataSet> pair2 in datas) { string tex = pair2.Value.Texture; if (!rs.SaveBlockTexture(tex, textureOutput)) failedTextures.Add(tex); } rs.Close(); } currentTotalTask++; rep.SetTotalPercent((int)(((float)currentTotalTask / (float)maxTotalTask) * 100f)); return true; }
public static bool IsTransparent(BlockData data) { if (_blocks[data.GetGlobalID()] == null) return true; return _blocks[data.GetGlobalID()].IsTransparent(); }
private List<BlockRange> Squareangulate(BlockData[,] data) { List<BlockRange> ql = new List<BlockRange>(); Dictionary<Tuple<uint, Byte>, BlockData[,]> types = CollectTypes(data); foreach (KeyValuePair<Tuple<uint, Byte>, BlockData[,]> pair in types) { BlockData[,] levelData = pair.Value; int rem = CountRem(levelData); if (rem > 0) { bool[,] proc = new bool[levelData.GetLength(0), levelData.GetLength(1)]; while (rem > 0) { Point s = FindStart(levelData, proc); if (s.X == -1 && s.Y == -1) break; Find(ref ql, ref levelData, ref proc, s, ref rem, levelData[s.X, s.Y]); } } } return ql; }
private Point FindStart(BlockData[,] grid, bool[,] exclude) { Point s = new Point(-1, -1); for (int y = 0; y < grid.GetLength(1); y++) for (int x = 0; x < grid.GetLength(0); x++) { if (grid[x, y] != null && !exclude[x, y]) return new Point(x, y); } return s; }
private void Find(ref List<BlockRange> ql, ref BlockData[,] oData, ref bool[,] proc, Point s, ref int remains, BlockData data) { //Find square int fsx = 0; int fsy = 0; bool find = true; bool b1 = false; bool b2 = false; while (find) { if (!b1 && s.X + fsx + 1 < oData.GetLength(0) && s.Y + fsy < oData.GetLength(1) && oData[s.X + fsx + 1, s.Y + fsy] != null && !proc[s.X + fsx + 1, s.Y + fsy]) { bool canAdd = true; for (int cx = s.X; cx <= s.X + fsx + 1; cx++) { for (int cy = s.Y; cy <= s.Y + fsy; cy++) { if (oData[cx, cy] == null || proc[cx, cy]) { canAdd = false; break; } } } if (canAdd) fsx++; else b1 = true; } else b1 = true; if (!b2 && s.X + fsx < oData.GetLength(0) && s.Y + fsy + 1 < oData.GetLength(1) && oData[s.X + fsx, s.Y + fsy + 1] != null && !proc[s.X + fsx, s.Y + fsy + 1]) { bool canAdd = true; for (int cy = s.Y; cy <= s.Y + fsy + 1; cy++) { for (int cx = s.X; cx <= s.X + fsx; cx++) { if (oData[cx, cy] == null || proc[cx, cy]) { canAdd = false; break; } } } if (canAdd) fsy++; else b2 = true; } else b2 = true; if (b1 && b2) { find = false; BlockRange br = new BlockRange(); br.From = s; br.To = new Point(s.X + fsx, s.Y + fsy); br.Block = data; ql.Add(br); for (int rx = s.X; rx <= br.To.X; rx++) for (int ry = s.Y; ry <= br.To.Y; ry++) { remains--; proc[rx, ry] = true; } } } }
private int CountRem(BlockData[,] datas) { int r = 0; for (int x = 0; x < datas.GetLength(0); x++) for (int y = 0; y < datas.GetLength(1); y++) if (datas[x, y] != null) r++; return r; }
private Dictionary<Tuple<uint, byte>, BlockData[, ]> CollectTypes(BlockData[,] source) { //ID, META : Level data Dictionary<Tuple<uint, byte>, BlockData[,]> dat = new Dictionary<Tuple<uint, byte>, BlockData[,]>(); for (int x = 0; x < source.GetLength(0); x++) { for (int y = 0; y < source.GetLength(1); y++) { BlockData d = source[x, y]; if (d != null) { Tuple<uint, byte> nd = new Tuple<uint, byte>(d.ID, d.Metadata); if (!dat.ContainsKey(nd)) { dat.Add(nd, new BlockData[source.GetLength(0), source.GetLength(1)]); } dat[nd][x, y] = d; } } } return dat; }