我已经在C#中实现了行进立方体,双行进立方体和自适应行进立方体,但却发现我需要双重轮廓以达到我的目的.我已经阅读了关于双轮廓的所有作品,除了双轮廓本身的核心之外,我得到的只是:最小化二次误差函数(QEF).
现在,我只是通过找到共享该单个顶点(3到6个边)的所有edgePoints之间的平均值来计算内部体素的顶点位置,并且它运行良好,但它显然不会在正确的位置创建内部顶点.
这是我要创建的代码片段.任何帮助将非常感激
////// ORIGINAL WORK: Dual Contouring of Hermite Data by Tao Ju (remember me of a MechCommander 2 character) /// 2.3 Representing and minimizing QEFs /// The function E[x] can be expressed as the inner /// product (Ax-b)T (Ax-b) where A is a matrix whose rows are the /// normals ni and b is a vector whose entries are ni*pi. <------------ (dot product?)> /// Typically, the quadratic function E[x] is expanded into the form /// E[x] = xT AT Ax - 2xT AT b + bT b (2) /// where the matrix AT A is a symmetric 3x3 matrix, AT b is a column /// vector of length three and bT b is a scalar. The advantage of this expansion /// is that only the matrices AT A, AT b and bT b need be stored /// (10 floats), as opposed to storing the matrices A and b. Furthermore, /// a minimizing value ˆ x for E[x] can be computed by solving /// the normal equations AT Aˆ x = AT b. /// public Vector3 GetMinimumError(Vector3 p0, Vector3 p1, Vector3 p2, Vector3 n0, Vector3 n1, Vector3 n2) { //so, here we are. I'm creating a vector to store the final value. Vector3 position = Vector3.Zero; //Values of b are supposed to b (:P) three floats. The only way i know to find a float value //by multiplying 2 vectors is to use dot product. Vector3 b = new Vector3( Vector3.Dot(p0, n0), Vector3.Dot(p1, n1), Vector3.Dot(p2, n2)); //What the transpose of a vector is supposed to be? //I don't know, but i think should be the vector itself :) float bTb = Vector3.Dot(b, b); //i create a square matrix 3x3, so i can use c# matrix transformation libraries. //i know i will probably have to build bigger matrix later on, but it should fit for now Matrix A = new Matrix( n0.X, n0.Y, n0.Z, 0, n1.X, n1.Y, n1.Z, 0, n2.X, n2.Y, n2.Z, 0, 0, 0, 0, 0); //easy Matrix AT = Matrix.Transpose(A); //EASY Matrix ATA = Matrix.Multiply(AT, A); //Another intuition. Hope makes sense... Vector3 ATb = Vector3.Transform(b, AT); //... // some cool stuff about solving // the normal equations AT Aˆ x = AT b //... return position; //profit! }
小智.. 7
优质教育基金很难理解.希望我能提供帮助.双轮廓法计算每个交叉点处的"厄米特"数据,或者换句话说,在体素边缘上创建的每个点处,表面的法线已知.使用点和法线可以计算平面的方程.
QEF是从体素的内部点到与体素相关联的每个平面的距离的平方的总和.下面是一些用于计算QEF的伪代码.
double get_QEF(Point3d point, Voxel3d voxel) { double QEF = 0.0; foreach(plane in voxel.planes) { double dist_to_plane = plane.distance(point); QEF += dist_to_plane*dist_to_plane; } return(QEF); }
然后,目标是在体素内选择一个最小化QEF的点.文献建议使用Grahm-Schmidt过程来定位最佳点,但这可能是复杂的,并且还可能导致位于体素之外的点.
另一种选择(hack-ish)是在体素内部创建点网格并计算每个点的QEF并选择具有最低点的QEF,网格越精细越接近您将到达的最佳点但是越长计算.
优质教育基金很难理解.希望我能提供帮助.双轮廓法计算每个交叉点处的"厄米特"数据,或者换句话说,在体素边缘上创建的每个点处,表面的法线已知.使用点和法线可以计算平面的方程.
QEF是从体素的内部点到与体素相关联的每个平面的距离的平方的总和.下面是一些用于计算QEF的伪代码.
double get_QEF(Point3d point, Voxel3d voxel) { double QEF = 0.0; foreach(plane in voxel.planes) { double dist_to_plane = plane.distance(point); QEF += dist_to_plane*dist_to_plane; } return(QEF); }
然后,目标是在体素内选择一个最小化QEF的点.文献建议使用Grahm-Schmidt过程来定位最佳点,但这可能是复杂的,并且还可能导致位于体素之外的点.
另一种选择(hack-ish)是在体素内部创建点网格并计算每个点的QEF并选择具有最低点的QEF,网格越精细越接近您将到达的最佳点但是越长计算.