我正在使用CGKit和RTree在python中编写一个非常简单的光线跟踪器。在使光线与三角形相交后,我想推断出顶点的U,V的交点的U,V。这样做的适当方法是什么?
目前我正在使用距离相对边缘的加权平均值,如下所示。除了CGKit相关的东西,我有3个顶点v1,v2,v3和3个UV的vt1,vt2,vt3。 hit_p是CGKit交集返回的三角形上的xyz点。
def extract_hit_vt(tri_geom, tri_vt,hit_p, oa_face):
hit_face = tri_geom.faces[oa_face]
vt1 = np.array(vec3(tri_vt[oa_face * 3]))
vt2 = np.array(vec3(tri_vt[oa_face * 3 + 1]))
vt3 = np.array(vec3(tri_vt[oa_face * 3 + 2]))
v1 = tri_geom.verts[hit_face[0]]
v2 = tri_geom.verts[hit_face[1]]
v3 = tri_geom.verts[hit_face[2]]
d1 = ptlined(v2, v3, hit_p)
d2 = ptlined(v3, v1, hit_p)
d3 = ptlined(v1, v2, hit_p)
hit_vt = (d1*vt1+d2*vt2+d3*vt3)/(d1+d2+d3)
return hit_vt
答案 0 :(得分:4)
这是从LuxRays(http://src.luxrender.net/luxrays)获取的代码。获得重心坐标:
static bool GetBaryCoords(const Point &p0, const Point &p1, const Point &p2,
const Point &hitPoint, float *b1, float *b2) {
const Vector u = p1 - p0;
const Vector v = p2 - p0;
const Vector w = hitPoint - p0;
const Vector vCrossW = Cross(v, w);
const Vector vCrossU = Cross(v, u);
if (Dot(vCrossW, vCrossU) < 0.f)
return false;
const Vector uCrossW = Cross(u, w);
const Vector uCrossV = Cross(u, v);
if (Dot(uCrossW, uCrossV) < 0.f)
return false;
const float denom = uCrossV.Length();
const float r = vCrossW.Length() / denom;
const float t = uCrossW.Length() / denom;
*b1 = r;
*b2 = t;
return ((r <= 1.f) && (t <= 1.f) && (r + t <= 1.f));
}
p0,p1,p2是三角形顶点,hitPoint是光线/三角形交点,b1,b2返回重心坐标。 一旦你有了b1,b2,就可以得到插值(u,v)值:
const float b0 = 1.f - b1 - b2;
const u = b0 * u_v0 + b1 * u_v1 + b2 * u_v2;
const v = b0 * v_v0 + b1 * v_v1 + b2 * v_v2;
其中u_v0,v_v0等是三角形顶点的(u,v)坐标。
答案 1 :(得分:0)
要决定的主要是你想要在三角形中插入UV的确切程度。既然你说你只有三个点,那么你不太可能比简单的线性插值更好。
在这种情况下,您需要三角形内部点的重心坐标:http://en.wikipedia.org/wiki/Barycentric_coordinate_system
简而言之,三角形内部的每个点都可以表示为顶点的加权和,其中每个权重都在0到1之间。权重可以通过求解2x2线性方程组来找到。
当你有这些权重时,可以使用它们来获得UV坐标的加权和。