使用 Canvas 创建 3D 立方体
Create 3D cube with Canvas
我有一个 2d 位图,我想将其转换为 3d 立方体(例如我的世界中的示例:)
我设法使用 "Camera" 在 3d space 中围绕图像旋转,但我不明白如何控制它或如何从中创建立方体,有人有想法吗?请注意我只能使用 canvas 而不能使用 OpenGL。
编辑:
这和我得到的一样接近:
使用此代码:
Matrix mMatrix = canvas.getMatrix();
canvas.save();
Camera camera=new Camera();
camera.save();
camera.rotateY(30);
camera.getMatrix(mMatrix);
mMatrix.preTranslate(-30, 0);
mMatrix.postTranslate(30, 0);
canvas.concat(mMatrix);
canvas.drawBitmap(b, 150, 150, null);
canvas.drawBitmap(b, 180, 180, null);
camera.restore();
canvas.restore();
canvas.save();
好的,因为 none 帮助了我,所以我寻找了另一种方法,并想到了一种可行的解决方法,它效率不高,并且在执行时可能会减慢程序速度,所以请三思在使用它之前。
我的做法是这样的:
首先,我在绘画中创建了一个立方体(可以是任何 3D 形状)
然后,我切割立方体的边并分别保存。
加载完这些图片后,剩下的就是代码:
public Bitmap CreateACube(Bitmap b2D){
Bitmap result=Bitmap.createBitmap(b2D);
/*loading sides of cube and painting texture on them*/
Bitmap top;
Bitmap left;
Bitmap front;
top=BitmapFactory.decodeResource(getResources(), R.drawable.top);
top=CubeCreator(top, b2D,"top");
left=BitmapFactory.decodeResource(getResources(), R.drawable.left);
left=CubeCreator(left, b2D,"left");
front=BitmapFactory.decodeResource(getResources(), R.drawable.front);
front=CubeCreator(front, b2D,"front");
Bitmap merge;
merge=overlay(top, left);//connecting all cube sides together into one bitmap
merge=overlay(merge, front);
result=Bitmap.createScaledBitmap(merge, merge.getWidth()*2, merge.getHeight()*2, false); //Scaling the result, you can remove if you don't want to.
return result;
}
private Bitmap CubeCreator(Bitmap srcBmp,Bitmap b2D,String s){
/*gets cube side bitmap, the texture bitmap, and a string of the side name*/
int width = srcBmp.getWidth();
int height = srcBmp.getHeight();
int width2=b2D.getWidth();
int height2=b2D.getHeight();
int rows1=0;
int rows2=0;
Bitmap dstBitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888);
/*Running on every pixel in the cube side*/
for (int row = 0; row < height; row++) {
rows1=++rows1%height2; //running on every pixel on the texture and reseting it if reached the last pixel
for (int col = 0; col < width; col++) {
rows2=++rows2%width2;
int pixel = srcBmp.getPixel(col, row);
int alpha = Color.alpha(pixel);
int dstColor=b2D.getPixel(rows2, rows1);
switch(s){//you can add more sides, I used 3
case "front":{
float[] hsv = new float[3];
int color = dstColor;
Color.colorToHSV(color, hsv);
hsv[2] *= 0.8f; // giving brightness to certain sides to make it look more 3D
dstColor = Color.HSVToColor(hsv);
break;
}
case "left":{
float[] hsv = new float[3];
int color = dstColor;
Color.colorToHSV(color, hsv);
hsv[2] *= 0.44f;
dstColor = Color.HSVToColor(hsv);
break;
}
case "top":{
float[] hsv = new float[3];
int color = dstColor;
Color.colorToHSV(color, hsv);
hsv[2] *= 1.2f;
dstColor = Color.HSVToColor(hsv);
break;
}
}
int pixel2=srcBmp.getPixel(col, row);
if(pixel2!= Color.TRANSPARENT)//checking if the current pixel of the side is not transparent
dstBitmap.setPixel(col, row, dstColor);
else{
dstBitmap.setPixel(col, row, pixel2);
}
}
}
return dstBitmap;
}
public static Bitmap overlay(Bitmap bmp1, Bitmap bmp2) {
/*connects two bitmaps together*/
Bitmap bmOverlay = Bitmap.createBitmap(bmp1.getWidth(), bmp1.getHeight(), bmp1.getConfig());
Canvas canvas = new Canvas(bmOverlay);
canvas.drawBitmap(bmp1, new Matrix(), null);
canvas.drawBitmap(bmp2, 0, 0, null);
return bmOverlay;
}
代码摘要: 我 运行 在立方体侧面(正面、左侧、顶部)的每个像素上,同时我也 运行 在纹理位图中的每个像素上,并使用纹理的像素为侧面像素着色。之后,我将所有彩色面连接到一张位图中,然后 return 它们。
结果:
我有一个 2d 位图,我想将其转换为 3d 立方体(例如我的世界中的示例:
我设法使用 "Camera" 在 3d space 中围绕图像旋转,但我不明白如何控制它或如何从中创建立方体,有人有想法吗?请注意我只能使用 canvas 而不能使用 OpenGL。
编辑:
这和我得到的一样接近:
使用此代码:
Matrix mMatrix = canvas.getMatrix();
canvas.save();
Camera camera=new Camera();
camera.save();
camera.rotateY(30);
camera.getMatrix(mMatrix);
mMatrix.preTranslate(-30, 0);
mMatrix.postTranslate(30, 0);
canvas.concat(mMatrix);
canvas.drawBitmap(b, 150, 150, null);
canvas.drawBitmap(b, 180, 180, null);
camera.restore();
canvas.restore();
canvas.save();
好的,因为 none 帮助了我,所以我寻找了另一种方法,并想到了一种可行的解决方法,它效率不高,并且在执行时可能会减慢程序速度,所以请三思在使用它之前。
我的做法是这样的:
首先,我在绘画中创建了一个立方体(可以是任何 3D 形状)
加载完这些图片后,剩下的就是代码:
public Bitmap CreateACube(Bitmap b2D){
Bitmap result=Bitmap.createBitmap(b2D);
/*loading sides of cube and painting texture on them*/
Bitmap top;
Bitmap left;
Bitmap front;
top=BitmapFactory.decodeResource(getResources(), R.drawable.top);
top=CubeCreator(top, b2D,"top");
left=BitmapFactory.decodeResource(getResources(), R.drawable.left);
left=CubeCreator(left, b2D,"left");
front=BitmapFactory.decodeResource(getResources(), R.drawable.front);
front=CubeCreator(front, b2D,"front");
Bitmap merge;
merge=overlay(top, left);//connecting all cube sides together into one bitmap
merge=overlay(merge, front);
result=Bitmap.createScaledBitmap(merge, merge.getWidth()*2, merge.getHeight()*2, false); //Scaling the result, you can remove if you don't want to.
return result;
}
private Bitmap CubeCreator(Bitmap srcBmp,Bitmap b2D,String s){
/*gets cube side bitmap, the texture bitmap, and a string of the side name*/
int width = srcBmp.getWidth();
int height = srcBmp.getHeight();
int width2=b2D.getWidth();
int height2=b2D.getHeight();
int rows1=0;
int rows2=0;
Bitmap dstBitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888);
/*Running on every pixel in the cube side*/
for (int row = 0; row < height; row++) {
rows1=++rows1%height2; //running on every pixel on the texture and reseting it if reached the last pixel
for (int col = 0; col < width; col++) {
rows2=++rows2%width2;
int pixel = srcBmp.getPixel(col, row);
int alpha = Color.alpha(pixel);
int dstColor=b2D.getPixel(rows2, rows1);
switch(s){//you can add more sides, I used 3
case "front":{
float[] hsv = new float[3];
int color = dstColor;
Color.colorToHSV(color, hsv);
hsv[2] *= 0.8f; // giving brightness to certain sides to make it look more 3D
dstColor = Color.HSVToColor(hsv);
break;
}
case "left":{
float[] hsv = new float[3];
int color = dstColor;
Color.colorToHSV(color, hsv);
hsv[2] *= 0.44f;
dstColor = Color.HSVToColor(hsv);
break;
}
case "top":{
float[] hsv = new float[3];
int color = dstColor;
Color.colorToHSV(color, hsv);
hsv[2] *= 1.2f;
dstColor = Color.HSVToColor(hsv);
break;
}
}
int pixel2=srcBmp.getPixel(col, row);
if(pixel2!= Color.TRANSPARENT)//checking if the current pixel of the side is not transparent
dstBitmap.setPixel(col, row, dstColor);
else{
dstBitmap.setPixel(col, row, pixel2);
}
}
}
return dstBitmap;
}
public static Bitmap overlay(Bitmap bmp1, Bitmap bmp2) {
/*connects two bitmaps together*/
Bitmap bmOverlay = Bitmap.createBitmap(bmp1.getWidth(), bmp1.getHeight(), bmp1.getConfig());
Canvas canvas = new Canvas(bmOverlay);
canvas.drawBitmap(bmp1, new Matrix(), null);
canvas.drawBitmap(bmp2, 0, 0, null);
return bmOverlay;
}
代码摘要: 我 运行 在立方体侧面(正面、左侧、顶部)的每个像素上,同时我也 运行 在纹理位图中的每个像素上,并使用纹理的像素为侧面像素着色。之后,我将所有彩色面连接到一张位图中,然后 return 它们。
结果: