这一周结束得太快了……在我们进入周末之前,这里有一些引人注目的话题:
- 使用 AVF 解释纹理 UV 映射
- 人体细胞的详细 3D 模型
推荐:用 NSDT设计器 快速搭建可编程3D场景。
1、使用 AVF 解释纹理 UV 映射
不久前在 Revit API 讨论论坛中提出了一个问题,并在 IExportContext 中将 UV 转换为范围 (0,1) 进行了部分讨论。
那时,我在关于自定义导出器中规范化 UV 的博客文章讨论中总结并保留了该讨论的初始部分。
现在 Jason 扩展了这个问题,Revit 开发团队承认缺乏这方面的信息,提供了一些提示,最重要的是,Richard RPThomas108 Thomas 再次加入了一个重要而强大的解决方案,既回答了问题又展示了 如何使用 Analysis Visualization Framework 或 AVF 功能进行 UV 调试来自己研究和解决这个问题。
问题:我正在为 Revit 编写导出器,在导出 UV 时遇到问题。 当我调用 PolymeshTopology.GetUV 时,给出的坐标通常大于 1。我的问题是:
1、如何将它们转换为所需的范围 (0,1)? 或者我应该如何理解这些UV值?
2、它们是图像上的坐标吗? 如果是这样,我如何访问 IExportContext 中的图像尺寸?
举一个具体的例子:假设我有一个大小为 4096x4096 的纹理,我在 IExportContext 中读取的相应 UV 数据约为 25,而 UnifiedBitmapAsset 中的 RealWorldScale 约为 141。我似乎无法辨别公式或其他东西。 …
有关 Faces 的 Building Coder 文章有所帮助。
但是,它把UV解释为参数化一个面的两个变量,但它们与面在3D空间中的结构有关,而不是面的每个顶点如何映射到位图。 如果您能对此进行详细说明,我将不胜感激,即如何将 PolymeshTopology.GetUV 返回的 UV 坐标转换为图像上或 (0,1) 范围内的像素坐标。
关于 PolymeshTopology UVs 的文章是相关的; 但是,给出的答案不够详细,无法真正解决问题。
回答:这是我目前的做法:
PolymeshTopology.GetUV 方法返回表示面参数的 UV 坐标。 因此,我猜测它们与它们参数化的面部尺寸有关。 这些 UV 坐标可以通过 UnitUtils.ConvertFromInternalUnits(已弃用,但无论如何…)转换为显示单位,并且在我的加载项中使用厘米。 所以,我们有以厘米为单位的UV。
下一步是获取位图的大小。 这是由名称为 UnifiedBitmap.TextureRealWorldScaleX/Y 的属性给出的。 这些值实际上以英寸为单位给出,因此你可以调用 UnitUtils.Convert 将它们从 DisplayUnitType.DUT_DECIMAL_INCHES 转换为 DisplayUnitType.DUT_CENTIMETERS。 事实上,我发现 DisplayUnitType.DUT_FRACTIONAL_INCHES 给出了相同的结果; 我不知道有什么区别。 AssetPropertyDistance 类实际上有一个 DisplayUnitType 属性,应该使用它来代替 DUT_DECIMAL_INCHES。
之后,UV 坐标可以缩放到范围 [0,1] 或其他范围。
The Building Coder 在自定义导出器中规范化 UV 的注释中保留了这种方法。
问题:Jason 对 Richard 帮助解决的更多细节的后续请求:
这有点令人困惑,因为 UV 通常是一个相对空间坐标系。 “相对”是关键词,因为它们不对应于可测量的距离。 那么,如果归一化最终是 x/y 或 y/x,为什么需要将 TextureRealWorldScaleX/Y 转换为另一个单位? Revit 如何计算其 UV?
提供的 UV 不是可用的 UV(除非纹理尺寸为 1:1)这似乎很疯狂——UV 的全部目的是让我们忽略纹理尺寸。 我所了解的是,它可以让 Revit 开发人员的工作更轻松,因为它允许在交换纹理时进行有趣的平铺动态。
无论如何,我尝试了一种我认为是标准化给定纹理尺寸的方法:
normalize_multiplier = scaleX / (scaleY + ((scaleX - scaleY) / 2))
如果 scaleX 为 14 且 scaleY 为 10(英寸、厘米,这应该无关紧要),那么我会看到从 (0, 0) 到 (1.167, 0.833) 的 UV,normalize_multiplier 结果为 1.167。 因此,(/, *) 结果为 (1, 1)。
但是,不幸的是,这并不总是有效,而且我在其他地方看到错误的 UV。
所以,我需要更多信息:
- 我们从 Revit 获得的 UV 是什么——它们不是经典的 UV,那么它们真正代表什么?
- 根据纹理尺寸转换或规范化 UV 的合适算法是什么?
- 是否有已经进行此转换的功能?
- TextureRealWorldOffsetX/Y 如何影响 UV?
- TextureWAngle 如何影响 UV?
回答:我认为这取决于脸型; 我发现它们并不总是从 0 归一化到 1。
你可以使用 AVF 在表面上绘制 UV 坐标; 我相信 UV 倾向于遵循面部边缘周围的曲线参数。
所以,我相信,上次我检查时,在圆柱面上,直边与曲线(线)的原始参数相关,而弯曲边具有圆弧的归一化参数,即对于垂直弯曲的面 墙,V 是原始的,U 是标准化的(或相反)。 有时,尤其是对于圆柱面,系统的方向不是 V 在与 Basis.Z 相同的方向上增加(取决于面方向)。 如果你有一个完整的圆,有两个圆柱面,一个 V 指向下,另一个指向上,以保持面法向外。
无论如何,我的建议是使用 AVF 来了解 UV 如何应用于不同类型的面部。
其实我记错了,结果如下:
通常,UV 基于弯曲边缘的原始参数,但对于某些面,即直纹面,它是标准化的。 以下是一些示例(请注意所有情况下的增加方向)。 下面是根据Face BoundingBoxUV Max/Min的差异,分成10段,将UV值加入到ValueAtPoint集合中。 下面的许多墙高 9.8 英尺,底部为 0。
这对我来说似乎是合乎逻辑的,因为直纹面必须从一条曲线过渡到另一条曲线(相对的边缘),因此对这两条相反的曲线进行归一化是有意义的,因此沿着它的点可以相互映射。 想象一下,否则你会在一条边上有一条弧线,与另一条边上的一条线相对(两条线的长度都不同); 你必须在某个阶段正常化。
同时,其他类型的面,例如圆柱面或平面面,可以用在给定方向上投影一定长度的曲线来构造,因此原始参数似乎也更适合这种构造形式。 关于圆柱面,你还可以看到U值与曲线的参数有关,即如果9.8英尺高的曲面墙显然比1.5英尺长(因此,需要乘以它的半径)。
我总是喜欢归一化曲线参数; 当与长度和起点相结合时,它们本质上会告诉你更多并告诉你一切。 我知道我的偏好是什么,但我认为我们只是得到了内部几何系统的剩余部分。
开发团队评论:
Richard 通过使用 AVF 提供了很好的解释。 当 UV 使用现实世界单位时,可以在每个对象的基础上对它们进行归一化(如果墙高 9.8 英尺,除以 9.8)。 但是,直纹面已经归一化了。 在我看来,这两种情况只能通过考虑顶点位置来协调。 我想知道规范化在这里是否是正确的方法,因为它会将任何纹理缩放到对象的大小,而在 Revit 中的目的是将纹理中的细节(例如,砖块)保持在相对于对象的真实比例。
因此,对于一般纹理,AVF 插图提供了所有答案,即大多数坐标都采用实际单位。 其余的取决于需要什么样的纹理贴图。 如果需要,可以通过标准化它们来直接使用大多数 Revit 对象的 UV(并注意直纹曲面的特殊情况)。 对于某些导入的对象,可能会有更复杂的纹理。 如果这还不够,那么答案就是从顶点位置计算 UV 坐标。
对于它的价值,PolymeshTopology 代码和它使用的内部代码没有任何关于 UV 是什么的描述,更不用说它们应该如何使用了。 似乎与纹理映射相关的任何内容都非常缺乏文档。
非常感谢 Richard 提出了使用 AVF 进行 UV 调试的伟大想法,以及他从中得出的显而易见的结论。
2、人体细胞的详细 3D 模型
从 Revit API、Python 和 Dynamo 转向一般的科学和建模,这是后者在非建筑甚至非技术背景下的一个非常令人印象深刻的例子,一个人体细胞的详细 3D 模型:
… 受 David Goodsell 令人惊叹的艺术启发,这个真核细胞的 3D 渲染是使用 X 射线、核磁共振 (NMR) 和冷冻电子显微镜数据集为其所有分子参与者建模的。 它试图概括涉及信号转导、蛋白质合成、内吞作用、囊泡运输、细胞间粘附、细胞凋亡和其他过程的无数途径。 尽管相对于真实细胞而言其浓度有所稀释,但此渲染图也是一种将细胞分子编排的巨大复杂性和美丽形象化的尝试。 可以在 www.digizyme.com/cst_landscapes.html 探索该景观部分的交互式版本。
原文链接:Revit AVF纹理UV — BimAnt