Wednesday, May 25, 2011

Object Material Tool 0.8

Eccomi con uno script per 3DStudioMax che costituisce la raccolta di alcune funzioni che uso normalmente nel mio workflow. Il risultato è questa simpatica (?) pulsantiera con menù a tendina :)


Nel dettaglio:
- "select by instance" seleziona le istanze dell'oggetto selezionato
- "select by material" una shortcut per la funzione già presente ma lentissima
- "select by modifier" seleziona tutti gli oggetti a cui è applicata l'istanza del modificatore selezionato
- "copy modifier" copia un'istanza del modificatore selezionato a tutti gli oggetti con lo stesso materiale
- "rmmod by material" elimina le istanze del modificatore selezionato da tutti gli oggetti con lo stesso materiale
- "rmmod (all instances)" elimina le istanze del modificatore selezionato da tutti gli oggetti in scena
- "rmmod all" elimina il modificatore (anche non istanziato) selezionato da tutti gli oggetti in scena

L'installazione non è ancora implementata, io per ora mi limito a trascinare lo script nella toolbar creando un pulsante ad hoc. Si accettano suggerimenti...

saluti,
pietro

Tuesday, March 29, 2011

Aggiornamento: script per automatizzare il lavoro di VRIMG2EXR

Eccomi qui!
Sono riuscito a rendere lo script indipendente dal file batch e ho pulito un po' il codice...
Cambiamenti:
- si lancia dalla riga di comando con python vrconv.py [nomefile.vrimg]
- è possibile utilizzare caratteri jolly e lo script si occupa da solo di trovare i frames e processarli tutti
- ogni file viene rinominato con nomefile+nomecanale+numeroframe.exr per poter essere facilmente rintracciato
- all'uscita cancella il file di testo utilizzato per la comunicazione con vrimg2exr.exe
- nel caso non aveste vrimg2exr nel PATH, o lo inserite o modificate la riga "vrimg2exr=" con il path completo del file.

ecco il file pronto all'uso: vrconv.zip
Per eseguirlo avete bisogno di Python 3.2

ciao!

Script per automatizzare il lavoro di VRIMG2EXR

Sono di fretta ma posto questo script che ho fatto in python per estrarre in un colpo solo tutti i canali da un file VRIMG. Per ora è lanciato tramite un batch perchè non sono ferratissimo in python e avevo necessità di farlo funzionare, sono aperto a qualunque miglioramento :)
Funziona da interfaccia per vrimg2exr.exe, ora sono proprio di corsa ma posto il codice perchè lo sto usando in questo momento e lavora da dio.

vrconv.bat:
@echo off
rem VRCONV: automatize vrimg conversion to exr,
rem finding all channels and separing them
rem -------- (C) 2011 Pietro Grandi -----------

rem Put here your ../vrimg2exr.exe complete path to find it
set VRAY2EXR=vrimg2exr.exe

rem Requiring info
%VRAY2EXR% -info %1 > %1.INFO.txt
if errorlevel 1 (goto:error)

rem Generate info file
set VRCONV_FILE=%1.INFO.txt
echo cmd: File has been saved as %VRCONV_FILE%
python vrconv.py %VRCONV_FILE%
goto:eof

:error
echo Some error occurred with %VRAY2EXR%


vrconv.py
import sys
import string
import os

name="vrconv"
info_file=sys.argv[1]
vrimg2exr=os.environ["VRAY2EXR"]

print("{1}: Assuming {0} as info file...".format(info_file, name))
print("{0}: vrimg2exr is located in {1}".format(name, vrimg2exr))
f = open(info_file)
k=0

current=f.readline()
v_channels=[()]

# Isolating info between quotes...
while current :
index=current.find('"')
if index!=-1 :
rev_index=current.find('"',index+1)+1 # +1 is to keep quotes
v_channels.append(current[index:rev_index])
k+=1
current=f.readline()

print("{0}: {1} channels found. Extracting...".format(name, k-1))

filename_vrimg=v_channels[1].strip('"')
filename_basic=filename_vrimg.strip('vrimg')

for i in range(2,k) :
print("{0}: Working on {1} channel".format(name,v_channels[i]))
os.system(vrimg2exr+" "+filename_vrimg+" "+"-channel "+v_channels[i])
filename_new=filename_basic+v_channels[i].strip('"')+".exr"
print("{0}: {1} is now {2}".format(name,filename_basic+"exr",filename_new))
os.rename((filename_basic+"exr"),filename_new)

Sunday, February 27, 2011

Blender: il selettore di istanze cresce...

Continua il lavoro sullo script... per quello che serve a me in realtà è già finito.
Ora viene definito un operatore che è possibile utilizzare come shortcut (screen.select_instances()) e che io ho assegnato a "SHIFT+I"
C'è un controllo sulla selezione attiva e un report in console e sulla finestra principale di blender.

Cose da fare: selezionare in base al nome. Non voglio in ogni caso farlo diventare un tool pesante con finestre ed altro: è una piccola utility per uso interno i cui pregi devono essere rapidità e leggerezza.
Chiedo scusa per la scrittura un po' raffazzonata ma ho studiato python giovedì scorso e le API di blender venerdì, tra l'altro le API sono soggette a continui cambiamenti e tanti esempi sul sito non funzionano sempre.

Ecco qui il codice ampliato:


#!BPY
"""
Name: 'Select object instances'
Blender: 256
Group: 'Object'
Tooltip: 'Select object instances'
"""
#author: Pietro Grandi (pietro909.blogspot.com)
#
#Release 0.4
# - now the script is an operator that can be added as a shortcut
# under Preferences->Input->Screen
# - the script performs a control in order to check if there is something active
# - messages are printed in console (verbose output) and as report on the top
#
# TODO: select by name, i'd like to have a popup to choose the selection type.
#


import bpy
class SelectInstances(bpy.types.Operator):
bl_idname = "screen.select_instances"
bl_label = "Select Instances"
def execute(self, context):
top = '[si-0.4]' #intestazione per i messaggi in console
scena = bpy.context.scene #punta alla scena attiva

i = 0 #contatore ciclo for
k = 0 #contatore di oggetti selezionati

sel_obj = bpy.context.active_object #oggetto attivo
if sel_obj == None: #se non ci sono oggetti attivi
print(top+'Error: no object selected') #segnala errore in console
self.report({'ERROR'}, 'no object selected') #segnala nel report
return{'CANCELLED'} #ed esci

#se invece la selezione e' valida continua#
sel_obj_type = sel_obj.data.name #tipo di oggetto selezionato
sel_obj_name = sel_obj.name #nome dell'oggetto selezionato


print(top+'Active object: '+sel_obj_name+' -> '+sel_obj_type)
print('Instances:')

for object in scena.objects: #per ogni oggetto in scena
current_obj = scena.objects[i] #prendi il nome dell'oggetto
if current_obj.data.name == sel_obj_type: #controlla se è del tipo selezionato
print('Selected '+current_obj.name) #stampalo
current_obj.select = True #selezionalo
k+=1
i+=1 #avanza il contatore
print('Total objects found and selected: '+str(k)) #stampa il risultato in console
report_string=str(k)+' instances of '+sel_obj_type+' found'
self.report({'INFO'}, report_string) #e nel report
return {'FINISHED'} #fine

if __name__ == "__main__":
bpy.ops.screen.select_instances()

EDIT: lo script è stato testato con una scena di oltre 2700000 poligoni e circa 8000 istanze per oggetto (cubi, coni, sfere, parallelepipedi)

Friday, February 25, 2011

Blender Script: Selezionare gli oggetti istanziati

Eccomi qui, dopo una lunga pausa.
Finalmente (e dico davvero: FINALMENTE!) ho integrato blender nel mio flusso produttivo, utilizzandolo come software principale in un lavoro nuovo che sto seguendo.

Appena avrò più tempo a disposizione ho intenzione di pubblicare un piccolo studio riguardante l'organizzazione della nuova pipeline, ma per ora sono pieno e soprattutto sto valutando quale motore di rendering entrerà a far parte della squadra una volta pensionato definitivamente 3DStudioMax (Thea e VRay sono i candidati per via dello stato di avanzamento degli exporter di blender).

Comunque... perchè scrivo?
Perchè lavorando con Blender su una scena con numerose istanze ho notato che l'outliner putroppo non ha tutte le funzioni di selezione che offre invece Max. Quindi, in piena filosofia open source, ho deciso di scrivermi degli script per fare questo lavoro :)

Questo è una "beta" di un selettore di istanze: cerca le istanze dell'oggetto attivo e le seleziona. Molto semplice, molto stupido se volete ma anche moooolto comodo.
Appena saprò usare meglio le API di Blender 2.6 voglio espanderlo ed integrare un pop-up.

Naturalmente è a disposizione di chiunque, rilasciato sotto licenza GPL:

# ##### BEGIN GPL LICENSE BLOCK #####
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####


#!BPY
"""
Name: 'Select object instances'
Blender: 256
Group: 'Object'
Tooltip: 'Select object instances'
"""
#author: Pietro Grandi (pietro909.blogspot.com)
#inspired by "atylmo" (http://atylmo.wordpress.com)
#

import bpy

scena = bpy.context.scene #punta alla scena attiva

i = 0 #contatore ciclo for

sel_obj = bpy.context.active_object #oggetto attivo
sel_obj_type = sel_obj.data.name #tipo di oggetto selezionato
sel_obj_name = sel_obj.name #nome dell'oggetto selezionato


print("E' attivo l'oggetto "+sel_obj_name+" di tipo "+sel_obj_type)
print("Istanze:")

for object in scena.objects: #per ogni oggetto in scena
current_obj = scena.objects[i] #prendi il nome dell'oggetto
if current_obj.data.name == sel_obj_type: #controlla se è del tipo selezionato
print("Selezionato "+current_obj.name) #stampalo
current_obj.select = True #selezionalo
i+=1 #avanza il contatore