我遇到了WriteableBitmap问题。我正在尝试渲染3d立方体。但是,当将像素写入WriteableBitmap时,其中的一部分就会移动。
初始化的多维数据集:
我已经用通常的Bitmap和SetPixel()方法测试了相同的点。这就是我将立方体沿三个轴沿45度旋转后得到的结果。我在这里看不到任何问题
我认为问题可能出在我的writeableBitmap像素设置算法上(也许是像素偏移问题?)。
具有灰色背景的第二张图片:
public WriteableBitmap DrawSceneByPoints(int width, int height, List<MPoint> points)
{
WriteableBitmap wBitmap = new WriteableBitmap(width, height, 96, 96, PixelFormats.Bgra32, null);
Int32Rect rect = new Int32Rect(0, 0, width, height);
var stride = (rect.Width * wBitmap.Format.BitsPerPixel + 7) / 8;
byte[] pixels = new byte[rect.Height * stride];
// For user: Moves 0,0 point from top-left to bottom-left
for (int i = 0; i < points.Count; ++i)
points[i].Y = height - points[i].Y;
int alpha = 255;
int red = 0;
int green = 0;
int blue = 0;
for (int i = 0; i < points.Count; ++i)
{
int pixelOffset = (int)(points[i].X + points[i].Y * wBitmap.PixelWidth) * wBitmap.Format.BitsPerPixel / 8;
pixels[pixelOffset] = (byte)blue;
pixels[pixelOffset + 1] = (byte)green;
pixels[pixelOffset + 2] = (byte)red;
pixels[pixelOffset + 3] = (byte)alpha;
}
wBitmap.WritePixels(rect, pixels, stride, 0);
return wBitmap;
}
public Bitmap DrawSceneByPointsBitmap(int width, int height, List<MPoint> points)
{
Bitmap bitmap = new Bitmap(width, height);
// For user: Moves 0,0 point from top-left to bottom-left
for (int i = 0; i < points.Count; ++i)
points[i].Y = height - points[i].Y;
for (int i = 0; i < points.Count; ++i)
bitmap.SetPixel((int)points[i].X, (int)points[i].Y, System.Drawing.Color.White);
return bitmap;
}
public WriteableBitmap Render()
{
new ShapeEditor().TransformShapes(Shapes, CurrentCamera);
List<MPoint> allPoints = GetAllPoints();
return new Painter().DrawSceneByPoints(this.Width, this.Height, allPoints);
}
class BresenhamLine : ILineRasterizer
{
public List<MPoint> GetLine(MPoint point1, MPoint point2)
{
return Bresenham3D((int)point1.X, (int)point1.Y, (int)point1.Z, (int)point2.X, (int)point2.Y, (int)point2.Z);
}
private List<MPoint> Bresenham3D(int x1, int y1, int z1, int x2, int y2, int z2)
{
var points = new List<MPoint>();
float x0 = x1, y0 = y1, z0 = z1;
int i, dx, dy, dz, l, m, n, x_inc, y_inc, z_inc, err_1, err_2, dx2, dy2, dz2;
int[] point = new int[3];
point[0] = x1;
point[1] = y1;
point[2] = z1;
dx = x2 - x1;
dy = y2 - y1;
dz = z2 - z1;
x_inc = (dx < 0) ? -1 : 1;
l = Math.Abs(dx);
y_inc = (dy < 0) ? -1 : 1;
m = Math.Abs(dy);
z_inc = (dz < 0) ? -1 : 1;
n = Math.Abs(dz);
dx2 = l << 1;
dy2 = m << 1;
dz2 = n << 1;
if ((l >= m) && (l >= n))
{
err_1 = dy2 - l;
err_2 = dz2 - l;
for (i = 0; i < l; i++)
{
points.Add(new MPoint(point[0], point[1], point[2]));
if (err_1 > 0)
{
point[1] += y_inc;
err_1 -= dx2;
}
if (err_2 > 0)
{
point[2] += z_inc;
err_2 -= dx2;
}
err_1 += dy2;
err_2 += dz2;
point[0] += x_inc;
}
}
else if ((m >= l) && (m >= n))
{
err_1 = dx2 - m;
err_2 = dz2 - m;
for (i = 0; i < m; i++)
{
points.Add(new MPoint(point[0], point[1], point[2]));
if (err_1 > 0)
{
point[0] += x_inc;
err_1 -= dy2;
}
if (err_2 > 0)
{
point[2] += z_inc;
err_2 -= dy2;
}
err_1 += dx2;
err_2 += dz2;
point[1] += y_inc;
}
}
else
{
err_1 = dy2 - n;
err_2 = dx2 - n;
for (i = 0; i < n; i++)
{
points.Add(new MPoint(point[0], point[1], point[2]));
if (err_1 > 0)
{
point[1] += y_inc;
err_1 -= dz2;
}
if (err_2 > 0)
{
point[0] += x_inc;
err_2 -= dz2;
}
err_1 += dy2;
err_2 += dx2;
point[2] += z_inc;
}
}
return points;
}
private void Swap<T>(ref T l, ref T r)
{
T temp = l;
l = r;
r = temp;
}
}
public List<MPoint> RasterizePolygon(MFacet triangle)
{
var points = new List<MPoint>();
Vector2 vertex0 = new Vector2(triangle.Vertices[0].X, triangle.Vertices[0].Y),
vertex1 = new Vector2(triangle.Vertices[1].X, triangle.Vertices[1].Y),
vertex2 = new Vector2(triangle.Vertices[2].X, triangle.Vertices[2].Y);
if (vertex0.Y == vertex1.Y && vertex0.Y == vertex2.Y) return new BresenhamLine().GetLine(triangle.Vertices[0], triangle.Vertices[2]);
// sort the vertices, vertex0, vertex1, vertex2 lower-to-upper
if (vertex0.Y > vertex1.Y) Swap(ref vertex0, ref vertex1);
if (vertex0.Y > vertex2.Y) Swap(ref vertex0, ref vertex2);
if (vertex1.Y > vertex2.Y) Swap(ref vertex1, ref vertex2);
int total_height = (int)(vertex2.Y - vertex0.Y);
for (int i = 0; i < total_height; i++)
{
bool second_half = i > vertex1.Y - vertex0.Y || vertex1.Y == vertex0.Y;
int segment_height = second_half ? (int)(vertex2.Y - vertex1.Y) : (int)(vertex1.Y - vertex0.Y);
float alpha = (float)i / total_height;
float beta = (float)(i - (second_half ? vertex1.Y - vertex0.Y : 0)) / segment_height; // be careful: with above conditions no division by zero here
Vector2 A = vertex0 + (vertex2 - vertex0) * alpha;
Vector2 B = second_half ? vertex1 + (vertex2 - vertex1) * beta : vertex0 + (vertex1 - vertex0) * beta;
if (A.X > B.X) Swap(ref A, ref B);
for (int j = (int)A.X; j <= B.X; j++)
{
points.Add(new MPoint(j, vertex0.Y + i, 1));
if (j > B.X || (A.X < vertex0.X && A.X < vertex1.X && A.X < vertex2.X))
Swap(ref vertex0, ref vertex0);
}
}
return points;
}
答案 0 :(得分:1)
我使用writeablebitmap将高程的2d数组转换为高度感图片。颜色代表高度。 我建议使用代表您的场景的2d数组,并对其进行迭代。 bgra32每个像素有4个字节。
WriteableBitmap WBM = new WriteableBitmap(width, height, 96, 96, PixelFormats.Bgra32, null);
byte[] pixels = new byte[width * height * 4];
double perColour = (double)(max - min) / 254d;
Color[] ca = Application.Current.Resources["HypsoColours"] as Color[];
int ix = 0;
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
int elv = elevations[x, y];
int eff = elv - min;
int ptr = 0;
if (eff> 0)
{
ptr = (int)((elv - min) / perColour);
}
Color colour = ca[ptr];
pixels[ix] = colour.B;
ix++;
pixels[ix] = colour.G;
ix++;
pixels[ix] = colour.R;
ix++;
pixels[ix] = 255;
ix++;
}
}
WBM.WritePixels(new Int32Rect(0, 0, width, height), pixels, width * 4, 0);
WBM.Freeze();
return WBM;