Softimage 頂点を渡すとグローバルの座標が戻される関数

ツイッタ―でJunkiさんから「XSIのスクリプトで頂点のグローバル座標の値を取得する方法」というお題が上がったので勉強がてらに調査。TERAさんが光の速度で「Mathの中に、”MapObjectPositionToWorldSpace” というメソッドがある」ということを突き止めたので無事解決かと思いきや、どうやらMapObjectPositionToWorldSpaceメソッドはグローバル座標ではなく「直接の親からの相対値」を戻す仕様であることが判明。
SDKには「指定されたObjectSpaceで記述された位置を、WorldSpaceに変換します。」って思いっきり書いてるのに…。Autodeskの凡ミス?

■追記
どうやら、SDKのサンプル構文が親のオブジェクトのLocal座標系を取得していたようで、きちんとMapObjectPositionToWorldSpaceメソッドでもグローバル座標取得出来たッス…。
こんなかんじ↓↓↓

var oObj = Selection(0);
var oGeometry = oObj.ActivePrimitive.Geometry
var oTrans = oObj.Kinematics.Global.Transform;
var oPos = oGeometry.Points(0).Position;
var oGlobalPos = XSIMath.MapObjectPositionToWorldSpace( oTrans, oPos);

Application.LogMessage ("The world position is: X "+ oGlobalPos.X + " Y " + oGlobalPos.Y + " Z " + oGlobalPos.Z);

自分の関数は頂点情報渡すだけでグローバル返ってくるっていう利点があるって事にしとく…orz




※上記画像はJunkiさんのツイッタ―から拝借しました。

とにかく、そんなこんなで自分で関数書いてみました。

//頂点を渡すとグローバルの座標が戻される
function GetGlobalData(in_Point){

	//頂点
	oPointTransform = XSIMath.CreateTransform();
	var oPos = in_Point.Position;
	oPointTransform.SetTranslation( oPos ) ;
	var oPoint_Mat4 = oPointTransform.Matrix4;//行列に変換


	//頂点が属するオブジェクト
	oParentObj = in_Point.Parent.Parent.Parent;//3DObject取得(スマートな取得の仕方がパッと出てこない)
	//行列を取得
	var oParentObj_tf = oParentObj.Kinematics.Global.Transform;
	var oParentObj_Mat4 = oParentObj_tf.Matrix4;

	//頂点の行列とオブジェクトの行列をかけ合わせて 目的のグローバル行列を作成する
	var oMat4 = XSIMath.CreateMatrix4();
	oMat4.Mul(oPoint_Mat4,  oParentObj_Mat4);

	//各要素に分解する。
	oNewTransform = XSIMath.CreateTransform() ;
	oNewTransform.SetMatrix4( oMat4 );

	//移動
	var oVector_pos = XSIMath.CreateVector3();
	oNewTransform.GetTranslation( oVector_pos ) ;

	//回転
	var oVector_rot = XSIMath.CreateVector3();
	oNewTransform.GetRotationXYZAngles( oVector_rot ) ;
	
	return oNewTransform

}


こんな感じで使います。

var oObj = Selection(0);
var oGeometry = oObj.ActivePrimitive.Geometry;
var oPos = GetGlobalData(oGeometry.Points(0));

logmessage(oPos.posx);
logmessage(oPos.posy);
logmessage(oPos.posz);

連番画像をブラウザで再生する

前回の記事で作ったSoftimageから書き出した透過PNGをブラウザで確認できるようにしたいと思います。
確認といっても、画像をズラーっと並べるよりも、動画のように再生出来た方が良いだろうということで、そちらに挑戦してみます。

前回記事

連番画像を再生するということでパッと思いつくのが

だったんですが、SoftimageからGIFアニメーションを生成できないし、フリーソフトとかを使って作れたとしても色数の制限であまり見た目も良くないということで却下。
動画は何かしらで出来るかもしれないけど画像を別々に観ることが出来なくなるし、透過処理も出来ないのでこれもナシ。
結局行きついた答えはPHP&jQueryでした。
PHPは「サーバーサイドスクリプト言語」、jQuery(ジェイクエリー)は、「現在人気のあるJavaScriptライブラリの1つ」ですね。
お恥ずかしいことに自分はjQueryの存在を最近知りました。
PHPjavascriptは専用の書籍やサイトが沢山あるのは知ってたんですが、最近本屋に行くとjQuery専用書籍がかなり出ていてビックリしました…。
大したことができない自分でも使って便利さを実感。こりゃもう手放せないって状態です!
話がそれました…。
今回作った実際に動作するサンプルが以下になります。

使用している画像はhttp://www16.tok2.com/home/guttari8/からお借りしました。感謝!
今回の連番画像を再生するにはどうするかと言うことですが、ざっくり説明すると

jQuery(javascript)を使って一定時間間隔で画像の表示を変更する
  ↓  ↓  ↓  ↓
しかし、クライアント側のスクリプトであるjavascriptからはどのような連番素材があるか分からない
  ↓  ↓  ↓  ↓
そこでPHPを使って連番素材のリストを作成しjavasecriptに伝達

というカラクリです。
今回参考にさせてもらったのは以下のサイトです。

参考ページと今回自分がやろうとしていることで違う点は、「切り替える画像の枚数、名前が不確定」「フェードインはいらない」ですね。
その辺りを考慮すると以下のようなソースになりました。
(単純にするためにサンプルよりもシンプルな内容にしています。)

<!--
################################################################
######################### HTML #################################
################################################################
-->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>PHP & jQuery 連番画像再生テスト</title>
<script src="jquery-1.7.2.min.js"></script>
</head>
<body>
	<td bgcolor=#ffffff id="gallery"><img src="img/1.jpeg">透過</td>
</body>
</html>

<!--
################################################################
#####################   javascript  ############################
################################################################
-->
<script type="text/javascript">
	//画像を切り替える速さ
	imgChangeSpeed = 50;

	//画像配列
	imgArray_png = new Array();//PNG

	<?php
		//PHPでディレクトリ内を検索、javascriptの配列としてデータを受け渡す
		$dir = "img/FumeFx_image_sq005/";//画像が置いてあるフォルダ
		$file_list = get_filename_arr($dir, "/\.png$/");//拡張子がpngのものだけ
		foreach( $file_list as $value ){
		  echo "imgArray_png.push(\"" . $dir  . $value . "\");\r\n";//javascirptの構文を出力
		}
	?>

	//最初に表示する画像
	randomInt = 0;

	$(function(){
	    //一定時間毎にスクリプトを呼び出す
	    var t = setInterval(loadImg, imgChangeSpeed);
	    //呼び出されるスクリプト
	    function loadImg(){
			
			//画像を切り替える処理
	        $("#gallery").children("img").animate({'opacity':'0'},  0)
	        $("#gallery").children("img").attr("src",function(){ return imgArray_png[randomInt] }).animate({'opacity':'1'}, 0);
	        
	        if(randomInt < imgArray_png.length){
	            randomInt = parseInt(randomInt) + 1;
	        }else{
	            randomInt = 0;//配列の先頭に戻る
	        }
	    }
	});
</script>


<!--
###############################################################
#####################      PHP     ############################
###############################################################
-->
<?php
//第1引数 : 対象ディレクトリのパス
//第2引数 : ファイル名の正規表現(マッチしたファイル名を取得)
function get_filename_arr($dir, $match) {
    $filename_arr = array();
    $dh = opendir($dir);
    while(($filename = readdir($dh)) !== false) {
        if(preg_match($match, $filename)) {
            $filename_arr[] = $filename;
        }
    }
    asort($filename_arr);//昇順ソート
    return $filename_arr;
}
?>

ポイントとなるのはjavascript内にあるPHPの構文です。

	//PHPでディレクトリ内を検索、javascriptの配列としてデータを受け渡す
	$dir = "img/FumeFx_image_sq005/";//画像が置いてあるフォルダ
	$file_list = get_filename_arr($dir, "/\.png$/");//拡張子がpngのものだけ
	foreach( $file_list as $value ){
	  echo "imgArray_png.push(\"" . $dir  . $value . "\");\r\n";//javascirptの構文を出力
	}

PHPでフォルダ内の連番ファイルの一覧を取得して、javascriptの構文を出力しています。
こうすることで、ブラウザが表示された際にjavascriptの構文が生成され、画像の切り替えが行えるわけですね。
実際にブラウザがページを表示された時には上記の構文が以下のように変わります。

	imgArray_png.push("img/FumeFx_image_sq005/0000000.png");
	imgArray_png.push("img/FumeFx_image_sq005/0000001.png");
	imgArray_png.push("img/FumeFx_image_sq005/0000002.png");
	imgArray_png.push("img/FumeFx_image_sq005/0000003.png");
	imgArray_png.push("img/FumeFx_image_sq005/0000004.png");
	imgArray_png.push("img/FumeFx_image_sq005/0000005.png");
	imgArray_png.push("img/FumeFx_image_sq005/0000006.png");
	imgArray_png.push("img/FumeFx_image_sq005/0000007.png");
	imgArray_png.push("img/FumeFx_image_sq005/0000008.png");
	imgArray_png.push("img/FumeFx_image_sq005/0000009.png");
	imgArray_png.push("img/FumeFx_image_sq005/0000010.png");
	imgArray_png.push("img/FumeFx_image_sq005/0000011.png");
				・
				・
				・

今回は配列のpushを使ってますが、javascriptに情報が伝達できればどのような手法でも多分良いと思います。
フェードインが入らないという部分ですが

$("#gallery").children("img").attr("src",function(){ return imgArray_png[randomInt] }).animate({'opacity':'1'}, 0);

の最期の0の数字を変更しました。これであたかも画像がアニメーションしているように再生してくれるようになりました。
背景の色や画像を変更すれば、どのように透過されているかも確認することが出来ます。
javascriptで背景を変更するのは良く行われていますから、それと組み合わせると良いかもしれません。
PHPの部分も読み込む対象のフォルダを変更すれば、様々なケースに対応できます。
ただ、今回インターネット上にサンプルを上げた際に、当初上手く画像が表示されませんでした。
iPhoneだと大丈夫だったのでデスクトップPCがへっぽこなのかもしれませんが…。
どうやら画像切り替えの間隔が短すぎて、画像を読み込み切れていないのが原因だったようです。
なので、アニメーションさせている下側に元画像の一覧を表示することで、安定した動作をさせるように工夫してみました。
まだ気づいてないだけで、いろいろ課題はありそうな予感です…。

Softimage ブラウザで表示できる画像(アルファチャンネルも確認可能)を書き出す。

Softimageからブラウザで使える画像を書きだすということをやったのでご紹介。
今回の要点は

  1. モデルに貼られているテクスチャ(連番含む)を抽出・書き出す。
  2. SIではTGA/PSD/PICなどなど色々な形式がサポートされているが、ブラウザで必ずしも表示できる形式とは限らない。むしろ出来ない物の方が多いので、形式を統一する。
  3. ブラウザでもアルファチャンネルでどうテクスチャが透過されているのか知りたい!

以上、3点ですね。d(≧▽≦*)

まずは、1ですが今回対象となるのはテクスチャとしてはり込まれた画像のみです。
Picturesフォルダにはあるけど、モデルには貼られていないものなんかがあった場合はなにかしら対処が必要だと思いますが、今回は触れません。
あとは、似た方法でレンダリングした画像にも同じこととかできるかもしれませんね。(試してませんが)

で、肝心のテクスチャのファイルを抽出・書き出しですが、オブジェクト内のマテリアルから繋がっているノードを辿って…という方法も考えられますが、
ぶっちゃけメンドクサイので標準装備のdotXSI書き出し機能を使用します!!
実はdotXSI書き出し機能には、テクスチャの書き出しと書きだした画像形式のフォーマット変更まで付いています。
これで1と2の用件を同時に満たせるわけです。
といいますか、画像の形式を変更するなんて自分の知識ではできんのですよ…。 A=´、`=)ゞアセアセ...

実際のスクリプトは簡単なので、特に書きません。
ただ書き出し前にはちょっと面倒なdotXSIの設定をしないといけないので、その関数を載せときますね。

//dotXSIOptionの設定を行う
function Setup_dotXSIOption(in_TextureSize,in_TextureFormat){

	//dotXSIの書き出しオプションを取得
	var dXEOp = Dictionary.GetObject("dotXSIExportOptions");

	dXEOp.output_file_format.value = 1;	//出力形式アスキー
	dXEOp.output_file_format_version.value = 360;	//バージョン

	//////ジオメトリグループ//////
	dXEOp.sceneroot.value = 0;	//選択がない場合にシーンルートを書き出す
	dXEOp.polymesh.value = 1;	//ポリゴンメッシュ
	dXEOp.nrbssrf.value = 0;	//NURBSサーフェイス
	dXEOp.user_normals.value = 0;	//ユーザ法線
	dXEOp.nrbscrv.value = 0;	//NURBSカーブ
	dXEOp.tesselation.value = 0;	//ポリゴンタイプ

	//////アニメーショングループ//////
	dXEOp.animall.value = 0;	//すべて
	dXEOp.animgeom.value = 0;	//ジオメトリ
	dXEOp.animcam.value = 0;	//カメラ
	dXEOp.animlight.value = 0;	//ライト
	dXEOp.animmat.value = 0;	//マテリアル
	dXEOp.animenv.value = 0;	//アンビエンス
	dXEOp.animaction.value = 0;	//アクション

	//////アニメーションフィルタリンググループ//////
	//プロット
	dXEOp.animplot.value = 0;
	//プロットしない場合は以下のチェックボックスは無効のため設定しない。

	//////関係グループ//////
	dXEOp.constraint.value = 0;//コンストレイント
	dXEOp.envelope.value = 0;//エンベロープ
	dXEOp.ik.value = 0;//IK

	dXEOp.custompset.value = 0;	//カスタムパラメータセット
	dXEOp.keep_shared_mat.value = 0;	//共通マテリアルの保持

	///////テクスチャグループ///////
	dXEOp.textures.value = 1;//テクスチャ
	dXEOp.txtabsolute.value = 0;	//絶対パス
	dXEOp.txtsequences.value = 0;	//シーケンス
	dXEOp.txtfiles.value = 1;	//ファイルのコピー
	dXEOp.txtformat.value = in_TextureFormat;	//ファイル形式
	dXEOp.txtresizeX.value = in_TextureSize;	//Xサイズ
	dXEOp.txtresizeY.value = in_TextureSize;	//Yサイズ

}

今回はテクスチャを書き出すことだけが目的ですから、不必要なものは書き出さないようにしています。書き出し時間が延びるだけですしね。
ポイントとしてはポリゴンメッシュは書き出すこと。
これを書き出さないとテクスチャも道ずれで書き出してくれません。
あとは、テクスチャグループのシーケンスを有効にすること。
テクスチャアニメーションなどが設定されている場合、これで一括して書き出してくれます。
dotXSI書き出し前に以下のような感じで使って下さい。

Setup_dotXSIOption(1,4);

引数としては

in_TextureFormat 1:オリジナル
2:PIC
3:BMP
4:PPM
5:TGA
6:JPEG
7:TIM2
in_TextureSize 1:オリジナル
2:自動
3:2pixel
4:4pixel
5:8pixel
6:16pixel
7:32pixel
8:64pixel
9:128pixel
10:256pixel
11:512pixel

となっています。
テクスチャのサイズは縦横比を維持したい場合は、XかYを自動にしておくとよいでしょう。
dotXSI書きだし設定から選択できる画像形式の中でブラウザで表示できる形式はJPEGくらいですね。
単純にブラウザで表示するのであればここまででOK!!しかし、今回は3の要件もあるので、JPEGでは役者不足。
アルファチャンネルが消えてしまいます。
そこでひとまず書き出しの際に選択できる形式の中で、アルファチャンネルが保持できてなおかつメジャーな画像形式ということでBMPを選択。
ここからさらにブラウザで表示でき、なおかつ透過できるPNG形式にしようという魂胆であります。(゚ー゚)ニヤリ

まず試みたのはPHPに内包されているGDライブラリという画像処理用のライブラリ(?)
しかし、問題が幾つか。一つ目は、BMPとWBMPがなんとか…詳しくは良く分からんですが、どうやらBMP形式がサポートされてないらしい。
しかし、インターネットの海は広いですから誰かそれらしいの公開してるだろうということで探してみたら

というものを発見。早速PHPに組み込んで試してみたところ、見事BMPPNGに変換成功!!
やったーーーーーーーーー!!
と喜んだのもつかの間、出来あがったPNGは透過データが吹っ飛んでました。��q|゚Д゚|p
拾ってきたものの中身を変更するスキルなんて当然ないので、PHPでの画像形式変換はきっぱりと諦め、作戦変更。別の手を探すことにしました。

次に考えたのがフリーソフト
コマンドラインから使える画像形式変換ツールがあれば、Softimageからバッチファイルを生成してdotXSI書き出し後に、一括変換、ウマーーーー。という流れ。
探したらピッタリなのがありました。

コマンドプロンプトを立ち上げて

(ソフトが置いてあるパス)\BMP2PNG.EXE -A (処理対象のフォルダ)/*.bmp

という感じに使います。これで透過済みのPNGファイルの出来あがり!!
ブラウザにファイルを放り込めば透過された画像が表示されてるのが確認できるはず。
Softimageから使うときは以下のようなものになります。
(手持ちに関数なかったのでババっと書いたので、エラー出るかも…)

//コマンドライン版 BMP ←→ PNG コンバータを使用してフォルダ以下のBMPファイルを一括でPNGに変換する
//in_Dir:処理対象フォルダパス
function BMP2PNG(in_Dir)
{
	//コマンドライン版 BMP ←→ PNG コンバータのパス
	var BMP2PNG_EXE = "パスを設定";
	//バッチファイルパス
	var BatPath = Application.InstallationPath( siUserPath )+ "\\Application\\Plugins\\BMP2PNG.bat";

	//バッチファイル内に記述する文字列
	var BatString = BMP2PNG_EXE + " -A" + in_Dir + "\\*.bmp";

	//バッチファイルを作成
	var oFso = new ActiveXObject("Scripting.FileSystemObject");
	var ScriptFile = BatPath;
	var file = oFso.OpenTextFile(ScriptFile, 2 , true);
	file.WriteLine(BatString)
	file.Close();
			
	//バッチファイルを実行
	var WshShell = new ActiveXObject("WScript.Shell");
	WshShell.Run( BatPath , 4, true );
	
	//バッチファイルの削除
	oFso.DeleteFile(BatPath,1);
	
	return
}

Jscriptから直接コマンドラインの操作は出来ない(と思う)ので、バッチファイルを作成。
それを実行することでコマンドラインから使用するソフトを操作します。
バッチファイルの実行が終わるまで、処理を次に回さないようにしています。
これをやらないと、外部ソフトの動作が終わってないのに次の処理に進んでしまい処理が上手く行かなくてエラーがでるかもです。
後は、この関数内には元のBMPファイルを削除する処理は書いてないので、場合によっては追加が必要ですね。
ちなみに、今回使用したフリーソフトのような実行ファイルのみで動くようなソフトは、インストールしてもらう手間が無く、サーバーにポンっと置いておけば使うことが出来るのが利点ですね。

長々となりましたが、まとめると

  1. dotXSIでBMPを一括書き出し。(シーケンスのチェックを入れることで連番テクスチャにも対応)
  2. コマンドライン用ソフトをSoftimageから使う為にバッチファイルを作成
  3. バッチを実行、コマンドラインBMP ←→ PNG コンバータを使用してフォルダ以下のBMPファイルを一括でPNGに変換
  4. ブラウザで表示可能な画像ファイルの完成!!
  5. 必要であれば元のBMPファイルを削除

こんなところでしょうか。
なにか間違い等あれば教えて下さい。m(。-_-。)m

Softimage JScriptからクリップボードを使う

UseClipboard("文字列を渡す\r\n改行もできる");


//クリップボードに文字列コピー
function UseClipboard(in_stg){
	// クリップボードに文字列を設定
	var jp;
	if (!jp) jp = {};
	if (!jp.raindrop) jp.raindrop = {};
	if (!jp.raindrop.frog) jp.raindrop.frog = {};
	jp.raindrop.frog.clipboard || (function ()
	    {
	        // コマンドのID
	        var OLECMDID_COPY = 12;
	        var OLECMDID_PASTE = 13;
	        var OLECMDID_SELECTALL = 17;

	        // IE の初期化
	        var _internetExplorer = new ActiveXObject ('InternetExplorer.Application');
	        _internetExplorer.navigate ("about:blank");
	        while (_internetExplorer.Busy)
	            WScript.Sleep (10);

	        // textarea 要素を作成する
	        var _textarea = _internetExplorer.document.createElement ("textarea");
	        _internetExplorer.document.body.appendChild (_textarea);
	        _textarea.focus ();

	        jp.raindrop.frog.clipboard = {
	            // クリップボードに文字列をコピー
	            setText: function (text)
	            {
	                _textarea.innerText = text;
	                _internetExplorer.execWB (OLECMDID_SELECTALL, 0);
	                _internetExplorer.execWB (OLECMDID_COPY, 0);
	            },

	            // クリップボードより文字列を取得
	            getText: function ()
	            {
	                _textarea.innerText = "";
	                _internetExplorer.execWB (OLECMDID_PASTE, 0);
	                return _textarea.innerText;
	            },

	            // IE を解放
	            release: function ()
	            {
	                _internetExplorer.Quit ();
	            }
	        };
	    }());


	//
	jp.raindrop.frog.clipboard.setText (in_stg);
	
}

アクションファイルを解析してマッピングテンプレート作成


アクションファイルを読み込む際に、読み込む先に要素が存在しない場合
マッピングテンプレートのUIが出て確認を求められるのがすご〜く邪魔でした。
特に自動処理とかの場合はそこでとまってしまって処理が先に進まないのが問題。
(なぜか無視して強制的に進ませるオプションは用意されてない…。)

ということで、

 アクションファイルを直接解析
   ↓↓
 読み込み先のモデルヌル以下と比較
   ↓↓
 モデルヌル以下に存在しないものは無視できるようにマッピングテンプレートを作成する

という関数を作りました。
これで邪魔なUIとはオサラバ!!ヾ(@⌒▽⌒@)ノワーイ!

使い方は

 MakeMappingTemplate(oModel,ActionFile)
oModel:アクション読み込みモデルのオブジェクト
ActionFile:読み込むアクションファイルのパス)



という感じ。
ファイルを解析してるだけなので、dotXSI形式(テキスト)にのみ対応してます。
(ファイルを見てエラー処理とかしてないので、必要だったら追加してください)

もちろんアクションを読み込んでから比較しても良かったんですが、
ImportActionAndAddClipコマンドを使いたかったのでこういう形にしてみました。



関数は↓↓↓です。
必要な人はそんないないと思いますが、必要でしたらドゾー!!!



//マッピングテンプレートを作る関数(本体)
function MakeMappingTemplate(oModel,ActionFile)
	//空のマッピングテンプレートを作成
	vtcol = CreateEmptyConnectionMap( oModel, null );
	var oMappingTemplate = vtcol.Value("MappingTemplate");

	//アクションファイルからFカーブ要素を取得
	var ObjList = GetObjectList_forActionFile(ActionFile);

	if(!ObjList)return null;

	//インポート先に存在しないものだけテンプレートに追加していく
	for(var i = 0; i < ObjList.length; i++){
		var oParam = Dictionary.getobject(Selection(0) + "." + ObjList[i],false);
		if(oParam == null)AddMappingRule( ObjList[i],  ,null )
	}
	return oMappingTemplate;
}

//*******************************************************************************************************************

//アクションファイルを解析、Fカーブの要素リストを戻す
function GetObjectList_forActionFile(in_FilePath){

	var objFso = new ActiveXObject("Scripting.FileSystemObject");

	//リストストック用
	var ObjList = new Array();

	if (!objFso.FileExists(in_FilePath))return false;

	//ファイルを開く
	var objTs = objFso.OpenTextFile(in_FilePath,1,false);
	
	//ファイル末尾まで繰り返す
	var flg = false;
	while (!objTs.AtEndOfStream){
	
		var Line = objTs.ReadLine();//1行読み込む
		Line = trim(Line);//空白の削除
		if(Line.indexOf("SI_FCurve") != -1)flg = true;//Fカーブの要素が来たら処理開始
		if(flg == false)continue;
		
		//Fカーブ要素内のデータが2つ溜まるまで読み込む
		var FCurveData = "";
		while (FCurveData.split(",").length < 3){
			FCurveData  += trim(objTs.ReadLine());//1行読み込む
		}
		
		//余計な物を削除してリストに加える
		ObjList.push(FCurveData.split(",")[1].replace(/\"/g,""));
		
		var flg = false;
	}
	objTs.Close();
	
	return ObjList

}

//*******************************************************************************************************************

//トリム
function trim(argValue){
	//半角スペース 全角スペース タブ を文字列から排除する
	var stg = String(argValue).replace(/[  	]*/g, "");
	//『/* */』こんなコメントを削除
	stg = String(stg).replace(/\/\*.+\*\//, "");
	//『//』こんなコメントを削除
	stg = String(stg).replace(/\/\/.+/, "");
	return stg
}

新しくNULLを作って、選択していたオブジェクトのコンストレイントを引き継ぐ(多分全て)

[Softimage Script]
使えるかわかんないけど書いてみた。
全部のケースを試してないし、エラーチェックもしてないので上手く動かないケースもあると思います。

■使い方

  1. オブジェクトを選択
  2. 実行
  3. シーンルート以下に新しいヌルが出来てコンストレイントの状態がコピーされてる
var oSel = Selection;

for(var i = 0; i < oSel.count; i++){

	var newNull = ActiveSceneRoot.AddNull(oSel(i).name + "_copy")

	//ストレインオブジェクトを取得
	var cnslist = oSel(i).Kinematics.Constraints;
	for(var j =0; j < cnslist.count; j++){
		//同じコンストレイントを張る
		var ConsType = cnslist(j).name.split(" Cns")[0].replace(/[  	]*/g, "");
		var newCons = newNull.Kinematics.AddConstraint(ConsType ,cnslist(j).Constraining);
		//パラメータの状態をコピー
		for(var k = 0; k < newCons.Parameters.count; k++){
			newCons.Parameters(k).value = cnslist(j).Parameters(k).value;
		}
		//めんどくさいのでコピペ 
		CopyAnimation(cnslist(j))
		PasteAnimation(newCons)
	}
}

【Softimageスクリプト講座】第1回 初めてのスクリプト

『アーティストによるアーティストの為のSoftimageスクリプト講座』が長すぎるので、今回から『Softimageスクリプト講座』に早速改名してみました。今回から実際にスクリプトを記述していきたいと思います。
初めてのスクリプト、これは『"Hello, world!"と表示する』と相場は決まっています!大抵のプログラミング言語の入門書では、最初の例題がそうなってます。何故かは知りませんが、そういうもんらしいです。
スクリプトを扱うにはいろいろな事を覚えなくてはなりませんが、初めはあまり難しく考えず『へぇ〜そういうもんなんだな〜』とゆる〜く捉えておきましょう。100%理解ようとすると疲れます。 自分も書いてる事100%完璧に理解しているかと聞かれれば怪しいものです。たとえその時に分からないことも、なんとなく掴んでいればその内勝手に分かってきます。『まずは形から』これも結構重要なのではないかと個人的には思っています。
では早速実践といきましょう。まずは下準備です。画面中央下にある紙のようなアイコン、まずはこのボタンを押してみてください。

ボタンを押すと下のようなウインドウが表示されたかと思います。これがこれから長いことお世話になるScript Editor(スクリプトエディタ)です。

次にJScriptをSoftimageで使うための設定を行います。手順は簡単です。Script Editorから直接切り替えが可能です{Softimage2010以前のバージョンではScript Editorのファイル(File)>設定(Preferences)を開き、 Scriptingタブで ScriptLanguage をJScript Language を選択します。)

文字の出力

今度は実際にスクリプトを記述していきましょう。Script Editorの画面下、白部分がスクリプトを記述する部分となっています。名前は『編集ペイン』です。上半分は操作のビュー上でのログなどが表示されていきます。名前は『ヒストリペイン』です。
編集ペインに以下のコード(スクリプトの文章のことはソースコード(設計図)と呼ばれます。)を記入してください。意味は分からなくて問題ありませんし、コピペでOKです!

 logmessage ("Hello, world!");

実際書きこんだ状態はこんなかんじです。

記述できたらScript Editor上部の『実行(Run)』ボタンを押して下さい。

どうでしょう?ボタンを押すことでスクリプトが実行され、ヒストリペインに『Hello, world!』と表示されたでしょうか?これで初めてのスクリプト完了です!!(゚∀゚)キタコレ!! 

※ログが表示されなかった場合は、ログを表示しない設定になっている可能性があります。スクリプトエディタのファイル>設定を実行し、表示されたウインドウ内のコマンドログという部分を以下のように設定してください。設定後、スクリプトを再度実行すればログが表示されたはずです。

「なぜこれがこうなったのか?」は次回説明します。今回は「スクリプト書いたどーー!!」ということに満足しとくということで。なんかすごく内容的に薄っぺらいですが、自分が飽きないようにボチボチいきますのでー。それではまた次回〜♪(。>ω<。)ノ