チュートリアル - 面領域 xView チェッカーの開発 - 第 1 部

チュートリアル > 面領域 xView チェッカーの開発 - 第 1 部

このチュートリアルでは、MAXScript 関数を使用してカスタム xView チェッカーを作成する方法を説明します。

xView チェッカーは、 3ds Max 2010 以降で使用可能です。

関連トピック:

xView ジオメトリ チェッカーへのアクセス

インタフェース: XViewChecker

全体の流れ:

プロパティと関数を含むグローバル構造体を作成します。

xView ジオメトリ チェッカーの関数を定義します。

サポートされる関数を定義します。

xView チェッカーを登録します。

スクリプト:

(
global FaceAreaChecker
struct FaceAreaCheckerStruct
(
FaceAreaThresholdMin = 1,
FaceAreaThresholdMax = 10,
faceAreaDialog = undefined,
 
fn geomCheck theTime theNode theResults =
(
  local theCount = case classof theNode of
  (
    Editable_Poly: getNumFaces theNode
    Editable_Mesh: theNode.numfaces
  )
  local theAreaMethod = case classof theNode of
  (
    Editable_Poly: polyOp.getFaceArea
    Editable_Mesh: meshOp.getFaceArea
  )
  
  for f = 1 to theCount do
  (
    local theArea = theAreaMethod theNode f
    if theArea >= FaceAreaChecker.FaceAreaThresholdMin and theArea <= FaceAreaChecker.FaceAreaThresholdMax do append theResults f
  ) 
3
),
 
fn supportedCheck theNode =
(
  classof theNode == Editable_Mesh or classof theNode == Editable_Poly
),
 
fn configDlg =
(
  try(destroyDialog FaceAreaChecker.faceAreaDialog)catch()
  rollout faceAreaDialog "Face Area Checker"
  (
    spinner spn_FaceAreaThresholdMin "Min. Threshold:" range:[0,1000000,FaceAreaChecker.FaceAreaThresholdMin] offset:[7,-3] type:#worldUnits
    spinner spn_FaceAreaThresholdMax "Max. Threshold:" range:[0,1000000,FaceAreaChecker.FaceAreaThresholdMax] offset:[7,-3] type:#worldUnits
   
    fn updateDisplay =
    (
      XViewChecker.runCheck CurrentTime
      max views redraw
    )
    on spn_FaceAreaThresholdMin changed val do
    (
      FaceAreaChecker.FaceAreaThresholdMin = val
      updateDisplay()
    ) 
    on spn_FaceAreaThresholdMax changed val do
    (
      FaceAreaChecker.FaceAreaThresholdMax = val
      updateDisplay()
    )   
  )--end rollout
  
  createDialog faceAreaDialog
  setDialogPos faceAreaDialog mouse.screenpos
  FaceAreaChecker.faceAreaDialog = faceAreaDialog
)
)--end struct
 
try(destroyDialog FaceAreaChecker.faceAreaDialog)catch()
FaceAreaChecker = FaceAreaCheckerStruct()
 
XViewChecker.unRegisterChecker "Face Area Checker"
XViewChecker.registerChecker FaceAreaChecker.geomCheck FaceAreaChecker.supportedCheck #Faces "Face Area Checker" FaceAreaChecker.configDlg undefined undefined
)--end script

ステップごとの解説

(

スクリプト全体をローカル スコープ内に配置します。

global FaceAreaChecker

xView チェッカーのプロパティと関数を格納する構造体のインスタンスだけを、グローバル スコープに公開します。

struct FaceAreaCheckerStruct (

すべてのプロパティと関数を含む構造体の作成から開始します。この構造体は、現在のスコープにローカルにします。

FaceAreaThresholdMin = 1,

このプロパティには、チェックする最小の面領域が含まれます。

FaceAreaThresholdMax = 10,

このプロパティには、チェックする最大の面領域が含まれます。

faceAreaDialog = undefined,

この xView チェッカーには、設定ダイアログを組み込みます。セッション間でこれを閉じられるようにするため、このプロパティにダイアログ ボックスのロールアウトを格納します。これにより、グローバル変数に直接格納しなくても、このダイアログ ボックスにグローバルにアクセスできるようになります。

fn geomCheck theTime theNode theResults =
(

メインの xViewChecker 関数です。

xView チェッカー関数は、チェックを実行する時間、チェック対象のノード、チェックの結果を入れるための配列の 3 つの引数をシステムから受け取ります。

local theCount = case classof theNode of
(
Editable_Poly: getNumFaces theNode
Editable_Mesh: theNode.numfaces
)

ここでは、編集可能ポリゴン オブジェクトと編集可能メッシュの両方をチェックできるようにしたいので、この関数に渡されたノードのクラスをチェックし、適切なメソッドまたはプロパティを使用して面またはポリゴンのカウントを取得します。

local theAreaMethod = case classof theNode of
(
Editable_Poly: polyOp.getFaceArea
Editable_Mesh: meshOp.getFaceArea
)

同じくノードのクラスに基づいて、ユーザ変数にポリゴンまたは面の領域を取得するメソッドを格納します。これにより、メソッドへのアクセス速度が上がり、さらに以下のループで同じ式を使用して面領域を取得できます。

for f = 1 to theCount do
(

ノードのすべての面またはポリゴンをループします。

local theArea = theAreaMethod theNode f

ポリゴンまたは面の領域用にキャッシュしたメソッドを呼び出し、ノードと面のインデックスを渡します。

if theArea >= FaceAreaChecker.FaceAreaThresholdMin and theArea <= FaceAreaChecker.FaceAreaThresholdMax do append theResults f

次に、値を最小しきい値および最大しきい値と比較して、領域が 2 つのしきい値の間にあれば、面インデックスを結果の配列に追加します。

) 
3

xView チェッカーは、結果のタイプを示す整数を返す必要があります。

ここでは結果の配列に面のインデックスを格納したため、3 を返します。

その他の値には、2 (エッジ)、1 (頂点)、0 (チェック失敗)があります。

これは、その他の xView Checker システムが、結果の配列内にあるデータをビューポートでの表示に使用したり、結果をサブオブジェクト選択に変換したりする方法を識別するのに役立ちます。

),

fn supportedCheck theNode =
(
classof theNode == Editable_Mesh or classof theNode == Editable_Poly
),

サポート チェック関数は、xView Checker システムによって、ノードがこのチェッカーをサポートしているかどうかを判断するために呼び出されます。ここでは、編集可能メッシュと編集可能ポリゴン オブジェクトのチェックを可能にしたいので、ノードのクラスをチェックし、これらのクラスと比較しています。その他のオブジェクトはスキップされます。

fn configDlg =
(

この関数は、ユーザがビューポートの[ここをクリックして設定](Click Here To Configure)ボタンをクリックしたときに、xView Checker システムによって呼び出されます。この関数がチェッカーに登録されていない場合 (ただし代わりに undefined 値として渡された場合)、このビューポート ボタンは表示されず、システムはこのチェッカーでは設定ダイアログ ボックスがサポートされていないものとみなします。

try (destroyDialog FaceAreaChecker.faceAreaDialog)catch()

これまでに開いた可能性があるダイアログ ボックスをすべて閉じます。ダイアログ ボックスで使用されたロールアウトの割り当て先となる、構造体インスタンスのプロパティを使用します。

ダイアログ ボックスが開いていない場合には、何も起こりません。

rollout faceAreaDialog "Face Area Checker"
(

設定ダイアログ ボックスとして表示するロールアウトを定義します。

spinner spn_FaceAreaThresholdMin "Min. Threshold:" range:[0,1000000,FaceAreaChecker.FaceAreaThresholdMin] offset:[7,-3] type:#worldUnits
spinner spn_FaceAreaThresholdMax "Max. Threshold:" range:[0,1000000,FaceAreaChecker.FaceAreaThresholdMax] offset:[7,-3] type:#worldUnits 

このテストで使用する最小しきい値と最大しきい値をコントロールする 2 個のスピナーを定義します。どちらのスピナーも、構造体インスタンスの現在のプロパティに既定値で設定し、ワールド単位で表示されるようにします。もちろん、チェックは平方単位で行いますが、スピナーには通常の線形単位だけを表示します。このため、スピナーに 10" と表示されている場合、この値は 10 平方インチであると解釈されます。

fn updateDisplay =
(
XViewChecker.runCheck CurrentTime
max views redraw
)

この関数は、ユーザ インタフェース要素 (スピナー) の値が変化したときに呼び出されます。この関数は、現在の xView チェックを現在時刻で実行するメソッドを呼び出し、その結果としてチェッカーデータが更新されます。新しいデータを表示するには、すべてのビューポートを完全に再描画する必要があります。

on spn_FaceAreaThresholdMin changed val do
(
FaceAreaChecker.FaceAreaThresholdMin = val
updateDisplay()
) 

最小しきい値スピナーが変更されるたびに、新しい値を構造体インスタンスのプロパティに格納し、更新関数を呼び出してビューポートをリフレッシュします。

on spn_FaceAreaThresholdMax changed val do
(
FaceAreaChecker.FaceAreaThresholdMax = val
updateDisplay()
)   

最大しきい値スピナーで同じ処理を行います。

)--end rollout 

createDialog faceAreaDialog

この時点で、このロールアウトからダイアログ ボックスを作成します。ダイアログ ボックスのサイズは、ロールアウト内のコントロールのサイズに基づいて自動的に設定されます。

setDialogPos faceAreaDialog mouse.screenpos

次に、ダイアログ ボックスをマウス位置に移動します。 これにより、ユーザがビューポートで[ここをクリックして設定](Click Here To Configure)ボタンをクリックすると、マウス ポインタの横にダイアログ ボックスが表示されます。

FaceAreaChecker.faceAreaDialog = faceAreaDialog

最後に、構造体インスタンスのプロパティにロールアウト定義を格納します。これにより、ロールアウトの定義の前にダイアログ ボックスを閉じようとしても、正しい値にアクセスされます。

) )--end struct

try (destroyDialog FaceAreaChecker.faceAreaDialog)catch()

このダイアログ ボックスを閉じようとする試行処理は、スクリプトの開発時にソースを何度も再評価する場合に便利です。 スクリプトを実行するたびに、これまでに開いたダイアログが閉じられます。この処理を行わない場合、テスト中にいくつものダイアログ ボックスが取り残されることがあります。

FaceAreaChecker = FaceAreaCheckerStruct()

ここでは、ローカル構造体のインスタンスを作成し、グローバル変数に割り当てます。これにより、その他のスクリプトまたはリスナーがこの構造体インスタンス内のプロパティと関数にアクセスできるようになり、開発やデバッグが簡単になります。

XViewChecker.unRegisterChecker "Face Area Checker"

名前により xView チェッカーを登録解除します。同じコードが複数回実行された場合、前のバージョンを削除してからこれを再登録するようにします。

XViewChecker.registerChecker FaceAreaChecker.geomCheck FaceAreaChecker.supportedCheck #Faces "Face Area Checker" FaceAreaChecker.configDlg undefined undefined

最後に、xView Checker システムに作成したチェッカーを登録します。

1 番目の引数はシーン オブジェクトをチェックするために呼び出す関数です。

2 番目の引数は、シーン オブジェクトがチェック可能かどうかを判定するために呼び出す関数です。

3 番目の引数は、チェッカーのタイプ (面、エッジ、頂点のいずれに対して機能するか) を定義します。これは、選択変換で、結果の配列の内容を正しいタイプのサブオブジェクト インデックスとして解釈するために必要です。

4 番目の引数はチェッカーの名前です。これは、リストおよびビューポートにチェッカーを表示するためと、登録解除するときに名前でチェッカーにアクセスするための両方に使用されます。

5 番目の引数は、[ここをクリックして設定](Click Here To Configure)ボタンがクリックされたときに呼び出される関数です。ダイアログ ボックスが不要な場合は、undefined として渡すことができます。

6 番目の引数は、ビューポートでチェッカーの名前の横に表示されるテキストを上書きするために呼び出す関数です。現時点では、テキストの上書きは行わないため undefined を渡します。この関数は、チュートリアルの次の部で実装します。

最後の引数は、既定値の表示機能を上書きするために呼び出す関数です。ここでは、既定値の表示機能を使用するため、同じく undefined を渡します。この関数は、チュートリアルの次の部で実装します。

)--end script

xView チェッカーの使用

現時点で、Ctrl+Eを押すとコードが評価され、xView チェッカーを使用できますが、ビューポート メニューにはまだ表示されません。

新しいチェッカーを表示するには、たとえば、[面方向](Face Orientation)などの他の xView チェッカーを有効にし、ビューポートの下部にある[面方向](Face Orientation)ラベルをクリックして、登録されているチェッカーのリストを表示します。Face Area Checker がそこに表示されます。

リストからこれを選択して有効にします。

画面の下部にラベル[Face Area Checker]が表示され、有効なオブジェクト(編集可能メッシュまたは編集可能ポリゴン)が選択されると、面/ポリゴンがテストされ、ビューポートでシェーディングされます。

最小および[最大](Max)しきい値を構成するには、[ここをクリックして設定](Click Here To Configure)ラベルをクリックします。

今後の 3ds Max セッションで、スクリプトを手動で評価しなくてもこのチェッカーを使用できるようにするには、スクリプトを ¥Startupフォルダ、もしくはプラグイン パスとして登録されているフォルダまたはそのサブフォルダにコピーします。

カスタムの xView チェッカーをビューポート メニューに追加する方法は、このチュートリアルの第 4 部で説明します。

次へ

チュートリアル - 面領域 xView チェッカーの開発 - 第 2 部

関連事項