WPF:3D正四面体旋转改错

一、坐标系

  • WPF 的 3D 坐标系原点通常位于对象中心,X 轴向右,Y 轴向上,Z 轴朝向观察者(右手定则)。

    正四面体旋转以原点为中心,绕Z 轴自动旋转。

  • 视点坐标:

    位置(Position)0,0,50、观察方向(LookDirection)0,0,-1 和向上方向(UpDirection)0,1,0

二、问题

问题:3D正四面体自动旋转,有时候会只看到两个分离的面,有时候什么都看不到,全白色。

三、解析

  • 这个问题是 WPF 3D 的背面剔除(Back-face culling) 机制导致的。
    在 WPF 中,默认只会渲染法线朝向相机的三角形面。
    而三角形面的朝向由顶点索引顺序决定(右手定则,逆时针为正面)。如果三角形面的顶点顺序反了,会导致它们的法线指向了立方体内部(很多是指向原点)。
    法线朝向相机(即指向外边的)能够正确显示,指向内部的不会显示。三角形不渲染,所以看到的是纯白色背景。
    因为 Viewport3D 默认背景为白色(或网格背景为白色),当所有三角形都被剔除、没有任何像素被绘制时,就直接透出白色背景了。

四、计算

  • 顶点:(0,0,0), (10,10,0), (10,0,10) , (0,10,10)

    面1: (0,0,0), (10,10,0), (10,0,10) 索引 0,1,2

    面2: (0,0,0), (10,10,0), (0,10,10) 索引 0,1,2

    面3: (0,0,0), (10,0,10), (0,10,10) 索引 0,1,2

    面4: (10,0,10), (0,10,10), (10,10,0) 索引 0,1,2

    另外三个顶点是 (10,10,0), (10,0,10), (0,10,10)。这个四面体不是以原点为中心,而是以原点为一个顶点。那么背面剔除的问题可能表现在某些角度出现空白?需要检查每个面的法线方向是否朝外。由于所有面都包含原点,且其他顶点都在正象限,法线方向可能需要计算。

  • 通常为了清晰显示立体感,我们只渲染正面,但需要正确顺序。

    对于以原点为顶点的四面体,我们可以选择从外部看每个面的逆时针顺序。

    更简单的方法是将所有三角形索引改为按顺时针从外部看?

    但标准是逆时针为正面。我们可以计算每个面的法线,如果指向内部,则交换最后两个索引。

  • 面1: A,B,C:

    A=(0,0,0), B=(10,10,0), C=(10,0,10)。

    向量AB=(10,10,0), AC=(10,0,10)。法线为: 叉积 AB × AC = (10,10,0) × (10,0,10) = (100, -100, -100),指向 (1,-1,-1) 方向,这大致指向外部吗?

    这个四面体位于第一象限,A在原点,外部应该是指向远离原点的方向?但这个四面体不在原点中心,其外部方向对于每个面是不同的。

    我们通常希望模型围绕原点旋转时,外部法线指向外。但该四面体所有顶点都在x>=0,y>=0,z>=0区域,其重心在 (5,5,5) 附近。对于面A,B,C,外部应该是远离重心方向。

    重心G=( (0+10+10+0)/4, (0+10+0+10)/4, (0+0+10+10)/4 ) = (5,5,5)。

    面ABC的中心是 ( (0+10+10)/3, (0+10+0)/3, (0+0+10)/3 ) ≈ (6.67, 3.33, 3.33)。

    从重心到面中心的方向向量是 (1.67, -1.67, -1.67),即大致方向 (1,-1,-1)。

    而我们的法线 (1,-1,-1) 正好指向外部,所以该顺序 (A,B,C) 是正确的。所以面1的顺序 0,1,2 是正确的。

  • 面2: A,B,D。

    A=(0,0,0), B=(10,10,0), D=(0,10,10)。

    向量AB=(10,10,0), AD=(0,10,10)。

    叉积 AB×AD = (10 * 10-0 * 10, 0 * 0-10 * 10, 10 *1 0-10 * 0) = (100, -100, 100) 即 (1,-1,1)。

    面2中心 ( (0+10+0)/3, (0+10+10)/3, (0+0+10)/3 ) = (3.33, 6.67, 3.33)。

    重心到面中心向量: (5-3.33, 5-6.67, 5-3.33) = (1.67, -1.67, 1.67) 即 (1,-1,1)。

    法线 (1,-1,1) 也是外部,所以顺序 0,1,2 也是正确的。

  • 面3: A,C,D。

    A=(0,0,0), C=(10,0,10), D=(0,10,10)。

    向量AC=(10,0,10), AD=(0,10,10)。

    叉积 AC×AD = (0 * 10-10 * 10, 10 * 0-10 * 10, 10 * 10-0 * 0) = (-100, -100, 100) 即 (-1,-1,1)。

    面3中心 ( (0+10+0)/3, (0+0+10)/3, (0+10+10)/3 ) = (3.33, 3.33, 6.67)。

    重心到面中心向量:(5-3.33, 5-3.33, 5-6.67) = (1.67, 1.67, -1.67) 即 (1,1,-1)。

    我们的法线是 (-1,-1,1),正好相反,是向内。所以顺序 0,1,2 是反的,应该改为 0,2,1 才使得法线向外。

  • 面4: B,C,D。

    B=(10,10,0), C=(10,0,10), D=(0,10,10)。

    向量BC=(0,-10,10), BD=(-10,0,10)。

    叉积 BC×BD = ((-10) * 10 - 10 * 0, 10 * (-10) - 0 * 10, 0 * 0 - (-10) * (-10)) = (-100, -100, -100) 即 (-1,-1,-1)。

    面4中心 ( (10+10+0)/3, (10+0+10)/3, (0+10+10)/3 ) = (6.67, 6.67, 6.67)。

    重心到面中心向量:(5-6.67, 5-6.67, 5-6.67) = (-1.67, -1.67, -1.67) 即 (-1,-1,-1)。

    法线 (-1,-1,-1) 是外部,所以顺序 0,1,2 正确。

  • 因此,只有第三个面(A,C,D)需要改为 0,2,1,而其他三个面保持 0,1,2。

五、问题判断

  • WPF 3D 默认只渲染法线朝向相机的三角形(逆时针顺序为正面)。程序的四个面都使用了 TriangleIndices="0,1,2",但经过计算,第三个面(A,C,D)的法线指向内部,而不是朝外。因此:
    • 当相机从某个方向看时,如果所有面都背对相机,就什么都看不见(全白色);
    • 当相机转到特定角度,只有个别面的法线指向相机,所以只能看到一两个面。

六、改正

第三个面(A,C,D)需要改为 0,2,1,而其他三个面保持 0,1,2。

七、补充

  • 绕 X 轴旋转 160°(接近 180°)相当于把原本在 Y 轴正方向的东西翻到了后面。
    红色原本在视角的正前方(原始状态下只有它可见),但转 160° 后它正好翻到了背面。
    绿色和黄色原本藏在背面,现在随着旋转被翻到了正面。
    WPF 3D 默认只渲染法线朝向相机的三角形来看,红色不渲染,所以看见了藏在背面的绿色和黄色。
相关推荐
lialaka2 小时前
「极客智库(The Architect‘s Nexus)」——全语音 3D AI 首席架构师与具身交互智能会话推演舱
人工智能·3d·交互
DTAS尺寸公差分析软件2 小时前
国产自研-DTAS 3D公差分析软件-功能简介
人工智能·3d·尺寸公差分析·三维公差分析·公差计算软件·尺寸链分析软件
cd_9492172111 小时前
哪些AI工具适合生成游戏开发用的3D道具模型?从道具草稿到引擎测试的选择方法
人工智能·3d
3D小将16 小时前
3D格式转换之IGS 转 CATIA 标准化转换技术
3d·solidworks模型·ug模型·sketchup模型·igs模型
熊猫钓鱼>_>18 小时前
当3DGS遇上ArkTS:用HarmonyOS端侧重建守护文化遗产——从零构建「古韵新生」完整工程
3d·华为·harmonyos·arkts·鸿蒙·3dgs
dalong1019 小时前
WPF:3D正四面体自动旋转
3d·wpf
He BianGu20 小时前
【WPF-Control】二次开发总览
wpf
饼饼学习空间智能1 天前
Kimi K3发布后,为什么数字孪生与物理AI底座更重要?从3D智能到具身智能落地
人工智能·深度学习·3d
绿浪19841 天前
WPF 后台刷新界面总结
wpf