public override List<CustomBlockData> GenerateModel(byte metadata, BlockData me, BlockData Xpos, BlockData Xneg, BlockData Ypos, BlockData Yneg, BlockData Zpos, BlockData Zneg, BlockSource source, Point3 blockPosition) { bool upsideDown = IsUpsideDown(metadata); List<BoundingBox> boxesToExport = new List<BoundingBox>(); byte direction = GetType(metadata); float bottomBasePos = (upsideDown ? 0.5f : 0f); float topBasePos = (upsideDown ? 0f : 0.5f); boxesToExport.Add(new BoundingBox(new Vector3(0, bottomBasePos, 0), new Vector3(1, bottomBasePos + 0.5f, 1))); //Collect data from environment Vector3 descendingDir = MetaToDirection(direction); Vector3 rightFloatDir = Vector3.TransformNormal(descendingDir, Matrix.CreateRotationY((float)Math.PI / 2)); rightFloatDir.X = (float)Math.Round(rightFloatDir.X, 4); rightFloatDir.Z = (float)Math.Round(rightFloatDir.Z, 4); //Fix small numbers Point3 facingDir = descendingDir.ToPoint3(); Point3 rightDir = rightFloatDir.ToPoint3(); BlockData frontBlock = source.GetData(blockPosition + facingDir); BlockData backBlock = source.GetData(blockPosition - facingDir); BlockData rightBlock = source.GetData(blockPosition + rightDir); BlockData leftBlock = source.GetData(blockPosition - rightDir); bool renderBaseStep = true; int littleCornerModel = -1; //Check if we need to make a corner { if (IsStairs(frontBlock)) { if (IsLeft(me.Metadata, frontBlock.Metadata)) { bool leftOk = (IsStairs(leftBlock) && me.Metadata == leftBlock.Metadata); bool rightOk = (IsStairs(rightBlock) && me.Metadata == rightBlock.Metadata); if ((leftOk && !rightOk) || (!leftOk && rightOk)) { int frontLittleStep = -1; { Point3 frontPos = blockPosition + facingDir; BlockData me2 = source.GetData(frontPos); byte direction2 = GetType(me2.Metadata); Vector3 descendingDir2 = MetaToDirection(direction2); Vector3 rightFloatDir2 = Vector3.TransformNormal(descendingDir2, Matrix.CreateRotationY((float)Math.PI / 2)); rightFloatDir2.X = (float)Math.Round(rightFloatDir2.X, 4); rightFloatDir2.Z = (float)Math.Round(rightFloatDir2.Z, 4); //Fix small numbers Point3 facingDir2 = descendingDir2.ToPoint3(); Point3 rightDir2 = rightFloatDir2.ToPoint3(); BlockData backBlock2 = source.GetData(frontPos - facingDir2); BlockData rightBlock2 = source.GetData(frontPos + rightDir2); BlockData leftBlock2 = source.GetData(frontPos - rightDir2); frontLittleStep = CheckLittleCorner(me2, backBlock2, leftBlock2, rightBlock2, direction2); } if (frontLittleStep == -1) { switch (direction) { case 0: if (leftOk) littleCornerModel = 2; else littleCornerModel = 1; break; case 1: if (leftOk) littleCornerModel = 0; else littleCornerModel = 3; break; case 2: if (leftOk) littleCornerModel = 1; else littleCornerModel = 0; break; case 3: if (leftOk) littleCornerModel = 3; else littleCornerModel = 2; break; } } } } } } //Check if we need to make a small corner if (littleCornerModel == -1) //It's not a corner so maybe.. { littleCornerModel = CheckLittleCorner(me, backBlock, leftBlock, rightBlock, direction); renderBaseStep = (littleCornerModel == -1); } if (littleCornerModel != -1) { switch (littleCornerModel) { case 0: boxesToExport.Add(new BoundingBox(new Vector3(.5f, topBasePos, 0), new Vector3(1f, topBasePos + 0.5f, .5f))); break; case 1: boxesToExport.Add(new BoundingBox(new Vector3(0, topBasePos, 0), new Vector3(.5f, topBasePos + 0.5f, .5f))); break; case 2: boxesToExport.Add(new BoundingBox(new Vector3(0, topBasePos, 0.5f), new Vector3(.5f, topBasePos + 0.5f, 1))); break; case 3: boxesToExport.Add(new BoundingBox(new Vector3(.5f, topBasePos, .5f), new Vector3(1f, topBasePos + 0.5f, 1f))); break; } } if (renderBaseStep) { switch (direction) //Ascending... { case 0: //east = +X boxesToExport.Add(new BoundingBox(new Vector3(.5f, topBasePos, 0), new Vector3(1f, topBasePos + 0.5f, 1))); break; case 1: //west = -X boxesToExport.Add(new BoundingBox(new Vector3(0, topBasePos, 0), new Vector3(.5f, topBasePos + 0.5f, 1))); break; case 2: //south = +Z boxesToExport.Add(new BoundingBox(new Vector3(0, topBasePos, 0.5f), new Vector3(1f, topBasePos + 0.5f, 1))); break; case 3: //north = -Z boxesToExport.Add(new BoundingBox(new Vector3(0, topBasePos, 0), new Vector3(1f, topBasePos + 0.5f, .5f))); break; } } return GeometryGenerator.GenerateModel(boxesToExport, source, blockPosition, true, this); }
/// <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; }
public override List<CustomBlockData> GenerateModel(byte metadata, BlockData me, BlockData Xpos, BlockData Xneg, BlockData Ypos, BlockData Yneg, BlockData Zpos, BlockData Zneg, BlockSource source, Point3 blockPosition) { List<CustomBlockData> mdl = new List<CustomBlockData>(); bool zPos = Zpos.IsSolid || Zpos.ID == me.ID; bool zNeg = Zneg.IsSolid || Zneg.ID == me.ID; bool xPos = Xpos.IsSolid || Xpos.ID == me.ID; bool xNeg = Xneg.IsSolid || Xneg.ID == me.ID; float xStart = 0; float xEnd = 1; float zStart = 0; float zEnd = 1; if (!xPos && xNeg) { xStart = 0; xEnd = 0.5f; } else if (xPos && !xNeg) { xStart = .5f; xEnd = 1; } else if (xPos && xNeg) { xStart = 0; xEnd = 1; } else if (!xPos && !xNeg) { xStart = 0; xEnd = 0; } if (!zPos && zNeg) { zStart = 0; zEnd = 0.5f; } else if (zPos && !zNeg) { zStart = .5f; zEnd = 1; } else if (zPos && zNeg) { zStart = 0; zEnd = 1; } else if (!zPos && !zNeg) { zStart = 0; zEnd = 0; } if (!zPos && !zNeg && !xPos && !xNeg) { xStart = 0; xEnd = 1; zStart = 0; zEnd = 1; } #region X sides if (xStart != 0 || xEnd != 0) { mdl.Add(new CustomBlockData() { Vertex1 = new Vector3(xStart, 0, .5f), Vertex2 = new Vector3(xStart, 1, .5f), Vertex3 = new Vector3(xEnd, 1, .5f), Vertex4 = new Vector3(xEnd, 0, .5f), Normal = new Vector3(1, 0, 0), Texture = _tex }.CreateUVsRotated90(xStart, 0, xEnd, 1)); mdl.Add(new CustomBlockData() { Vertex1 = new Vector3(xStart, 0, .5f), Vertex2 = new Vector3(xStart, 1, .5f), Vertex3 = new Vector3(xEnd, 1, .5f), Vertex4 = new Vector3(xEnd, 0, .5f), Normal = new Vector3(1, 0, 0), TriFlip = true, Texture = _tex }.CreateUVsRotated90(xStart, 0, xEnd, 1)); if (!source.GetData(new Point3(blockPosition.X, blockPosition.Y + 1, blockPosition.Z)).EqualsID(me)) { mdl.Add(new CustomBlockData() { Vertex1 = new Vector3(xStart, 0.99f, 0.45f), Vertex2 = new Vector3(xEnd, 0.99f, 0.45f), Vertex3 = new Vector3(xEnd, 0.99f, .55f), Vertex4 = new Vector3(xStart, 0.99f, .55f), Normal = new Vector3(0, 1, 0), UV1 = new Vector2(.45f, 0), UV2 = new Vector2(.45f, 1), UV3 = new Vector2(.55f, 1), UV4 = new Vector2(.55f, 0), Texture = _tex }); } if (!source.GetData(new Point3(blockPosition.X, blockPosition.Y - 1, blockPosition.Z)).EqualsID(me)) { mdl.Add(new CustomBlockData() { Vertex1 = new Vector3(xStart, 0.01f, 0.45f), Vertex2 = new Vector3(xEnd, 0.01f, 0.45f), Vertex3 = new Vector3(xEnd, 0.01f, .55f), Vertex4 = new Vector3(xStart, 0.01f, .55f), Normal = new Vector3(0, 1, 0), UV1 = new Vector2(.45f, 0), UV2 = new Vector2(.45f, 1), UV3 = new Vector2(.55f, 1), UV4 = new Vector2(.55f, 0), Texture = _tex }); } if (xPos && !xNeg) { mdl.Add(new CustomBlockData() { Vertex1 = new Vector3(.5f, 0, .45f), Vertex2 = new Vector3(.5f, .99f, .45f), Vertex3 = new Vector3(.5f, .99f, .55f), Vertex4 = new Vector3(.5f, 0, .55f), Normal = new Vector3(1, 0, 0), UV1 = new Vector2(.45f, 0), UV2 = new Vector2(.45f, 1), UV3 = new Vector2(.55f, 1), UV4 = new Vector2(.55f, 0), Texture = _texY }); } else if (!xPos && xNeg) { mdl.Add(new CustomBlockData() { Vertex1 = new Vector3(.5f, 0, .45f), Vertex2 = new Vector3(.5f, .99f, .45f), Vertex3 = new Vector3(.5f, .99f, .55f), Vertex4 = new Vector3(.5f, 0, .55f), Normal = new Vector3(1, 0, 0), UV1 = new Vector2(.45f, 0), UV2 = new Vector2(.45f, 1), UV3 = new Vector2(.55f, 1), UV4 = new Vector2(.55f, 0), Texture = _texY }); } } #endregion #region Z sides if (zStart != 0 || zEnd != 0) { mdl.Add(new CustomBlockData() { Vertex1 = new Vector3(.5f, 0, zStart), Vertex2 = new Vector3(.5f, 1, zStart), Vertex3 = new Vector3(.5f, 1, zEnd), Vertex4 = new Vector3(.5f, 0, zEnd), Normal = new Vector3(0, 0, 1), Texture = _tex }.CreateUVsRotated90(zStart, 0, zEnd, 1)); mdl.Add(new CustomBlockData() { Vertex1 = new Vector3(.5f, 0, zStart), Vertex2 = new Vector3(.5f, 1, zStart), Vertex3 = new Vector3(.5f, 1, zEnd), Vertex4 = new Vector3(.5f, 0, zEnd), Normal = new Vector3(0, 0, 1), TriFlip = true, Texture = _tex }.CreateUVsRotated90(zStart, 0, zEnd, 1)); if (!source.GetData(new Point3(blockPosition.X, blockPosition.Y + 1, blockPosition.Z)).EqualsID(me)) { mdl.Add(new CustomBlockData() { Vertex1 = new Vector3(.45f, 1, zStart), Vertex2 = new Vector3(.45f, 1, zEnd), Vertex3 = new Vector3(.55f, 1, zEnd), Vertex4 = new Vector3(.55f, 1, zStart), Normal = new Vector3(0, 1, 0), UV1 = new Vector2(.45f, zStart), UV2 = new Vector2(.45f, zEnd), UV3 = new Vector2(.55f, zEnd), UV4 = new Vector2(.55f, zStart), Texture = _tex }); } if (!source.GetData(new Point3(blockPosition.X, blockPosition.Y - 1, blockPosition.Z)).EqualsID(me)) { mdl.Add(new CustomBlockData() { Vertex1 = new Vector3(.45f, 0, zStart), Vertex2 = new Vector3(.45f, 0, zEnd), Vertex3 = new Vector3(.55f, 0, zEnd), Vertex4 = new Vector3(.55f, 0, zStart), Normal = new Vector3(0, 1, 0), UV1 = new Vector2(.45f, zStart), UV2 = new Vector2(.45f, zEnd), UV3 = new Vector2(.55f, zEnd), UV4 = new Vector2(.55f, zStart), Texture = _tex }); } if (zPos && !zNeg) { mdl.Add(new CustomBlockData() { Vertex1 = new Vector3(.45f, 0, .5f), Vertex2 = new Vector3(.45f, 1, .5f), Vertex3 = new Vector3(.55f, 1, .5f), Vertex4 = new Vector3(.55f, 0, .5f), Normal = new Vector3(1, 0, 0), UV1 = new Vector2(.45f, 0), UV2 = new Vector2(.45f, 1), UV3 = new Vector2(.55f, 1), UV4 = new Vector2(.55f, 0), Texture = _texY }); } else if (!zPos && zNeg) { mdl.Add(new CustomBlockData() { Vertex1 = new Vector3(.45f, 0, .5f), Vertex2 = new Vector3(.45f, 1, .5f), Vertex3 = new Vector3(.55f, 1, .5f), Vertex4 = new Vector3(.55f, 0, .5f), Normal = new Vector3(1, 0, 0), UV1 = new Vector2(.45f, 0), UV2 = new Vector2(.45f, 1), UV3 = new Vector2(.55f, 1), UV4 = new Vector2(.55f, 0), Texture = _texY }); } } #endregion return mdl; }