用Java创建图像凹面

时间:2015-01-20 00:10:39

标签: java concave

我有一个简单的问题,并想知道是否有人可以使用任何想法或库。我正在制作一个java游戏,需要将2d图像凹进去。问题是,1:我不知道如何使图像凹陷。 2:我认为凹面效果有点像后期过程,想想Oculus Rift。一切都很正常,但是玩家的相机会扭曲正常的2D图像看起来像3d。我是Sophmore,所以我不知道非常复杂的数学来完成这个。

谢谢, 蓝

1 个答案:

答案 0 :(得分:1)

如果您没有使用任何3D库或类似的东西,只需将其实现为简单的2D失真即可。只要它看起来不错,它就不必100%在数学上正确。您可以创建几个数组来存储位图的扭曲纹理坐标,这意味着您可以预先计算一次失真(这将是缓慢但只发生一次),然后使用预先计算的值渲染多次(会更快)。

这是一个使用幂公式生成失真场的简单函数。没有关于它的3D,它只是在图像的中心吮吸以呈现凹面外观:

int distortionU[][];
int distortionV[][];
public void computeDistortion(int width, int height)
{
    // this will be really slow but you only have to call it once:

    int halfWidth = width / 2;
    int halfHeight = height / 2;
    // work out the distance from the center in the corners:
    double maxDistance = Math.sqrt((double)((halfWidth * halfWidth) + (halfHeight * halfHeight)));

    // allocate arrays to store the distorted co-ordinates:
    distortionU = new int[width][height];
    distortionV = new int[width][height];

    for(int y = 0; y < height; y++)
    {
        for(int x = 0; x < width; x++)
        {
            // work out the distortion at this pixel:

            // find distance from the center:
            int xDiff = x - halfWidth;
            int yDiff = y - halfHeight;
            double distance = Math.sqrt((double)((xDiff * xDiff) + (yDiff * yDiff)));

            // distort the distance using a power function
            double invDistance = 1.0 - (distance / maxDistance);
            double distortedDistance = (1.0 - Math.pow(invDistance, 1.7)) * maxDistance;
            distortedDistance *= 0.7; // zoom in a little bit to avoid gaps at the edges

            // work out how much to multiply xDiff and yDiff by:
            double distortionFactor = distortedDistance / distance;
            xDiff = (int)((double)xDiff * distortionFactor);
            yDiff = (int)((double)yDiff * distortionFactor);

            // save the distorted co-ordinates
            distortionU[x][y] = halfWidth + xDiff;
            distortionV[x][y] = halfHeight + yDiff;

            // clamp
            if(distortionU[x][y] < 0)
                distortionU[x][y] = 0;
            if(distortionU[x][y] >= width)
                distortionU[x][y] = width - 1;
            if(distortionV[x][y] < 0)
                distortionV[x][y] = 0;
            if(distortionV[x][y] >= height)
                distortionV[x][y] = height - 1;
        }
    }
}

调用它一次传递要扭曲的位图的大小。您可以使用这些值或使用完全不同的公式来获得所需的效果。对pow()函数使用小于1的指数应该使图像具有凸面外观。

然后,当您渲染位图或将其复制到另一个位图时,请使用distortionU和distortionV中的值来扭曲位图,例如:

for(int y = 0; y < height; y++)
{
    for(int x = 0; x < width; x++)
    {
        // int pixelColor = bitmap.getPixel(x, y);  // gets undistorted value
        int pixelColor = bitmap.getPixel(distortionU[x][y], distortionV[x][y]);  // gets distorted value
        canvas.drawPixel(x + offsetX, y + offsetY, pixelColor);
    }
}

我不知道你在画布上绘制像素的实际功能是什么,上面只是伪代码。