なたで日記

いろいろな思ったこと書きますヽ(^▽^ゞ) by natade

Archive for the ‘game’ Category

セカンドライフのスカイボックスに太陽の光を!

leave a comment »


スカイボックスをご存知でしょうか。

セカンドライフでは地面の上に家をたてる場合と、
4000mまでの上空の間に家を浮かばせるスカイボックスがあります。

スカイボックスの最大のメリットとしては、
周りの情景に気にせず好きなものを建てられるということです。

通常、地面の上に建てる場合、お隣さんの家に気を使ったりして大きな建物を建てられなかったり、
あるいは雪の土地の上であれば、冬っぽい家を建てないと気分がでないなど
様々な制約があるのですが、スカイボックスは、自分で地面から作成して、
周りの風景まで画像を張ったりすることで楽しむこともできます。
中から外へのボックスが透過にし、解放感も味わうこともできます。

しかし1つ問題があります。
それは太陽の光をあびれないということ……。

スカイボックスは、プライバシーのために箱で包むことがよくあるのですが、
解放感を出すため内部から外へは透明にすることがよくあります。
一見、外の空が見えるので、解放感はあるのですが、なぜだか内部が暗くなってしまいます。
それは、影のせいです。

例えばですが、次のように立方体を設置すると影がでます。
secshadow1

ここで、影側のほうから壁を透明にした場合でも、やはり影ができてしまうのです。
secshadow2
スカイボックス内で内部から外を透過して解放感を出しても、
外からの光は残念ながら中に入らないのです。

 

 

実はテクニックがありまして・・・

 

 

テテーン!
secshadow3

さて、どのようにして影を出さないようにしたのでしょうか。

実は、外側のテクスチャを微妙に透過させることで、
影を出さないようにしたのです。
調査した結果、12%の透過度にすると影がでなくなるようです。

少しは透けてしまうようになるのですが、
大体中は見えないですし、二重にすることでより見づらくすることもできます。

こんな感じに
secshadow4

以上、スカイボックスの中に太陽の光を!でした。

Written by なたで

2016年4月21日 at 00:00

カテゴリー: game, memo

Tagged with ,

セカンドライフのサードパーティビューア Black Dragon の紹介

leave a comment »


ビューア関係の前回の記事「セカンドライフのサードパーティビューア Catznip の紹介」では
土地の境界線表示機能付きのカラフルなミニマップ表示
自分のオブジェクト一覧表示機能
・容姿にフォルダ構造を持たせられる機能
など他のビューアにはない機能を持つ「Catznip Viewer」について紹介しました。

今回は、「Black Dragon」(ブラックドラゴン)を解説します。


Black Dragonはグラフィック設定がすごい!

Black Dragonの最大の特徴は、3DCGの表示機能設定が豊富な点です。
設定できる機能の一部を紹介します。
.

テクスチャのメモリの最大値の増加

ここのメモリの容量が大きいほど、テクスチャが汚くなりません。
しかし通常、テクスチャはグラボにグラフィックメモリが何GBもつんであっても、最大512MBしか設定できません。
Black Dragonでは、グラフィックメモリの最大値を8GBまで設定することができます。
.

FXAAのアンチエイリアスが有効

これを有効にすると、ジャギー(2D座標空間の標本化歪み)が目立たなくなります。
通常のビューアでは、アンチエイリアシングは FSAA 2x/4x/… などが利用できます。
このアルゴリズムは、SSAA(Super Sampling Anti-Aliasing, Full-Scene Anti-Aliasing)を使用しています。
SSAAは綺麗にはなるのですが、大きな画面として描写するため処理が重たくなります。
一方、ここでは使用できませんが、MSAAというものあり、
MSAAは、SSAAより軽いですが、テクスチャ自体にはアンチエイリアスをかけられない特徴があります。

今回、このビューアではFXAAが利用できます。
FXAAの最大の特徴は、3DCGを描写後に行うアンチエイリアスという点です。
品質は、SSAAより悪いですが、動作は非常に軽く、MSAAと違いテクスチャ自体のギザギザも抑えられます。
それぞれの特徴については、「4Gamerの記事」を参照。
.

影テクスチャを細かく設定できる

通常のビューアでは、影の設定を「太陽/月・プロジェクタ」という1つの設定しかありません。
しかし、Black Dragonでは影の設定を細かく設定できるため、綺麗に影を落としこむこともできます。
例えば影を落とすために、シャドウマッピング用にテクスチャを用意するのですが、
このテクスチャの解像度によって、影の品質がきまります。
Black Dragonでは、このテクスチャの縦と横の大きさを自由に設定できます。
あまりに大きいと、グラフィックメモリを使用するので注意が必要です。
また、解像度以外にも、このテクスチャから
何点のポイントを使用して平均化し影をつけるかの設定ができます。(ソフトシャドウ技術
この設定を行うことで、はっきりした影や、ぼやけた影の表現もできます
.

SSAOの詳細設定ができる。

物をリアルに表示させるために明暗をつける
アンビエントオクルージョンというテクニックがあります。
例えば、近くに物があれば、その物の近くにあるオブジェクトを暗くする機能です。
通常のビューアでは「アンビエントオクルージョン」という1つのチェックボックスですが、
Black Dragonでは、Screen Space Ambient Occlusionの設定項目で、詳細設定が可能です。
ここの設定は重たくなる原因なので、チェックを外すのもアリだと思います。
.

DoFの詳細設定ができる。

DoF(Depth of Field)という技術があります。
これは、ある距離より遠いものや近いものをぼかして、被写界深度を再現します。
通常のビューアでは「フィールの遠近感」という1つのチェックボックスですが、
Black Dragonでは、Depth of Fieldの設定項目で、詳細設定が可能です。
なお、この中で「Enable Alphas in Depth of Field calculations」という設定があるのですが、
これは透明度を持つオブジェクトに対してもDoFを正しく行うという機能です。
この機能は、結構重たい処理のためFPS稼ぎに外しておくのがオススメです。
.

モーションブラーを設定できる。

カメラをぶらすと、映像の軌跡を残るように、
3DCG表示でもこれを再現させます。
モーションブラーを使用すると、アバターをアニメーションをさせたときに
滑らかに表示されるように感じたり、躍動感がうまれます。
.

レンズフレア

太陽をみたときなどに、レンズフレアを表示させることができます。
ただ、太陽との間にオブジェクトで遮っている場合でも、
レンズフレアが見えてしまうことがあるので、この設定は一長一短。
.

トーンマッピング

3DCGのレンダリング後に、色に対してエフェクタを通すことができます。
色は、線形や非線形に変更したりできます。
具体的には、コントラストを上げたり、明るくしたり、赤みをおびさせたり、
好きな雰囲気にすることができます。


さて、使いたくなってきたところで、
インストール時によくやる設定について最後に紹介します。
.

キーボード操作の設定(Keybindings)の変更

スライド移動(Strafe)と回転(Rotate)とジャンプのキーボード操作が
デフォルトと異なるため、変更すると使いやすいです。

三人称視点時設定(Third Person Keybindings)と
一人称視点(マウスルック)時設定(First Person Keybindings)の
両方で設定をする必要があります。

Third Person Keybindings
・Move Forwards [W] -> [W]
・Move Backwards [S] -> [S]
Strafe Left [A] -> [A + [Shift]]
Strafe Right [D] -> [D + [Shift]]
Rotate Left [Q] -> [A]
Rotate Right [E] -> [D]
Jump [Space] -> [E]

First Person Keybindings
・Move Forwards [W] -> [W]
・Move Backwards [S] -> [S]
・Strafe Left [A] -> [A]
・Strafe Right [D] -> [D]
・Rotate Left [Q] -> [Q]
・Rotate Right [E] -> [E]
Jump [Space] -> [E]

.

カメラの設定(Camera)の変更

下記のチェックボックスを外しましょう。
「Enable ‘realistic’ Camera behavior in Mouselook」
この設定が有効になっていると、
マウスルック時のカメラが、アバターのアニメーションに
追従するようになると思います。酔う原因になります。
.
また、Smoothingを8.00->0.50にすると、
カメラが向いた方向へ瞬時に移動するので好みで設定。
.

グラフィックの変更

Black Dragonは、デレンダラ(非描写)機能があります。
Rendering Options -> Derender … と書いてある設定です。
この設定は、指定したファイルサイズより大きかったり、
表面の面積が大きかったりしたりすると表示しなくなります。
アバターやオブジェクトが表示されなくならないように、適切な値に調節するか、
あるいは全て 0 にして無効化するといいです。


グラボをつけている方や、
綺麗なスクリーンショットを撮りたい方は
一度 Black Dragon を試してみるといいかもしれません。

以上、紹介を終わります!


自分用の設定メモ

.

髪の毛などの影も綺麗に顔に落とす(太陽の光用)

☑Deferred Rendering
・Extended Shadow Distance 128 -> 16
・Closeup Shadowmap Size 2048 -> 4096
・Close Shadowmap Size 4096 -> 4096
※Shadowの設定で上と下があるのは、おそらく上が太陽の影、下がライトによる影設定です
※「Extended Shadow Distance」は小さくなるほど、影の精度があがりますが、遠い距離にある影がおちにくくなります。
.

全体をふんわりと明るくする

☑Windlight Options
・Warmth Red 1.00 -> 2.00
・Warmth Green 0.60 -> 2.00
・Warmth Blue 0.75 -> 2.00
☑Volumetric Lighting
・中はデフォルト
☑Post Processing Effects -> Lens Flare Effect
・中はデフォルト
☑Tone Mapping
☑Custom
Linear Strength 0.44 -> 0.25
Toe Strength 0.24 -> 0.87
Toe Numerator 0.02 -> 0.87
Toe Denominator 0.18 -> 0.66
Linear White 25.00 -> 13.22
Exposure Bias 3.00 -> 0.91
☑Color Correction Linear
・中はデフォルト

Written by なたで

2016年4月17日 at 16:18

カテゴリー: game, memo, review

Tagged with

セカンドライフのランドインパクトと標準プリムの話

leave a comment »


セカンドライフでは、土地でおけるプリム数が決まっています。
(詳しくは、セカンドライフの土地維持費を参照)

今回は、そのプリム数というのが、
どのような基準で決まるか、お話します。

まず単純にプリムとは、何なのかというと、
セカンドライフ上で作成できる「正方体」や「球体」などです。
これらは、1つ1つが、1プリムとなり、例えば512m2の土地では、117プリム=117個置けるとなります。

では、ここで一辺が50cmの正方体(キューブ)を作成して、詳細を見てみましょう。
右クリックで編集メニューを表示して、リンクの右側あたりにある「詳細」ボタンです。

すると次のように表示されると思います。
prims_0_cube
ここで、一番下の「土地の負荷」の「選択済」の 1 がランドインパクト(以下LI)となります。
実際、117プリム置ける土地は、117LI置けるということになります。

ちなみにここで表示されているそれぞれの意味について説明します。

選択済
選んでいるオブジェクトについて表示します
オブジェクト
選択中のオブジェクト(例えば、リンクすると1になります)
プリム
選択中のプリム(リンクしたものであれば、リンク数となります)

選択済みアイテムのウエイト
土地の重さ(LI)に関わる情報
ダウンロード
サーバーから、モデルをダウンロードする際の負荷です。
モデルは、メッシュであれば頂点数、ポリゴン数が多いほど、
ファイルサイズが大きいので、サーバーのダウンロードに負荷がかかるという分けです。
プリムが大きいほど、遠い距離からでもダウンロードが必要になるので、負荷が大きくなります。
ポリゴン数は、グラフィックボードの描写負荷と言っても分かりやすいかもしれません。
ポリゴン数、大きさ、描画詳細度(以下、LoD)などで変わってきます。
LoDについては、描画詳細度についての設定を参照してください。
物理効果
実像(当たり判定に使用するポリゴン)の負荷です。
プリムの大きさによっても変わってきますが、大きいほど大きくなるという分けでもなく、
小さくなると、大きくなるものもあります。
また実像の計算方法は「なし」「プリム」「凸状の外殻構造」があり、
計算方法をそれぞれ異なるため、物理効果の負荷も変わってきます。
メッシュをアップロードする際には、ここも設定することが可能です。
詳しくは、メッシュに物理形状を設定しよう1を参照してください。
あたり判定が必要でないのであれば、適当な立方体を実像にしたほうがいいです。
実像のポリゴン数、大きさなどで変わってきます。
サーバー
一律、1 プリムごとに最低 0.5 かかります。
表示用サーバーに 1 プリムを用意してもらっているための負荷となります。
プリムと同等の重さの計算 によると、物理オブジェクトやスクリプトを入れることで大きくなるようです。

土地の負荷 選択済み
オブジェクトの最終的なLIとなります。
ここの値は、上記の「ダウンロード」「物理効果」「サーバー」で、
最も大きな値の小数点を四捨五入した値です。
※ここについて、メッシュではなくセカンドライフで用意されている
標準のプリム(以下、標準プリム)で、実像が「プリム」の場合は、特例で必ず 1 になります。

下のは、球(スフィア)です。
prims_1_sphere
これを見ると、ダウンロードが球のほうが大きいことが分かります。
恐らく、球のほうがポリゴン数が大きくなるためだと思われます。
実像は、変わりありません。球のほうが、正方体より当たり判定が大変かと思うかもしれませんが、
球であると分かっている以上、球専用の当たり判定の数式を使うため正方体より簡単になるためです。
そのため、メッシュで球を作ろうとすると、物理効果が大きくなってしまいます。

では、立方体と球の両方を選択してみます。
prims_2_link_0
この場合は、オブジェクト数が2、プリム数が2
その他のものについても、2つのプリムの合計値が表示されています。

これらの立方体と球の両方を選択してリンクしてみます。
prims_3_link_1
すると、リンクができたため、オブジェクト数が1になります。
土地の負荷は、選択済みのアイテムのウエイトの最大値から 1 になります。
(今回の場合は、特例により2になっています。これについて後で解説)

ここで、片方のプリムの実像の種類を「なし」にしてみます。
つまり当たり判定をしない設定とするわけです。
prims_4_link_2
物理効果が 0.2 から 0.1 となり、
1プリム分の物理効果が減ることが分かります。

このような感じで、土地の負荷(LI)は、いろいろな要素から計算されます。
これらの知識を知っていれば大体、LIが予想つくようになり
物づくり、メッシュアップロードなどで低LIの物も作れるようになります。


さて、続けてランドインパクトに関係して、
物理効果と、標準プリムの特例の話をしたいと思います。

先ほど、2種類の標準プリムについてみてきました。
キューブは、ダウンロード 0.1、物理効果 0.1
スフィアは、ダウンロード 0.9、物理効果 0.1

ポイント
・ダウンロードは頂点数、ポリゴン数の量
・物理効果は数式による計算量(球の計算は簡単)

ここでスフィアについて物理効果が増やす方法があります。
それは、引き伸ばしです。
スフィアを引き延ばすことで、楕円体という形になります。
この場合、球の簡単な計算式が使えなくなるため物理判定をコストが大きくなります。
(立方体については、大きくしても物理判定の計算方式は変わらないので問題ありません)
prims_5_ellipsoid
物理効果が 1.2 に膨れ上がります!

また、標準プリムの中には、
何も編集しなくても巨大な物理効果があるものがあります。
それがトーラスです。(ドーナッツのようなやつ)
prims_6_torus
なんと、物理効果が 35.0 もあります。
3D空間でのトーラス自体とのあたり判定は数式を使っても大変なようです。
ただ、おそらくセカンドライフ上では、ポリゴンを使用してあたり判定を行っていると思われます。

ここまで、物理効果が大きくなる話をしてきましたが、
LIは、1であることにお気づきでしょうか。
そう、標準プリムなので、どれだけ物理効果が大きくても1なのです。
これは特例を受けているためだと思われます。

しかし、実像の種類を変えた場合に注意が必要です。
標準プリムは最初、実像の種類が、「プリム」となっているいますが、
これを「凸状の外殻構造」としてしまうと、特例から外れしまいます。
prims_7_torus_2
「プリム」から「凸状の外殻構造」にしたため、
物理効果の計算方法が変わり、35.0 から 1.8 に下がりましたが、
LIは、特例処置から外れてしまったため、 2 LIになってしまいました。

さらに、注意する点として、標準プリムをリンクした場合の話です。
例えば2つのトーラスをリンクしてみましょう。
prims_8_torus_link
この場合、物理効果が合わせて大変なことになっていますが。
特例により 2 LI しかありません。ヤッタネ!

ここで、リンクした2つのトーラスのうち、
片方のプリムの実像を「なし」にしてみましょう。
これで、物理効果がなくなるので半減するはず……
prims_9_torus_link_2
実は、物理効果は半減するのですが、
最終的な土地の負荷で、特例から外れてしまい、 35 LI となってしまいます。
標準プリムに関しては、リンクを行った後に実像を「プリム」以外に変更してしまうと、
他の標準プリムについても、特例から外れてしまうわけです。

ただ、逆に言えば、特例をうけてしまうと、
本来であれば 0.5LI の立方体を 2つリンクしても 1LI にならず、 2LI になってしまうのです。
つまり、特例を抜けたほうが、土地の負荷量が下がる場合もあるのです。

例えば立方体の標準プリムを10個リンクしました。
prims_10_A1
ごらんのように、
ダウンロード 0.6、物理効果 1.0、サーバー 5.0
なので、 5 LI となるはずなのですが、
特例のために、プリムの数=LIとなってしまい、 10 LI になってしまいます。

そこで、1 つでも、実像の種類を変更すると、
例えば、どれか 1 つだけ選んで「プリム」から「凸状の外殻構造」としましょう。
prims_10_A2
すると、特例から外れて、負荷が 5 LI となります。

標準プリムを扱うときは、
このような知識を持っておくことで、
低 LI の家などを作ることができると思います。


実像で、「プリム」と「凸状の外殻構造」何が違うのか、
実は、LI 以外にも、大きなメリットとデメリットがそれぞれあります。
それについては、またいつか話したいと思います。

Written by なたで

2015年7月25日 at 12:00

カテゴリー: game, memo

Tagged with , ,

セカンドライフでメッシュに物理形状を設定しよう1

leave a comment »


メッシュでアップロードするときに、「実際の見た目」と「物理形状」を自由に選ぶことができます。
今回は、それらがどのような動きをするのか、少し調べたのでまとめたいと思います。

obj_1
このような単純な物体を用意します。
赤色は「実際の見た目」として利用して、青色が「物理形状」として利用したいと思います。
画像を見るように、まずは、重なった立方体としています。
obj_2_X
さて、これをアップロードすると、このような感じになります。
「実際の見た目」、「物理形状」が合わさって、同じ物体が1つしか見えないようにみえます。
なお、画像にある物理演算という部分は、アップロード時に表示されたものを書いています。

obj_2
次は、「見た目」と「物理形状」の位置をずらしてみました。
さらに、「物理形状」の大きさも上下左右奥行で違ったものにした場合です。
obj_2_X
アップロードすると、不思議なことがおきます。
これは、先ほどの「見た目」と「物理形状」が同じだった場合と一致しているのです。
どうしてこのようになるのか、次の実験でわかると思います。

obj_3
「物理形状」を回転させた場合です。
obj_3_X
こちらが、アップロードした場合の「見た目」と「物理形状」です。これでわかりましたでしょうか、
「物理形状」というのは、勝手に形が変更されてしまうのです。
具体的には「見た目」のバウンディングボックスに最大限おさまるように、
上下左右奥行の各々で正規化されてしまうというわけです。
これは、物理形状を別で作るうえで注意が必要です。

obj_4
次は別のテストをしてみます。
このように、物理形状のみの法線を逆にした場合です。
obj_4_X
アップロード時には、「物理形状」の面が逆になっているように見えます。
しかし、これを実際にプリムとして設置しても、別に立方体の中へ入れるといったことはございません。
「見た目」の法線は、描写するときに見える方向が決まってしまいますが、
「物理形状」の法線は、あたり判定の方向が決まるというわけではないのです。
そのため、一方通行のような面を作ることはできないのです。

obj_5
ところで、面1枚のような物理判定も作ることができるのでしょうか。
通常のSLに用意されている通常プリムには、面1枚のものはないので気になります。
というわけで、今回はこのようなオブジェクトを用意してみます。
obj_5_X★1

こちらも、問題なく面1枚も物理として設定できます

S_obj_5_X_2
しかし注意が必要でして、アップロード後に実際においてみると、
物理形状が変わっており、上の平面の部分に当たることができなくなります。

type

これを防止するためには、設置後に自分で「実像の種類」を
「凸状の外殻構造」(デフォルト)から「プリム」に変更する必要があります。
「凸状の外殻構造」というのは、凹みがない構造のことをいいます。

S_obj_5_X_3
そして、設定するとアップロード時に表示された形状の物理判定となります。

S_obj_6_X_2
「実像の種類」というのは重要な設定で、例えば3つの立方体があるモデルでも、
「凸状の外殻構造」にしていると、1つの構造となってしまい、接続されてしまいます。

ところで「実像の種類」を「プリム」にしたときに、様々な問題が発生します。

obj_5_X_2_2
★1を「実像の種類」を「プリム」としたときの物理負荷はこのようになるのですが、
これでは、アップロード前確認で表示されたものと一致しません。
これはプリムの大きさをアップロード後に変更したためです。

つまり、大きさによって、物理負荷が変わってくるわけです。
そして、大きければ物理負荷が大きくなるというものでもなくて、
大きさを小さくすると、物理負荷が大きくなる可能性があります。

物理負荷というのが、どのような計算で算出されるのかちょっとわからないですが、
プリムの大きさを小さくすると物理負荷が大きくなることから、
何回、ポリゴンとの衝突判定を行わないといけないかといった計算から
導いているのかもしれませんね。
小さいと、その分どのポリゴンとも衝突する可能性があるわけでして。

これについては、いつかまた調査したいです。

オマケ

obj_6
例えば、3つの立方体が並んだモデルも
obj_6_X
アップロードして……
obj_6_X_2_b_2
「実像の種類」を「プリム」としたときに、1プリムで済んでしまうのです。
やはり、メッシュは強いですね~。

なお、物理演算コストは32を超えるとだめなようです。

Written by なたで

2015年6月2日 at 00:55

カテゴリー: 3D, game, memo

Tagged with , ,

セカンドライフでHSVとRGBを相互変換してみよう

leave a comment »


HSVというのは、いわゆるHSV色空間のことです。
これは、Hue(色相)、Saturation(彩度)、Value(明度)を表しておりましています。

ご存知?の通りRGBの色空間から、HSVの色空間へ変換が可能でして、
これを利用すれば、今のRGBの色から、少し濃い色にしたり、逆に薄い色にしたり、
明るい色にしたり、暗い色にしたり、色相を反転させたり、いろいろできるわけです。

そしてこちらが、関数と逆関数です。スキニツカテイイヨー(あんまりテストしてないので・・・)

float	fractF(float x) { if(x >= 0) { return(x - (integer)x); } else { return(1.0 + (x - (integer)x));}}

vector getRgbFromHsv(vector hsv) {
	vector rgb = <hsv.z, hsv.z, hsv.z>;
	if(hsv.y > 0.0) {
		hsv.x *= 6.0;
		integer	i = (integer)hsv.x;
		float	f = fractF(hsv.x);
		if(i == 0) {
			rgb.y *= 1.0 - hsv.y * (1.0 - f);
			rgb.z *= 1.0 - hsv.y;
		}
		else if(i == 1) {
			rgb.x *= 1.0 - hsv.y * f;
			rgb.z *= 1.0 - hsv.y;
		}
		else if(i == 2) {
			rgb.x *= 1.0 - hsv.y;
			rgb.z *= 1.0 - hsv.y * (1.0 - f);
		}
		else if(i == 3) {
			rgb.x *= 1.0 - hsv.y;
			rgb.y *= 1.0 - hsv.y * f;
		}
		else if(i == 4) {
			rgb.x *= 1.0 - hsv.y * (1.0 - f);
			rgb.y *= 1.0 - hsv.y;
		}
		else if(i == 5) {
			rgb.y *= 1.0 - hsv.y;
			rgb.z *= 1.0 - hsv.y * f;
		}
	}
	return(rgb);
}

vector getHsvFromRgb(vector rgb) {
	float min = llListStatistics(LIST_STAT_MIN, [rgb.x, rgb.y, rgb.z]);
	float max = llListStatistics(LIST_STAT_MAX, [rgb.x, rgb.y, rgb.z]);
	vector hsv = <max - min, max - min, max>;
	if(hsv.x > 0.0) {
		if(max == rgb.x) {
			hsv.x = (rgb.y - rgb.z) / hsv.x;
			if (hsv.x < 0.0) {
				hsv.x += 6.0;
			}
		}
		else if(max == rgb.y) {
			hsv.x = 2.0 + (rgb.z - rgb.x) / hsv.x;
		}
		else {
			hsv.x = 4.0 + (rgb.x - rgb.y) / hsv.x;
		}
	}
	hsv.x /= 6.0;
	if(max != 0.0) {
		hsv.y /= max;
	}
	return(hsv);
}

default {
	state_entry() {
	}
	touch_start(integer total_number) {
		vector color	= <0.5, 0.7, 0.2>;
		vector hsv		= getHsvFromRgb(color);
		vector rgb		= getRgbFromHsv(hsv);
		llOwnerSay((string) hsv);
		llOwnerSay((string) rgb);
	}
}

色相は0→1が360度に対応していますので、
1を超えたら、また0→1へを繰り返します。

余談ですが、HLS色空間というものもあります。
こちらは少し、また計算式が変わってきています。詳しいことはこちらに。

以上


そしていつものおまけ
GLSL でおなじみの lerp や fract はよく使用するので、準備しておくと便利です。

float	fractF(float x) { if(x >= 0) { return(x - (integer)x); } else { return(1.0 + (x - (integer)x));}}
float	minF(float x, float xmin) { if(x > xmin) { return xmin; } else {return x;}}
float	maxF(float x, float xmax) { if(x < xmax) { return xmax; } else {return x;}}
vector	lerpV(vector A, vector B, float r) { return(A * (1.0 - r) + B * r); }
float	lerpF(float  a, float  b, float r) { return(a * (1.0 - r) + b * r); }
integer	lerpI(float  a, float  b, float r) { return((integer)(a * (1.0 - r) + b * r)); }
float	limitF(float x, float xmin, float xmax) { if(x > xmax) { return xmax; } else if(x < xmin) { return xmin; } else {return x;}}
integer	limitI(float x, float xmin, float xmax) { if(x > xmax) { return (integer)xmax; } else if(x < xmin) { return (integer)xmin; } else {return (integer)x;}}
float	normalizeF(float x, float xmin, float xmax) { return (x - xmin) / (xmax - xmin); }

Written by なたで

2015年4月9日 at 21:04

カテゴリー: game, memo, program

Tagged with , ,

セカンドライフで被らないチャンネルの作り方

leave a comment »


セカンドライフで物づくりしてますと、
llSay / llRegionSayTollListen 使ってコマンドで物を操作することありますよね。
そんなときに、どの出力チャネル使おうか迷うことありませんか。

例えばですが、適当に25135034 という数値を使ったとします。
これは恐らく他のものと被ることはないと思われます。
しかしですよ、このチャネルを使用した物を配るとします。

すると、もらった誰かがそのオブジェクトを操作しようとすると、
他にもらった誰かも、そのチャネルを受信してしまいます。
llListen でフィルターもかけられますが、
今回はチャネル番号をアバター固有の情報から作成する方法を紹介します。

ハッシュ関数 パンパカパーン

はい。以上です。
文字列から数値を作り出すあれです。

え?
SLって、16進数の文字列から数値へ変換する関数なんてないんじゃないの?

と思う方もいるかもしれませんが、実は (integer)”0x1234″ とすれば、
文字列を16進数の数値とみなして変換できるわけです。

とりあえず、keyから整数を変換できる関数を2種類作ってみました。

integer i;

/* 線形合同法によるハッシュ関数 */
integer getKey2HashLCGs(key src) {
	integer start_pos = 0;
	integer seed = 0x32123;
	integer hash = seed;
	// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
	// 32ビットずつ取り出してハッシュを作成
	for(i = 0; i < 8; i++) {
		hash = hash * 0x1234321 + (integer)("0x" + llGetSubString(src, start_pos, start_pos + 3));
		start_pos += 4;
		if(	(start_pos == 8) ||
			(start_pos == 13) ||
			(start_pos == 18) ||
			(start_pos == 23) )	{
			start_pos++;
		}
	}
	return(hash);
}

/* SHA1+線形合同法によるハッシュ関数 */
integer getKey2HashSHA(key src) {
	integer start_pos = 0;
	integer seed = 0x32123;
	integer hash = seed;
	string buffer = llSHA1String((string)src);
	for(i = 0; i < 40; i += 4) {
		hash = hash * 0x1234321 + (integer)("0x" + llGetSubString(buffer, i, i + 3));
	}
	return(hash);
}

default {
	state_entry() {
	}
	touch_start(integer total_number) {
		key x;
		x = llGetOwner();
		llSay(0, (string)x
			+ "\n-> " + (string)getKey2HashLCGs( x )
			+ "\n-> " + (string)getKey2HashSHA( x )
			);
		x = llGenerateKey();
		llSay(0, (string)x
			+ "\n-> " + (string)getKey2HashLCGs( x )
			+ "\n-> " + (string)getKey2HashSHA( x )
			);
	}
}

恐らく上のgetKey2HashLCGsの方が、llSHA1Stringを使わない分、速いです。
お好きな方をどうぞ。

SHA1で作った関数は、引数の key を string に型を変更すれば、
何でも好きな文字列から32ビットの整数を取得できるようになります。

それと、両方の関数とも seed を引数に追加するこでとることで、
色々なアプリケーションでアバターごとに被らないチャンネル番号の作成を
利用できるようになると思います。

以上!

あ!
注意点として、
運が悪いと取得したチャンネル番号が「0」になることもあるかもしれませんので、
その点だけはお気を付け下さい・・・。

それを踏まえてこんな感じに使いましょう。

integer	i;
string	MY_PROJECT_NAME = "test tool";

integer getOriginalKey(string src) {
	integer start_pos = 0;
	integer seed = 0x32123;
	integer hash = seed;
	string buffer = llSHA1String((string)llGetOwner() + (string)src);
	for(i = 0; i < 40; i += 4) {
		hash = hash * 0x12344321 + (integer)("0x" + llGetSubString(buffer, i, i + 3));
	}
	if(hash == 0) {
		hash = 0x43019768;
	}
	return(hash);
}

default {
	state_entry() {
	}
	touch_start(integer total_number) {
		llSay(0, (string)MY_PROJECT_NAME
			+ "\n-> " + (string)getOriginalKey( MY_PROJECT_NAME )
			);
	}
}

オマケというメモ

線形合同法の乱数は、
X_n+1 = ( A * X_n + B ) mod M
という式から作成できます。

ここで、数値は32ビットの整数なので、
M = 0x100000000 = 4294967296 となります。
M の素因数分解は、2 ^ 32 です。
ここで A-1 が、Mの素因数分解の全て割り切れると、
この乱数の周期性が最大となることが知られています。
2 ^ 15 + 1 = 0x8001 = 32769 とかを設定すると、周期性が最大となります。

ですが、今回はハッシュ値を求めるためなので、
好きな値を入れても構わないです。
Bの値なんてどんな値がくるか分からないのですから。


追記 2015/3/25

listenに入ってくるチャンネル番号は
オブジェクトのUUIDなので、人でフィルターができないと思っていました。
ところが実はいい方法がありまして、これをある方から教えていただきました。
所有者を調べる llGetOwnerKey という関数があるのです。
たしかにこれを使えば、オブジェクトのUUIDだとしても誰が持っている
オブジェクトが発言したのか分かりますね!すっすごい!
&nbsLlGetOwnerKeこ

Written by なたで

2015年2月27日 at 23:56

カテゴリー: game, memo, program

Tagged with , ,

セカンドライフの描画詳細度について

leave a comment »


今日はセカンドライフのLoDの動作について、少し解明していきたいともいます。以前もLoDの話はしておりますが改めて説明します。

LoDとは、Level of Detailの略でして、描画詳細度と呼ばれるものです。描画詳細度が大きければ、ディテールを細かくし、詳細度が低ければディテールを荒くします。例えばですが、3Dの世界で全てを描写しようとすると、とてもGPUに負荷がかかります。そのため、カメラが写っている範囲だけを描写したり、いろいろな工夫をしているわけです。その中の1つに、カメラからの距離が遠くなればなるほど、負担が少なくなるようにモデルの形を変更させる方法があります。LoDを設定しておけば、レベルの段階に合わせて、簡単モデルを表示させられるわけです。

さて、「カメラからの距離に合わせて、描写するモデルを簡略化させる」と簡単には書きましたが、よくよく考えると、いまいち仕様が分かりません。

例として、縦長のモデルがあったとします。このモデルを上から見れば小さく表示されて、横から見れば大きく表示されます。つまり、正確に実装するとするならばモデルを見る方向によって、描画詳細度を変える必要があるのです。モデルのバウンディングボックスを2次元平面に投影した後に、面積を調べるといった形になります。ただ、目的としては負担を減らすためにやっているはずなので、そういうことまではしていないとは思うのですが、確証はありません。

今回実際にセカンドライフ、ビューアはCatznipを使用して調べてみました。まずは、LoDにあわせて4つのモデルを作成します。なお、LoDは、低くなるにつれて必ずポリゴン数、頂点数が上がらないようにする必要があります。

MaruRo
ShikakuSankaku最低

作ったモデルをセカンドライフにアップロードします。
UploadS
上記のファイルをそれぞれのLoDに設定します。

では、まずは表示する面積によって、LoDが変わるのかテストしたいと思います。

HaichiS
次のように配置しました。
手前から奥に向かって、大きさが大きくなっていきます。
上の段は、奥行はうすっぺらいですが、横と縦の大きさを大きくしていっています。1×1, 2×2, 4×4, 8×8
下の段は、さらに奥行も大きくなっています。1x1x1, 1x1x2, 1x1x4, 1x1x16

そうそう、実際に見る前に公平性を保つためにカメラの設定をします。
ShiyakakuS
カメラの視野角を最低にしておきます。こうすることで、カメラの画角による影響を減らします。

さて、下が水平から見てある程度でカメラを離れたところにおいた時の画像となります。
SLLODTest1

ここから見ると、上の段にある奥行が薄っぺらいモデルの方が大きくみえるのですが、表示されるディテールが悪くなっています。従って、実際に画面に表示される大きさによって、ディテールを変更しているわけではないのです。

次はモデルのバウンディングボックスの体積が関係あるのでは、と仮定をして配置します。

SLLODTest2
左のモデルは2x2x2。右のモデルは1x1x8となります。
このモデルを離れたところから見て、2つとも同時にディテールの変更があれば、体積が影響するといえます。

しかし実際にやってみるとそうではありませんでした。
SLLODTest3
左のモデルの方が先にディテールが低くなったのです。

次は「モデルの体積」ではなく、
SLLODTest4
「モデルの大きさの最大値」を使用しているのではと仮定して配置しなおしました。
左のモデルは2x2x8。右のモデルは1x1x8となります。

この場合は、ほぼ同じ位置でディテールの変更がありました。
SLLODTest5
これらの結果から「モデルの大きさの最大値」がディテールに影響することが分かりました。

脱線しますが、セカンドライフのディテールの設定は、デバッグ設定の RenderVolumeLODFactor に依存します。
SLLODTest6

これが大きいと、ディテールの低下を下げることができます。グラボの性能が良いのであれば、少し上げても問題ないと思われます。


オマケ
カメラの座標を取得するスクリプトです。

integer	isStartTimer	= FALSE;

default {

	state_entry() {
	}
	
	touch_start(integer total_number) {
		if(isStartTimer) {
			isStartTimer = FALSE;
			llSetTimerEvent(0.0);
			llClearCameraParams();
		}
		else {
			llRequestPermissions(llGetOwner(), PERMISSION_TRACK_CAMERA);
			isStartTimer = TRUE;
			llSetTimerEvent(1.0);
		}
		llOwnerSay("isStartTimer = " + (string)isStartTimer);
	}
	
	timer() {
		llOwnerSay("llGetCameraPos = " + (string)llGetCameraPos());
	}
	
}

Written by なたで

2015年1月24日 at 14:02

カテゴリー: 3D, game, memo

Tagged with , ,