在虚拟现实中打印

2021-03-28 03:38:28

欢迎人们,我希望你保持安全和良好。我将在一系列文章和一些工具上花费时间,以帮助Tiltbrush软件的刷子和技术艺术品。

本文旨在成为一系列中的第一个。请注意,本文中的Python代码以及关联的工具集中的易窃,以便冗长和表达。我已经采取了这种方法,因为它可以易于访问和容易地理解。这不是最佳的python,也不是好的风格。你被警告了!

Tiltbrush草图的最基本方面称为控制点。本质基本上是在三维空间中的曲线上的单个顶点,其中几个属性,例如压力和时间戳。渲染刷子冲程时使用这些属性组合。对于这个项目,我们将首先建立一个线原语,我们稍后将用来构建其他羊膜混合。

(如果您想了解有关Tiltbrush文件格式的更多信息,请在此之前写在此处)。

在Tiltbrush Shixt素描中的中风是一系列有序的控制点。我们可以将此笔划表示为我们代码中的3维线。我们会确保线上的顶点是等距离,而不是间隔开,并以正确的顺序没有重复的顺序。

这很容易通过递归函数来实现,该递归函数在线段发现线段长度足够短,然后通过递归熄灭。作为进修,中点和段长度式2D和3D是。

$$ d = \ sqrt {(x2 -x1)^ 2 +(y2 - y1)^ 2} $$ $$ d = \ sqrt {(x2-x1)^ 2 +(y2 - y1)^ 2 +(z2 - z1)^ 2} $$ $$(x,y)= \左(\ dfrac {x1 + x2} 2,\ dfrac {y1 + y2} 2 \右)$$(x,y,z) = \左(\ dfrac {x1 + x2} 2,\ dfrac {y1 + y2} 2,\ dfrac {z1 + z2} 2 \右)$$大多数代码来解决这是平凡的,但我确实喜欢恢复细分线条段的呼应。当我完成这个实验性项目并系列博客文章时,我将分享所有代码和工具。

def __subdivide(自我,段):seg_len = self。 __Length(段)如果seg_len<自己 。 max_seg_size:self。 ctrl_pts。附录(段)返回段= self。 __Split_segment(段)在部分中的s:self。 __subdivide(s)

一旦这些操作完成,我们有一个很好的细分线段,可以用于渲染Tiltbrush内部的笔触。

虽然没有必要,但我认为基于Polyhedra的质心或中心质量具有多面体形式是非常方便的。这使得基于世界坐标的皮带形状更容易。

这需要一段时间才能找到源头的良好解决方案。 iFound两个推荐的解决方案,两者都适用于非自相互联系的闭合3D多面体,但获得两种不同的性能。我要站在巨人的群体,并将这些解决方案转换为代码。

第一方法使用网格中的顶点向量的平均值来获得顶点的茚,第二种方法使用发散定理以获得多孔的达格兰(和面积)。两个属性对于不同类型的网格(例如,3D线VS 3D网格)非常有用)

为了帮助计算上面,我为3个维度创建了一个向量类,并为其计算了一些实用程序方法,用于计算点,交叉产品 - 作为腹部幅度和方向。我还添加了一些功能以促进载体算法。此类可以在本文的参考部分中找到。

顶点的质心是从多面体中所有顶点的算术导出的点。这是2,3和确实n维的情况。

要获取顶点列表的质心,首先组织顶点尖角图图,如下所示:

$$ p = \ begin {bmatrix} x_1& X_2& X_3& \ dots& x_n \\ y_1& Y_2& Y_3& \ dots& y_n \\ z_1& Z_2& Z_3& \ dots& z_n \\\结束{bmatrix} $$在我们的代码中,这是一个非常简单的操作,但它在下一步中使Thecentroid计算更容易。

Rows = 3#x,y,z cols = len(pts)#n p = zeros_matrix(行,cols)#填充I的矩阵(行):对于j在范围(cols)中:p [i] [i] [ j] = pt [j] [i]

现在要计算质心C,我们只是迭代矩阵P Andobtain的算术平均值。

$$ c = \ begin {bmatrix} x \\ y \\ z \ neg {bmatrix} = \ frac 1 n \ biggl(\ begin {bmatrix} x_1 \\ y_1 \\ z_1 \ neg {bmatrix} + \ begin { bmatrix} x_2 \\ y_2 \\ z_2 \ neg {bmatrix} + \ begin {bmatrix} x_3 \\ y_3 \\ z_3 \ neg {bmatrix} + \ dots + \ begin {bmatrix} x_n \\ y_n \\ z_n \ neg { Bmatrix} \ biggl)$$ LST = []对于I范围(COL):_M = Zeros_matrix(1,3)_M [0] [0] [0] [0] = p [0] [i] _m [0] [1] = p [1] [i] _m [0] [2] = p [2] [i] lst。 Append(_M)_MSUM = add_matrices(lst)sc = 1 / cols centroid_matrix = multiply_matrix_by_scalar(_msum,sc)

使用Polyhedra的三角形(面部)计算质心更涉及。令人惊讶地涉及。它需要一些复杂的(对我)的腺体溶液进行微积分。

随着我的微积分生锈,我花了很长时间才能理解这种方法。坦率仍然没有坚定的直觉。我会尝试在未来的articleas中重新审视这对我来说非常有趣。我从应用程序角度来看,我会促进前进。刚刚安慰,如果你发现这个数学很难过来,你并不孤单。

此处描述了该过程,我将在这里将其转换为Python代码。

在该方法中,ai(i = 0 - > n-1)是多面体p.so ai上的三角形面的计数是三角形。对于这些三角形中的每一个,我假设TheTheNgle Ai,Bi,Ci的顶点顺时针逆时针排序。我们可以为每个P的每个三角形计算外部单元正常n为。

$$ n_i = \ hat {n_i} / | \ hat {n_i} |,\ enspace where \ enspace \ hat {n_i} =(b_i-a_i)⊗(c_i-a_i)$$,小^符号意味着单位矢量, ⊗是产品尺寸。由此,我们使用分歧的概念判断P的V卷V是因为x·nᵢ是每个三角形的常数,每个三角形的区域是:

定理具有以下形式,Sigma是一种像循环一样的样式。 Long S类型yembol是一个明确的积分,可以被认为是一种总和函数 - 这些这些功能在微积分中使用了很多,以导出区域 - 特别是曲线的区域。这里有一个很好的内部积分微积分

$$ v = \ int_ {p} \ enspace 1 = \ cfrac {1} {3} \ int _ {\ partial p} \ enspace x \ cdot n = \ cfrac {1} {3} \ sum_ {i = 0} ^ {n-1} \ int_ {a_i} \ enspace a_i \ cdot n_i = \ cfrac {1} {6} \ sum_ {i = 0} ^ {n-1} ^ {n-1} ^ {n-1} a_i \ cdot \ hat {n_i} $$ P的质心将在3个维度R3中置于实数。其中C是质心,V是卷:

$$ c = cfrac {1} {v} {v} \ enspace \ int_ {p} x $$再次应用分歧定理,其中标准基础表示为E1,E2,E3,允许我们获得三个坐标质心:

$$ c \ cdot e_d = \ frac {1} {v} \ enspace \ int _ {\ partial p} \ frac {1} {2}(x \ cdot e_d)^ 2(x \ cdot e_d)= \ frac { 1} {2v} \ sum_ {i = 0} ^ {n-1} \ in {a_i}(x \ cdot e_d)^ 2(n_i \ cdot e_d)\ enspace d = 1,2,3 $$ \ int_ {a_i}(x \ cdot e_d)^ 2(n_i \ cdot e_d)\\\\ = \ FRAC {1} {6} \ hat {n_i} \ cdot e_d([\ frac {1} {2} (a_i + b_i)\ cdot e_d] ^ 2 + [\ frac {1} {2}(b_i + c_i)\ cdot e_d] ^ 2 + [\ frac {1} {2}(c_i + a_i)\ cdot e_d ] ^ 2)\\\\ = \ frac {1} {24} \ hat {n_i} \ cdot e_d([(a_i + b_i)\ cdot e_d] ^ 2 + [(b_i + c_i)\ cdot e_d] ^ 2 + [(c_i + a_i)\ cdot e_d] ^ 2)$$我不完全了解上述如何与三角形的标准中点采样Quadreformulululululululululate有关。

这是转换为代码,三角形是我创建的自定义类,以表示atriangle - 属性a,b和c是vector3对象 - 记住参考部分中的矢量图3类)。三角形是从倒换网格获得的三角形对象的有序列表。

total_volume = 0.0 centroid_integral = vec3。 ZERO()#对于每个三角形的三角形,在三角形的三角形中构成网格中的三角形:B_A =三角形。 B - 三角形。一个c_a =三角形。 c - 三角形。 A#计算此三角形的区域级正常,并将其添加到此Polyhedra N = B_A的#总卷。 Cross(C_A)Total_volume + =三角形。一个 。点(n)/ 6.0#Compute,然后将当前三角形贡献添加到每个维度的整体#质心积分。 #x x_contribution = n。 x *数学。 POW((三角形。一个。x +三角形。b。x),2)+数学。战俘((三角形。x +三角形。c。x),2)+数学。 POW((三角形。C. x +三角形。一个。x),2)Centroid_Integral。 x = centroid_Integral。 x + x_contribution#y y_contribution = n。 Y *数学。战俘((三角形。一个。y +三角形。b。y),2)+数学。战俘((三角形。y +三角形。c。y),2)+数学。战俘((三角形。C. y +三角形。a。y),2)centroid_Integral。 y = centroid_Integral。 y + y_contribution#z z_contribution = n。 z *数学。 POW((三角形。一个。z +三角形。b。z),2)+数学。战俘((三角形。Z +三角形。C. Z),2)+数学。 POW((三角形。C. Z +三角形。一个。z),2)Centroid_Integral。 z = centroid_Integral。 z + z_contribution#最终通过逆卷x_scaled = centroid_Integral缩放每个质心尺寸。 x *(1.0 /(24.0 * 2.0 * total_volume))Y_SCALED = CEMETRAID_INTEGLAL。 Y *(1.0 /(24.0 * 2.0 * total_volume))z_scaled = centroid_Integral。 Z *(1.0 /(24.0 * 2.0 * total_volume))#并返回质心!返回vec3(x_scaled,y_scaled,z_scaled)

我们现在可以应用上述理论和代码来派生网格的质心。我在线找到了Amesh南瓜,这是一个非常好的测试。它是低聚的,它有一个不寻常的形式。它也是一个不相交的封闭的多面体。这里是结果,红点是质心。

那很有趣!我没有预料到这种复杂性,所以它变成了一个真正整洁的Littleadventure。现在让我们前进!让我们打印这张照片!

要使用上述工作生成艺术,我们需要创建一些形状的原语。我们这样做,我们还需要知道如何旋转,并将这些原始的原因均匀地将它是一个非常乏味的图片,它是一个非常乏味的图片,其由一个单独的单位上重叠的所有像素组成

在未来,我们将讨论和添加功能以扩展,也是歪斜基元!

翻译操作应在给定方向上通过Afix距离将几何对象中的所有点移位。翻译公式是:

$$ p' =对象上所有点P的P + D $$。这将(🥁)转换为以下Python Code.we使用我们之前讨论的Vertice质心解决方案。

def translate_cy_celltroi​​d3d(Centroid,Delta,顶点):#wortringroid ortrated_cleadroid = translate_vertice3d(centroid,delta)dv =(translated_centroid [0] - centroid [0],transtrated_centroid [1] - centroid [1],translated_centroid [2] - firedroid [2])翻译_vertices = []对于V顶点,x = v [0] y = v [1] z = v = v [2] tx = x + dv [0] ty = y + dv [1] tz = z + dv [2]翻译_vertices。附加((tx,ty,tz))返回(翻译_cayroid,translated_vertices)def translate_vertice3d(tastice,delta):x = waltice [0] y = wastice [1] z = wastice [2] tx = x + delta [0] ty = y + delta [1] tz = z + delta [2] return(tx,ty,tz)

旋转操作有点涉及,我们希望旋转其质心旋转3D。此操作的转换矩阵是:

$$ rx = rx(\ theta)= \ begin {bmatrix} 1& 0& 0 \\ 0& \ cos \ theta& - \ sin \ theta \\ 0& \ sin \ theta& \ cos \ theta \ neg {bmatrix} \\\\\ enspace \\\\ ry = ry(\ theta)= \ begin {bmatrix} \ cos \ theta& 0& \ sin \ theta \\ 0& 1& 0 \\ - \ sin \ theta& 0& \ cos \ theta \ neg {bmatrix} \\\\\ enspace \\\\ rz = rz(\ theta)= \ begin {bmatrix} \ cos \ theta& - \ sin \ theta& 0 \\\ sin \ theta& \ cos \ theta& 0 \\ 0& 0& 1 \结束{bmatrix} $$我们可以创建以下代码,主要仿真上述转换。但我们将在另一个帖子中接近比例和偏差。现在,这是我的天空化:

def rotate3d(角度,顶点):rftclecles = rotate_x(角度[0],顶点)rftctions = rotate_y(角度[1],revcticrics)rftctions = rotate_z(角度[2],revcticrics)返回refrices def rotate_x(θ,顶点) :sin_theta =数学。 SIN(THETA)COS_THETA =数学。 COS(θ)rotated_vertices = []用于顶点的v:打印(":" v)x = v [0] y = v [1] z = v [2] rx = x ry = y * cos_theta - z * sin_theta rz = z * cos_theta + y * sin_theta rotated_vertices。附加((rx,ry,rz))返回rotated_vertices def rotate_y(θ,顶点):sin_theta = math。 SIN(THETA)COS_THETA =数学。 COS(θ)rotated_vertices = []对于顶点的v:x = v [0] y = v [1] z = v [2] rx = x * cos_theta + z * sin_theta ry = y rz = z * cos_theta - x * sin_theta rotated_vertices。附加((rx,ry,rz))返回rotated_vertices def rotate_z(theta,顶点):sin_theta = math。 SIN(THETA)COS_THETA =数学。 cos(theta)rotated_vertices = []对于顶点的v:x = v [0] y = v [1] z = v = v [2] rx = x * cos_theta - y * sin_theta ry = y * cos_theta + x * sin_theta rz = z rotated_vertices。附加((rx,ry,rz))返回rotated_vertices

为了使这篇文章是合理的大小,我们将专注于两个简单的PrimitivesFirst,然后在未来的文章中我们将获得更先进的文章。现在我们将制作Pixelsand Voxels!我认为我们都知道像素是什么,但体素是长方体,它是三维的紫杉醇。

我创建了像素的像素,该方形由Tiltbrush中的四行组成,然后将X形成为X作为像素的填充。我已经包含以下代码:

Warning: Can only detect less than 5000 characters