jeudi 28 février 2013

Zbrush to Max pourquoi c'est mou ?

    J'ai souvent entendu et eu ce problème, "j'ai sorti une décimation (ou high poly) de zbrush avec mes normales... et quand je rends avec max ma modé est toute mole et je perds beaucoup de détails."

Le problème vient des smooth group, faut savoir que par défaut max import des .obj avec un smooth group commun pour tout les poly. Vous pouvez voir ça dans l'editpoly, face mode, smoothing groups.

Tout les poly on un smooth group a 1.










Donc avant de rendre votre modé sortie de ZBrush pensez bien a "Clear All" les smooth groups.










Voila, c'est bête mais on y pense pas toujours.
En image, un petit comparatif:

 Avec smoothing group a 1.



Sans smoothing group.

La modé reste en peu moche (pas de lighting, shader, texture ..)  mais on peu voir qu'on gagne réellement en dureté et en détails.


vendredi 22 février 2013

la recursivité ou la fonction dans la fonction

Voici mon dernier petit utilitaire écrit en python pour 3ds max (py3dsMax), il s'agit d'une boucle récursive, c'est a dire une boucle infinie qui analyse des "éléments" les un après les autres jusqu’à qu'on lui signal par une "clé" de stopper la boucle.

Par exemple c'est très pratique lorsqu'on a des arbres nodales et qu'on veut effectuer une tache sur chacun de leurs nodes:



 


from Py3dsMax import mxs

#le nouveau nom appliqué a tout les nodes.
newName = "Name"

#je recupere ma selection d'objet.
sel = mxs.selection

#je recupere le nombre de slot du material appilque a ma selection.
idMap = mxs.getNumSubTexmaps(sel[0].material)

#je rename le material
sel[0].material.name = newName + sel[0].material.name 

#Je lance ma fonction recursive.
renameNode(idMap, sel[0].material)


def renameNode(idMap, sel):

 for i in range(1, idMap+1):
  slot = mxs.getSubTexmap(sel, i)
  if slot == None :
   print("empty slot")

  else:
   slot.name = newName + slot.name 
   idMap = mxs.getNumSubTexmaps(slot)
   for i in range(1, idMap+1):
    #je relance ma fonction dans cette meme fonction:
    renameNode(idMap, slot)

lundi 21 janvier 2013

Paroie rocheuses zbrush tuto

    En pleine prod de notre film de fin d'etude "ascension", je laisse de coté le script pour faire du modeling d'environnement avec zbrush.
Vu que notre film se passe en haute montagne il y a donc beaucoup de parois rocheuses, cailloux, roche ... , le meilleur outils que j'ai trouvé c'est  zbrush.

Voici quelques screens de zbrush des modé finals (sans texture, shader basique de zbrush):







Et voici un step by step:

    la modé de base:

    Première passe avec le brush TrimBorder (dans le dossier brush), jouer beaucoup avec le alt:


Puis un passage avec le brush Crumple pour déformer le tout et rendre moins lisse:


On ajoute du détails et de la texture avec le brush Fracture:







Et une dernière passe avec le NoiseMaker, on ajoute un noise et une érosion avec une petite échelle:






Et voila finit ! Plus qu'a faire un shader et texture dans max.



dimanche 18 novembre 2012

Enumerate list python la fin du range.

    J'ai découvert il y a peu de temps une fonction de l'objet list qui existe depuis quelques temps mais qui se fait discrète, elle m'a drôlement simplifier la vie. Cette fonction c'est enumerate(list). Enumerate d'une list retourne un objet pas vraiment exploitable.
 
listA = ["un", "deux", "trois", "quatre", "cinq"]
print (enumerate(listA))
#enumerate object at 0x000000000209A900

La où énumerate est vraiment intéressant c'est son utilisation dans une boucle for. Par item enumerate return un tuple contenant l'index de l'item et l'item lui même:
listA = ["un", "deux", "trois", "quatre", "cinq"]

for i, item in enumerate(listA):
    print (i)
    print (item)


# Result:
0
un
1
deux
2
trois
3
quatre
4
cinq


Voila finit les:
 

for i in range(0, len(listA)):
    print (i)
    print (listA[i])

i = 0
for item in listA:
    print (i)
    print (item)
    i += 1 

Faut avouer que avec enumerate c'est quand même plus propres et plus python like. see ya

dimanche 21 octobre 2012

PyQt parent to main maya window


    Pour parenter sa fenetre pyqt a celle de maya pour pouvoir l'avoir en top et qu'elle se hide avec elle. Il faut récupérer le QMainWindow() et y parenter notre nouvelle fenêtre grasse au module SIP.
Exemple:



import maya.OpenMayaUI as OpenMayaUI
import sip
from PyQt4 import QtCore, QtGui
class window(QtGui.QMainWindow):
    def __init__ (self,        parent = sip.wrapinstance( long( OpenMayaUI.MQtUtil.mainWindow() ), QtCore.QObject )):
        super(window, self).__init__(parent)
        
d = window()
d.show()

lundi 15 octobre 2012

astuce python, compare two variables with set

        Petit astuce python fort pratique ! l'utilisation des variables de type "set". "set" permet de faire des opérations entre variables "set". Voici quelques exemples:


#union
a = set(['a','b','c','d'])
b = set(['d','d','d','d','e','f','g'])
a.union(b)

# Result: set(['a', 'c', 'b', 'e', 'd', 'g', 'f']) #
#remarques: 'd' est stocké qu'une fois dans le nouveau set; attention le set mélanges les valeurs

#différence
a = set(['a','b','c','d','e','f','g'])
b = set(['d','d','d','d','e','f','g'])
a.difference(b)
# Result: set(['a', 'c', 'b']) # 



Il existe beaucoup d'autres opérateurs, pour plus de détails:
 http://docs.python.org/library/sets.html

lundi 17 septembre 2012

PyQt right click button (QPushButton)


    Qt ne propose pas d'event 'right click', du genre mousePressRightEvent() et c'est bien dommage.  Donc c'est a nous de faire ce event, pas vraiment en créant un nouvelle fonction mais en modifiant la fonction mousePressEvent() classique. Pour cela nous devons dériver notre QPushButton a partir d'une nouvelle classe, exemple PushRightButton (le 'Q' étant réservé a Qt).


#
#


#import des modules Qt
from PyQt4.QtGui import *
from PyQt4.QtCore import *

#creation de la class, on precise qu'on derive la class QPushButton entre parentheses
class PushButtonRight (QPushButton):

    #creation du signal emetteur (emet rien pour le moment)
    rightClick = pyqtSignal()


    #creation de notre fontion __init__ avec un arg string pour le nom du futur bouton
    def __init__ (self, string):
        #on integre la classe QPushButton a notre class PushRightButton
        QPushButton.__init__(self, string)

    #modification de la fontion mousePressEvent
    def mousePressEvent (self, event):
        #on integre la fonction QPushButton.mousePressEvent(self, event) a notre fonction PushRightButton.mousePressEvent(self, event)
        QPushButton.mousePressEvent(self, event)

        #condition du click droit
        if event.button() == Qt.RightButton :
            #emittion du signal rightClick
            self.rightClick.emit()
            print ('right click')

#
#


Maintenant il suffit de creer un bouton grace a notre class PushRightButton et de faire la connection:

#
#


butRightClick = PushRightButton('hello')

butRightClick.rightClick.connect(laFuturFonction)

#
#