Math 从二维点计算单位球体上的三维坐标

Math 从二维点计算单位球体上的三维坐标,math,graphics,geometry,Math,Graphics,Geometry,我有一个圆形的正方形位图,我想计算该圆形中所有像素的法线,就像它是半径为1的球体一样: 球体/圆在位图中居中 这个方程是什么?很明显,由于缺少维度,你只能假设所有的点都在球体的一半或类似的地方。除此之外,这很简单 圆的中间有一个精确向内或向外的法线,垂直于绘制圆的平面 圆边上的每个点都背向中间,因此可以计算该点的法线 对于中间和边缘之间的任何一点,你都可以使用到中间的距离,以及一些简单的三角(我现在不知道)。lerp在某些点上大致准确,但并不完全符合您的需要,因为它是一条曲线。虽然是简单的曲线

我有一个圆形的正方形位图,我想计算该圆形中所有像素的法线,就像它是半径为1的球体一样:

球体/圆在位图中居中


这个方程是什么?

很明显,由于缺少维度,你只能假设所有的点都在球体的一半或类似的地方。除此之外,这很简单

圆的中间有一个精确向内或向外的法线,垂直于绘制圆的平面

圆边上的每个点都背向中间,因此可以计算该点的法线


对于中间和边缘之间的任何一点,你都可以使用到中间的距离,以及一些简单的三角(我现在不知道)。lerp在某些点上大致准确,但并不完全符合您的需要,因为它是一条曲线。虽然是简单的曲线,但你知道起始值和结束值,所以计算它们只需要一个简单的等式。

我想我得到了你想要做的:为图像生成深度数据网格。有点像光线跟踪球体

在这种情况下,需要进行光线-球体相交测试:

基于U/V坐标(乘以2,因为球体的直径为2),光线将是简单的垂直光线。这将为您提供球体上的前向点

从这里开始,按如下方式计算法线(
点-原点
,半径已经是1个单位)

从上面的链接中删除:

您必须组合两个方程式:

  • 射线:R(t)=R0+t*Rd,t>0,其中R0=[X0,Y0,Z0]和Rd=[Xd,Yd,Zd]
  • Sphere:S=点集[xs,ys,zs],其中(xs-xc)2+(ys-yc)2+(zs-zc)2=Sr2
为此,请计算光线(x*像素/宽度,y*像素/宽度,z:1),然后:

  • A=Xd^2+Yd^2+Zd^2
  • B=2*(Xd*(X0-Xc)+Yd*(Y0-Yc)+Zd*(Z0-Zc))
  • C=(X0-Xc)^2+(Y0-Yc)^2+(Z0-Zc)^2-Sr^2
插入二次方程:

  • t0,t1=(-B+(B^2-4*C)^1/2)/2
检查判别式(B^2-4*C),如果为实根,则交点为:

  • Ri=[xi,yi,zi]=[x0+xd*ti,y0+yd*ti,z0+zd*ti]
曲面法线为:

  • SN=[(xi-xc)/Sr,(yi-yc)/Sr,(zi-zc)/Sr]
将其全部煮沸:

因此,由于我们讨论的是单位值,以及直接指向
Z
(没有x或y分量)的光线,我们可以将这些方程大大简化:

雷:

  • X0=2*像素x/宽度
    Y0=2*像素/高度
    Z0=0

  • Xd=0
    Yd=0
    Zd=1

球体:

  • Xc=1
    Yc=1
    Zc=1
因素:

  • A=1(单位射线)
  • B
    =2*(0+0+(0-1))
    =-2(无x/y分量)
  • C
    =(X0-1)^2+(Y0-1)^2+(0-1)^2-1
    =(X0-1)^2+(Y0-1)^2

  • 判别式
    =(-2)^2-4*1*C
    =4-4*C

从这里开始:

If discriminant < 0:
  Z = ?, Normal = ?
Else:
  t = (2 + (discriminant) ^ 1 / 2) / 2
If t < 0 (hopefully never or always the case)
  t = -t
如果判别式<0:
Z=?,正常=?
其他:
t=(2+(判别式)^1/2)/2
如果t<0(希望从未或始终如此)
t=-t
然后:

  • Z:t
  • 席:1—BR> 纽约:易-1
    新西兰:t-1
煮得更远:


直观地看,它看起来像C(
X^2+Y^2
),平方根是这里最突出的数字。如果我对我的数学有更好的记忆(特别是对和的指数的变换),那么我敢打赌我可以把它归结为Tom Zych给你的。既然我不能,我就把它放在上面。

我不太了解人们是如何编程3D东西的,所以我只讲纯粹的数学,希望它有用

以原点为中心的半径为1的球体是满足以下条件的点集:

x2+y2+z2=1

我们需要球体上x和y已知的点的三维坐标。所以,只需求解z:

z=±sqrt(1-x2-y2)

现在,让我们考虑从球面向外指向的单位向量。它是一个单位球体,所以我们可以使用从原点到(x,y,z)的向量,当然是

现在我们想要一个平面在(x,y,z)处与球体相切的方程,但这将使用它自己的x,y和z变量,因此我将使它在(x0,y0,z0)处与球体相切。这很简单:

x0x+y0y+z0z=1

希望这有帮助


(OP):

你的意思是:

const int R = 31, SZ = power_of_two(R*2);
std::vector<vec4_t> p;
for(int y=0; y<SZ; y++) {
    for(int x=0; x<SZ; x++) {
        const float rx = (float)(x-R)/R, ry = (float)(y-R)/R;
        if(rx*rx+ry*ry > 1) { // outside sphere
            p.push_back(vec4_t(0,0,0,0));
        } else {
            vec3_t normal(rx,sqrt(1.-rx*rx-ry*ry),ry);
            p.push_back(vec4_t(normal,1));
        }
    }
}
const int R=31,SZ=two的幂(R*2);
std::向量p;

对于(int y=0;y此公式通常用于“假环境映射”效果

double x=2.0*像素x/位图大小-1.0;
双y=2.0*像素y/位图大小-1.0;
双r2=x*x+y*y;
if(r2<1)
{
//圈内
双z=sqrt(1-r2);
…这里的法线是(x,y,z)。。。
}

他们不倾向于从图片中生成几何图形。你要找的是一种算法。当然,除非你已经找到了你认为图片中的中心点的方法。在这种情况下,请重新表述这个问题。这不是高中作业吗?不,这是大脑的一个。-一个周末的问题,我有所有的信息,可能还有我高中时代的所有数学知识,但我已经盯着这个问题看了几个小时,却没能写出一行代码。目的:在我的爱好游戏中为一些球形广告牌制作法线和深度图……你想要一个以o为中心的球体的解决方案吗还是在任意点(x,y,z)上?首先要简单得多。@Tom Zych:球体以位图的中心为中心。如果你想在2D中将该中心称为0,0(目前我无法理解),我可以处理平移
double x = 2.0 * pixel_x / bitmap_size - 1.0;
double y = 2.0 * pixel_y / bitmap_size - 1.0;
double r2 = x*x + y*y;
if (r2 < 1)
{
    // Inside the circle
    double z = sqrt(1 - r2);
    .. here the normal is (x, y, z) ...
}