FC2ブログ

myara CG blog

CG Design Blog. Thoughts, experiments and experiences.

Python で TGAの情報(header)を読み込む方法

今回の案件でテクスチャはTGA 24bit RLE圧縮という指定がありまして、それをチェックが出来るツールを書こうとしていました。

まずは既に書いてある物をネットで探して、使えそうなモジュールはこれでした:

pyTGA
https://github.com/MircoT/pyTGA

TGAを読み込んだり、書き出したり出来るモジュールです。
そして、全てデフォルトのPythonで動くモジュールです!

全てPythonだから好きに編集が出来るけど、処理が重いのかなという心配もあります。
とりあえず試してみます。

使い方を読んで、以下のコマンドで欲しかった情報を取得ができました。
image = pyTGA.Image()
image.load( texture_filePath )
print image._header.pixel_depht


しかし、重い。
1枚数十秒だったので、4K テクスチャを数十枚を確認するには向いていませんね・・・。

どうやら load でテクスチャのデータを全て読み込んでいるようで、かなり時間が掛かってしまいます。

でも、欲しいのはヘッダーの部分だけ。
テクスチャのデータとかはいらないので、色々弄ってみて以下のコードに変わりました。
あっちこちの調整も必要があったけど、主にヘッダーの読み込みに役に立ちそうな部分だけを残して、あとは削除する作業でなんとかなりました:

from struct import unpack
def dec_byte(data, size=1, littleEndian=True):
"""Decode some data from bytes.

Args:
data (bytes): data to decode
size (int): number of bites of the data
littleEndian (bool): little endian or big endian

Returns:
int: the decoded data
"""
order = str('<' if littleEndian else '>')
format_ = str((None, 'B', 'H', None, 'I')[size])

return unpack(order + format_, data)[0]

class TGAHeader(object):
"""
#- Field(1)
# ID LENGTH (1 byte):
# Number of bites of field 6, max 255.
# Is 0 if no image id is present.
#
#- Field(2)
# COLOR MAP TYPE (1 byte):
# - 0 : no color map included with the image
# - 1 : color map included with the image
#
#- Field(3)
# IMAGE TYPE (1 byte):
# - 0 : no data included
# - 1 : uncompressed color map image
# - 2 : uncompressed true color image
# - 3 : uncompressed black and white image
# - 9 : run-length encoded color map image
# - 10 : run-length encoded true color image
# - 11 : run-length encoded black and white image
#
#- Field(4)
# COLOR MAP SPECIFICATION (5 bytes):
# - first_entry_index (2 bytes) : index of first color map entry
# - color_map_length (2 bytes)
# - color_map_entry_size (1 byte)
#
#- Field(5)
# IMAGE SPECIFICATION (10 bytes):
# - x_origin (2 bytes)
# - y_origin (2 bytes)
# - image_width (2 bytes)
# - image_height (2 bytes)
# - pixel_depth (1 byte):
# - 8 bit : grayscale
# - 16 bit : RGB (5-5-5-1) bit per color
# Last one is alpha (visible or not)
# - 24 bit : RGB (8-8-8) bit per color
# - 32 bit : RGBA (8-8-8-8) bit per color
# - image_descriptor (1 byte):
# - bit 3-0 : number of attribute bit per pixel
# - bit 5-4 : order in which pixel data is transferred
# from the file to the screen
"""

def __init__(self, file_name):
with open(file_name, "rb") as image_file:

# Read Header
image_file.seek(0)
# ID LENGTH
self.id_length = dec_byte(image_file.read(1))
# COLOR MAP TYPE
self.color_map_type = dec_byte(image_file.read(1))
# IMAGE TYPE
self.image_type = dec_byte(image_file.read(1))
# COLOR MAP SPECIFICATION
self.first_entry_index = dec_byte(image_file.read(2), 2)
self.color_map_length = dec_byte(image_file.read(2), 2)
self.color_map_entry_size = dec_byte(image_file.read(1))
# IMAGE SPECIFICATION
self.x_origin = dec_byte(image_file.read(2), 2)
self.y_origin = dec_byte(image_file.read(2), 2)
self.image_width = dec_byte(image_file.read(2), 2)
self.image_height = dec_byte(image_file.read(2), 2)
self.pixel_depth = dec_byte(image_file.read(1))
self.image_descriptor = dec_byte(image_file.read(1))


これで欲しかった情報を一瞬で読み込むことが出来ました。
テクスチャの作り方にミスがあったかどうかはすぐに分かる。

tga = TGAHeader( texture_filePath )
print tga.image_type #3以下の場合は圧縮なし
print tga.image_height #高さ
print tga.image_width #横幅
print tga.pixel_depth #24bit か 32bit


そして何もインストールする必要がない!
チェックツール1つだけで済むというのも嬉しいですね。
スポンサーサイト



Maya | ヒストリを残さないアトリビュートの転送(メモ)

今日見つけたやり方です。昔のMayaユーザーにとってこれは当たり前かは分かりませんが、ちょっと面白いと思ったのでメモっておきます。

アトリビュート転送をウェイトが入っているモデルに使うと「デフォーマ以外のヒストリ(Non-Deformer History)」がこのアトリビュート転送のヒストリを消してくれない。普通のトランスフォームノードではなく、中間シェイプに転送すれば、ヒストリでアトリビュート転送を消してもウェイトが残ります。

transfer.jpg


やり方:
・Outlinerではシェイプノードが表示されるようにShapeにチェックします。
・中間シェイプ (Intermediate Shape) を探して(普通はなんとか _Orig という名前になっています)、 Intermediate Object アトリビュートのチェックを外す。これでやっと中間シェイプがOutlinerには表示されます。
・転送したい元のオブジェクトを選択して、中間シェイプを選択して、アトリビュート転送を行います。
・中間シェイプのヒストリを削除して
・中間シェイプのIntermediate Object のチェックを付けなおします。
以上

試しにポーズされたままで転送を使ってみた動画です。


Maya Transfer Attributes without history from myara on Vimeo.



スクリプト化は簡単そうなので、そのうちに書いてみようかな。

SI データを Maya に持って行ったり、持って来たり

MayaとSoftimageにデータを持って行ったりもって来たりするツールを作ろうとしています。

最初のプロトタイプ(テスト用)が出来たので、公開します。

オブジェクトモデルをインポートエクスポート
UVをインポートエクスポート

という機能です。

仕組みはわりと簡単です。
一時フォルダにOBJに書き出して、OBJを読み込む。
UVの場合は、一時フォルダからOBJを読み込んで、UVをコピーして、OBJを削除。

※ C:\TEMP フォルダを使用されていない場合は自動に作成されます。

※ ただのOBJなので、マテリアル設定などは持っていけない。


色々考えて試してみた結果、この簡単な方法が一番うまく行きました。

これでFBXとかを使い分けると共有が出来るデータの幅が広がりそう。例えばSIにデータを持って行って、SIでウェイト作業を行って、ウェイトだけMayaに持って帰ったりして・・・。

参考までにして、好きにカスタマイズしてみてください。



MayaSI
Download

・script フォルダにコピー
・Python で:

オブジェクトデータをエクスポート
import MayaSI
MayaSI.expOBJ()

オブジェクトをインポート
import MayaSI
MayaSI.impOBJ()

UVをインポート
import MayaSI
MayaSI.impUV()


SIMaya_Plugin
Download

プラグインフォルダにコピー

オブジェクトデータをエクスポート
Application.expOBJ()

オブジェクトをインポート
Application.impOBJ()

UVをインポート
Application.impUV()

SI | Normal + Inmed モードでもウェイトが消えない方法

Softimage でInmedモード(ヒストリーが残らないモード)のままでウェイトが付いているオブジェクトにNormal(法線)ツールを使うと、ウェイトが消えてしまう。

Inmedモードで法線いじらなければ済む問題ですが、ついやってしまいます。

Inmedモードを切って、
法線をいじって、
Freeze M を掛けて
Inmedモードに戻す

という手順になりますが、これは自動に出来ないのかと今更思いついて書いてみました。

答えは、コマンドイベントを作って、以上の手順を自動にすればいいだけです。
なんで早くこれをやらなかったのかな!

以下のコードをPythonファイルに保存して

例:NormalsEvent.py



プラグインフォルダに入れる:

例: C:\Users\myara\Autodesk\Softimage_2015_SP1\Application\Plugins


ワークグループの場合は:

C:\Workgroup\Application\Plugins


それだけです。あとはSoftimageに任せてください。


from win32com.client import constants as c
xsi = Application

def XSILoadPlugin( in_reg ):
in_reg.Author = "myara"
in_reg.Name = "NormalsEvent Plug-in"
in_reg.Major = 1
in_reg.Minor = 0

in_reg.RegisterEvent("Normal_BeginCommand", c.siOnBeginCommand)
in_reg.RegisterEvent("Normal_EndCommand", c.siOnEndCommand)
#RegistrationInsertionPoint - do not remove this line

return True

def XSIUnloadPlugin( in_reg ):
strPluginName = in_reg.Name
Application.LogMessage(str(strPluginName) + str(" has been unloaded."), c.siVerbose)
return True

def Normal_BeginCommand_OnEvent( in_ctxt ):
Application.LogMessage("BeginCommand_OnEvent called", c.siVerbose)
Application.LogMessage("Command: " + str(in_ctxt.GetAttribute("Command")), c.siVerbose)

coms = ['Tweak Normal Tool', 'Average User Normals', 'Set User Normal Values', 'Set Vertex User Normals', 'Set Polygon User Normals', 'Invert User Normals', 'Normalize User Normals', 'Paste User Normals', 'Create User Normals']

if str(in_ctxt.GetAttribute("Command")) in coms:
UserImmed = xsi.GetUserPref("OperationMode")
if UserImmed == True :
xsi.SetGlobal('Normal_Immed', 1)
xsi.SetUserPref("OperationMode", False )

return False

def Normal_EndCommand_OnEvent( in_ctxt ):
Application.LogMessage("EndCommand_OnEvent called", c.siVerbose)
Application.LogMessage("Command: " + str(in_ctxt.GetAttribute("Command")), c.siVerbose)

coms = ['Tweak Normal Tool', 'Average User Normals', 'Set User Normal Values', 'Set Vertex User Normals', 'Set Polygon User Normals', 'Invert User Normals', 'Normalize User Normals', 'Paste User Normals', 'Create User Normals']

if str(in_ctxt.GetAttribute("Command")) in coms:
UserImmed = xsi.GetUserPref("OperationMode")
if xsi.GetGlobal('Normal_Immed') == 1 :
sel = xsi.Selection
for obj in sel:
if obj.Type.find('Component')!=-1:
obj = obj.SubComponent.Parent3DObject
xsi.FreezeModeling(obj)
xsi.SetUserPref("OperationMode", True )

return False


元から書いてある部分
Application.LogMessage("Command: " + str(in_ctxt.GetAttribute("Command")), c.siVerbose)

をあえて残しています。
このコマンドイベントは全てのコマンドを感知して、この行で使われたコマンドのログを残してくれる。
スクリプトエディターのプリファレンスにVerboseもログするようにしない限りログには出てこないけど、似たようなコマンドイベントを作りたい場合は便利だと思ったので、念のため残しておきます。

では、 続きを読む

PySide + SI 2015 + Win10 + Maya

= エラー
(その2)

以前の記事にWin10 で PySideを使う方法を書きましたが、一つ大きな問題があるのは、Mayaには影響がある可能性がある。

PYTHONHOME という環境変数を設定するとMayaのPythonがうまく動かないこともあるので、その場合はSoftimageの環境だけに設定する必要があります。

やりかたはわりと簡単です。

・環境変数のPYTHONHOMEを削除しておく。
・Softimage のフォルダを開く
例:
C:\Program Files\Autodesk\Softimage 2013 SP1\Application\bin
・setenv.bat をテキストエディターで編集する。(例 notepad++)
※ 管理者として編集が出来るソフトが必要ですが、できない場合は、このsetenv.batをほかの場所にコピーしてから編集してもOK。

このファイルをひらくと最初に以下の5行が見えます:

@echo off
rem Softimage Installation path
set SI_HOME=C:\Program Files\Autodesk\Softimage 2013 SP1
set XSI_HOME=%SI_HOME%
set XSI_BINDIR=%XSI_HOME%\Application\bin



この次にPYTHONHOME 変数を入れればいいです。
PYTHONHOME = C:\Python27

注意:クオーテーションマークは不要 (PYTHONHOME = "C:\Python27" はNG)

こんな感じ:

@echo off
rem Softimage Installation path
set SI_HOME=C:\Program Files\Autodesk\Softimage 2013 SP1
set XSI_HOME=%SI_HOME%
set XSI_BINDIR=%XSI_HOME%\Application\bin

set PYTHONHOME=C:\Python27



・ファイル保存して、完了。
※他の場所に移って編集された場合は、元の場所に上書きしてください。

以上。

※ 
次のページ