public static bool InTriangle(BarycentricPoint bc) { // Use int approximation to avoid floating point errors. int u = (int)bc.U * 100000; int v = (int)bc.V * 100000; return(u >= 0 && v >= 0 && u + v <= 100000); }
public static Point ToCartesian(BarycentricPoint bp, Point a, Point b, Point c) { double x = (a.X * bp.U) + (b.X * bp.V) + (c.X * bp.W); double y = (a.Y * bp.U) + (b.Y * bp.V) + (c.Y * bp.W); int ix = (int)x; int iy = (int)y; return(new Point(ix, iy)); }
public static BarycentricPoint ToBarycentric(Point p, Point a, Point b, Point c) { Point v0 = Subtract(b, a); Point v1 = Subtract(c, a); Point v2 = Subtract(p, a); double d00 = Dot(v0, v0); double d01 = Dot(v0, v1); double d11 = Dot(v1, v1); double d20 = Dot(v2, v0); double d21 = Dot(v2, v1); double denom = d00 * d11 - d01 * d01; BarycentricPoint bp = new BarycentricPoint(); bp.V = (d11 * d20 - d01 * d21) / denom; bp.W = (d00 * d21 - d01 * d20) / denom; bp.U = 1.0 - bp.V - bp.W; return(bp); }
public Bitmap BakeTextureMap() { var bitmap = new Bitmap(canvas.Width, canvas.Height); layers.Sort(); composed = 0; Rbx2Source.Print("Composing " + context + "..."); Rbx2Source.IncrementStack(); foreach (CompositData composit in layers) { var buffer = Graphics.FromImage(bitmap); var drawFlags = composit.DrawFlags; var canvas = composit.Rect; if (drawFlags.HasFlag(DrawFlags.Rect)) { if (drawFlags.HasFlag(DrawFlags.Color)) { composit.UseBrush(brush => buffer.FillRectangle(brush, canvas)); } else if (drawFlags.HasFlag(DrawFlags.Texture)) { Bitmap image = composit.GetTextureBitmap(); if (composit.FlipMode > 0) { image.RotateFlip(composit.FlipMode); } buffer.DrawImage(image, canvas); } } else if (drawFlags.HasFlag(DrawFlags.Guide)) { Mesh guide = composit.Guide; for (int face = 0; face < guide.NumFaces; face++) { Vertex[] verts = composit.GetGuideVerts(face); Point offset = canvas.Location; Point[] poly = verts .Select(vert => vert.ToPoint(canvas, offset)) .ToArray(); if (drawFlags.HasFlag(DrawFlags.Color)) { composit.UseBrush(brush => buffer.FillPolygon(brush, poly)); } else if (drawFlags.HasFlag(DrawFlags.Texture)) { Bitmap texture = composit.GetTextureBitmap(); Rectangle bbox = GetBoundingBox(poly); Point origin = bbox.Location; Bitmap drawLayer = new Bitmap(bbox.Width, bbox.Height); Point[] uv = verts .Select(vert => vert.ToUV(texture)) .ToArray(); int origin_X = origin.X, origin_Y = origin.Y; for (int x = bbox.Left; x < bbox.Right; x++) { for (int y = bbox.Top; y < bbox.Bottom; y++) { var pixel = new Point(x, y); var bcPoint = new BarycentricPoint(pixel, poly); if (bcPoint.InBounds()) { var uvPixel = bcPoint.ToCartesian(uv); Color color = texture.GetPixel(uvPixel.X, uvPixel.Y); drawLayer.SetPixel(x - origin_X, y - origin_Y, color); } } } buffer.DrawImage(drawLayer, origin); drawLayer.Dispose(); } } } Rbx2Source.Print("{0}/{1} layers composed...", ++composed, layers.Count); if (layers.Count > 2) { Rbx2Source.SetDebugImage(bitmap); } buffer.Dispose(); } Rbx2Source.Print("Done!"); Rbx2Source.DecrementStack(); return(bitmap); }
public Bitmap BakeTextureMap() { Bitmap bitmap = new Bitmap(canvas.Width, canvas.Height); layers.Sort(); composed = 0; Rbx2Source.Print("Composing " + context + "..."); Rbx2Source.IncrementStack(); foreach (CompositData composit in layers) { Graphics buffer = Graphics.FromImage(bitmap); DrawMode drawMode = composit.DrawMode; DrawType drawType = composit.DrawType; Rectangle compositCanvas = composit.Rect; if (drawMode == DrawMode.Rect) { if (drawType == DrawType.Color) { using (Brush brush = new SolidBrush(composit.DrawColor)) buffer.FillRectangle(brush, compositCanvas); } else if (drawType == DrawType.Texture) { Bitmap image = composit.GetTextureBitmap(); if (composit.FlipMode > 0) { image.RotateFlip(composit.FlipMode); } buffer.DrawImage(image, compositCanvas); } } else if (drawMode == DrawMode.Guide) { Mesh guide = composit.Guide; for (int face = 0; face < guide.FaceCount; face++) { Vertex[] verts = composit.GetGuideVerts(face); Point offset = compositCanvas.Location; Point vert_a = CompositUtil.VertexToPoint(verts[0], compositCanvas, offset); Point vert_b = CompositUtil.VertexToPoint(verts[1], compositCanvas, offset); Point vert_c = CompositUtil.VertexToPoint(verts[2], compositCanvas, offset); Point[] polygon = new Point[3] { vert_a, vert_b, vert_c }; if (drawType == DrawType.Color) { using (Brush brush = new SolidBrush(composit.DrawColor)) buffer.FillPolygon(brush, polygon); } else if (drawType == DrawType.Texture) { Bitmap texture = composit.GetTextureBitmap(); Rectangle bbox = CompositUtil.GetBoundingBox(vert_a, vert_b, vert_c); Point origin = bbox.Location; int width = bbox.Width; int height = bbox.Height; Bitmap drawLayer = new Bitmap(width, height); Point uv_a = CompositUtil.VertexToUV(verts[0], texture); Point uv_b = CompositUtil.VertexToUV(verts[1], texture); Point uv_c = CompositUtil.VertexToUV(verts[2], texture); for (int x = bbox.Left; x < bbox.Right; x++) { for (int y = bbox.Top; y < bbox.Bottom; y++) { Point pixel = new Point(x, y); BarycentricPoint bcPixel = CompositUtil.ToBarycentric(pixel, vert_a, vert_b, vert_c); if (CompositUtil.InTriangle(bcPixel)) { Point uvPixel = CompositUtil.ToCartesian(bcPixel, uv_a, uv_b, uv_c); Color color = texture.GetPixel(uvPixel.X, uvPixel.Y); drawLayer.SetPixel(x - origin.X, y - origin.Y, color); } } } buffer.DrawImage(drawLayer, origin); drawLayer.Dispose(); } } } Rbx2Source.Print("{0}/{1} layers composed...", ++composed, layers.Count); if (layers.Count > 2) { Rbx2Source.SetDebugImage(bitmap); } buffer.Dispose(); } Rbx2Source.Print("Done!"); Rbx2Source.DecrementStack(); return(bitmap); }