メッシュ出力のみを用いて、Shade3D Legacy独自のフリーフォームサーフェスアルゴリズムを再構築する。

This is a multi-part series on how to recover the original proprietary math behind the Shade3D Curved Surface using only what the program outputs when converting to a polygon mesh object. No generative AI will be used for this task.

本シリーズは、Shade3Dの自由曲面に用いられている独自の数学的アルゴリズムを、プログラムが提供するポリゴンメッシュオブジェクトへの変換機能のみを用いて復元する方法について、複数回にわたり解説するものです。この作業には、生成型人工知能は一切使用しません。

Part 0 - Fundamentals:
第0部分:基础知识:

Before we begin, we will set some fundamentals with how a Bezier Surface is represented. Common Bezier surface functions beyond degree 1 will be represented in Bernstein notation, and the control points will be labeled as such in the following diagram:

本題に入る前に、ベジエ曲面の表現方法に関する基礎をいくつか整理しておきます。次数1を超える一般的なベジエ曲面関数はバーンスタイン表記で表され、以下の図では制御点にはそのようにラベルが付けられています:

The Bezier surface blending functions will be represented as such:
ベジェ曲面のブレンド関数は、次のように表されます:

Now that all the relevant notations have been determined, it is time to move on to Part 1.
関連する表記がすべて確定したところで、いよいよ第1部へと進みましょう。

Part 1: Shade3D Legacy - Calculating the 4 internal control points
第1部:Shade3D Legacy - 4つの内部制御点の計算

Shade3D Legacy (ver.17.0.1 and earlier) has a simple method of calculating the internal control points of any Bezier surface. This method used to be in a forum post by ToshiakiKatoh, which has since been deleted. It is being reposted here for archival’s sake.

Shade3D Legacy(ver.17.0.1 以前)には、任意のベジエ曲面の内部制御点を計算する簡単な方法があります。この方法は、かつてToshiakiKatoh氏によるフォーラムの投稿に掲載されていましたが、その投稿はすでに削除されています。ここでは、記録として再掲載します。

The following Python command obtains the mesh output of the Bezier surface:
以下の Python コマンドは、ベジエ曲面のメッシュ出力を取得します:

convert_to_polygon_mesh_with_divisions(n,m)

To get the polygon mesh output of the proprietary Curved Surface:
独自の「曲面」機能からポリゴンメッシュを出力するには:

convert_to_polygon_mesh_with_subdivision_level(s)

In the next part, we will discover significant properties of the mesh output given by convert_to_polygon_mesh_with_subdivision_level, and construct rudimentary functions that approximate the behavior of the freeform surface.
次のセクションでは、convert_to_polygon_mesh_with_subdivision_level によって生成されるメッシュ出力の重要な性質について考察し、自由曲面の挙動を近似する基本的な関数を構築します。

Part 2: Curved Surface tesselation observation & approximate behavior.
第2部:自由曲面テッセレーションの観察と近似的な挙動。

Shade3D has a unique way of deforming the Bezier surface based on UV coordinate position. This is confirmed by two functions listed in the old Shade SDK, under shade_interface:

Shade3Dには、UV座標の位置に基づいてベジエ曲面を変形させる独自の方法があります。これは、旧Shade SDKのshade_interfaceにリストされている2つの関数によって確認できます:

virtual void calculate_internal_points (std::array< std::array< sxsdk::vec3, 4 >, 4 > &p, const bool correction, const sxsdk::mat4 &lw, void *aux=0)
	(Shade独自変形)ベジエ曲面の内部コントロールポイントを計算する。 
virtual sxsdk::vec2 	calculate_blending_weights (const sxsdk::vec2 &uv, void *aux=0)
 	ベジエ曲面ブレンディングの荷重を計算する。 

It appears that Shade calculates 16 control points per individual Bezier surface, rather than 4, for Curved Surface parts. In addition, there is the secondary function calculate_blending_weights, which at first glance appears to be redundant for a regular Bezier surface. However, in this part, we will observe that it does not follow the standard intuition of blending weights.

Shadeでは、自由曲面パーツについて、個々のベジェ曲面ごとに制御点を4つではなく16つ計算しているようです。さらに、calculate_blending_weightsという二次的な関数がありますが、一見すると通常のベジェ曲面にとっては冗長に見えるかもしれません。しかし、このパートでは、この関数がブレンドウェイトに関する標準的な直感とは異なる動作をすることを確認することになります。

For now, only the U direction will be considered, since the behavior of a Curved Surface is easier to observe.
ここでは、曲面の挙動を観察しやすいという理由から、ひとまずU方向のみを考慮することにする。

Attached is a test scene with a simple Curved Surface, with a 40mm difference in length between tangent out-handles in the U direction:
U方向の接線アウトハンドル間の長さに40mmの差がある、単純な曲面を含むテストシーンを添付します:

Shade3D-Labo-Reborn-Module-Example-00.shd (129.6 KB)

What is immediately noticeable is the appearance of two rational functions that are interpolated along the V-direction of the surface. It is tempting to figure this out using only the VeryFine subdivision level, but no useful relations can be determined without first pre-calculating the Curved Surface at a much higher subdivision level, so 128 faces of level-10 subdivision are included in the attached file.

すぐに目につくのは、曲面のV方向に沿って補間された2つの有理関数が現れていることです。VeryFineの細分化レベルのみを用いてこれを解明したくなるかもしれませんが、はるかに高い細分化レベルで曲面を事前に計算しておかないと有用な関係式を導き出すことはできません。そのため、添付ファイルにはレベル10の細分化による128面のデータが含まれています。

We will look at the surface coordinates u = v = 1/1024, and also look at the edges of the surface when u = 1/1024, at the top left of the mesh object labeled “独自の手法-細分化レベル 10”. Select the polygon mesh object, and run the following Python commands to get the x-coordinates of each vertex in question:

ここでは、表面座標 u = v = 1/1024 について検討するとともに、「独自の手法-細分化レベル 10」とラベル付けされたメッシュオブジェクトの左上にある、u = 1/1024 における表面の縁についても見ていきます。ポリゴンメッシュオブジェクトを選択し、以下の Python コマンドを実行して、対象となる各頂点の x 座標を取得してください:

print xshade.scene().active_shapes[0].vertex(1).position #ベジェ曲面の縁
print xshade.scene().active_shapes[0].vertex(10).position
print xshade.scene().active_shapes[0].vertex(145).position
print xshade.scene().active_shapes[0].vertex(154).position #ベジェ曲面の縁

They are respectively:
順に並んでいる座標は次のとおりです:

(-74.853515625, 0.0, -75.0)
(-74.88275146484375, 0.0, -74.853515625)
(-74.94123840332031, 0.0, 74.853515625)
(-74.97047424316406, 0.0, 75.0)

長さの順:
0.146484375, #L1
0.11724853515625, #C1
0.05876159667969, #C2
0.02952575683594, #L2

To obtain the surface coordinate of vertex(10), the lengths L1 and L2 must be added in the following manner:
頂点(10)の表面座標を求めるには、長さ L1 と L2 を次のように足し合わせる必要があります:

(3 * L1 + L2)/4

Checking the result obtained from this relation against length C1, it agrees with the mesh output to 6 significant digits, near the limit of precision for a 32-bit float. The same applies for C2 if L1 and L2 are exchanged in the above equation.

この関係式から得られた結果を長さ C1 と照合すると、32 ビット浮動小数点の精度限界に近い、有効数字 6 桁の範囲でメッシュ出力と一致している。上記の式で L1 と L2 を入れ替えた場合、C2 についても同様のことが言える。

A geometric sequence can be constructed for successive increments of the V-parameter, and each equation from that sequence will obtain the surface coordinates to within 1e-5.
Vパラメータを段階的に増加させることで等比数列を構成することができ、その数列に含まれる各方程式は、1e-5以内の精度で曲面の座標を求めることができる。

V方向に沿って
(4 * L1 + (2 * L2))/6
(5 * L1 + (3 * L2))/8
(6 * L1 + (4 * L2))/10…

Separating the L1 and L2 terms, we obtain the following equations:
L1項とL2項を分離すると、次の式が得られる:
06-Shade3D-init-geo-sequences

These equations are tied to world-space, and the underlying pattern becomes difficult to discern when the UV-coordinates are not small. There is a way to convert them to UV-space, and it involves levaraging the following equality:
これらの方程式はワールド空間に紐づいており、UV座標が小さくない場合、その根底にあるパターンを把握することが難しくなります。これらをUV空間に変換する方法があり、それは次の等式を活用するものです:

06b-Shade3D-equality

The difference in lengths between opposite rows is 40mm. If we divide that length by 2**subdivision_level, then multiply by 3/4, we have the desire displacement from the original Bezier surface when u = v. However, when u ≠ v, the resolution alone becomes useless in getting the desired displacement. We can obtain a divisor which is independent of subdivision resolution if we take the product of the UV coordinates and divide them by twice their sum, as shown below:

対向する行間の長さの差は40mmです。この長さを2**subdivision_levelで割り、さらに3/4を掛ければ、u = vのとき、元のベジエ曲面からの所望の変位が得られます。しかし、u ≠ vの場合、解像度だけでは所望の変位を得ることはできません。以下に示すように、UV座標の積を、その和の2倍で割ることで、細分化解像度に依存しない除数を得ることができます:

07-Shade3D-init-geo-sequences

The above equation gives us exactly 1/3 the desired displacement for surface coordinates near the corner, so multiplying by 3, we have the first approximation.

上記の式からは、角付近の表面座標における求めている変位のちょうど1/3が得られるため、これに3を掛けると、第1近似が得られる。
08-Shade3D-init-geo-sequences

The equations for the other three corners are trivially obtained by substituting the appropriate variables into ‘f(0,0)’.
残りの3つの角に関する式は、「f(0,0)」に適切な変数を代入することで、自明に導き出される。