PDA

Voir la version complète : Matière Formule (développement)



César Vonc
10/02/2012, 21h56
Bonjour,


Étant donné que j'approuve particulièrement les matières procédurales, je me suis demandé s'il n'y avait pas moyen d'en créer de nouvelles... et apparemment si !


La création d'une matière en Python est abordable grâce à la classe ShaderData, voici mes premiers essais réussis :


http://img832.imageshack.us/img832/4886/matformule.png


Je souhaiterais à terme créer une matière procédurale avec une formule paramétrable.
Cependant, je bloque sur l'interface, je n'arrive pas à créer le moindre paramètre pour ma matière.

La doc à ce sujet (http://chicagoc4d.com/C4DPythonSDK/modules/c4d.plugins/BaseData/NodeData/ShaderData/index.html) reste relativement épurée

J'ai découvert cette page (http://villager-and-c4d.cocolog-nifty.com/blog/2009/10/c4d-channelsh-5.html) en japonais où le nippon arrive à afficher une boîte de dialogue au clique sur la matière, mais j'ai du mal à cerner son code. Quelqu'un a-t-il une idée sur la façon de créer un tableau de paramètres comme ceux des bruits procéduraux ?


Je me suis basé sur l'exemple Py-Fresnel.pyp de la doc, qui peut vous servir de support.



import os
import math

import c4d
from c4d import plugins, bitmaps, utils, documents

MODULE_ID=1028230

class MatFormule(plugins.ShaderData):
def __init__(self):
self.SetExceptionColor(c4d.Vector(1,0,0)) # Couleur si erreur

def formule(self, x, y, z, i):
n = c4d.utils.noise.Noise(c4d.Vector(x, y, z), i)*10
f = math.cos(x+n)
return f

def Output(self, sh, cd):
if cd.vd: # 3d
vec = cd.vd.p * 0.1
v = self.formule(vec.x, vec.y, vec.z, 10)
vec.x = v
vec.y = v
vec.z = v
vec = abs(vec)
return vec
else: # 2d
return c4d.Vector(0.0)

def FreeRender(self, sh):
# Libère la mémoire
return


if __name__=='__main__':
plugins.RegisterShaderPlugin(MODULE_ID, "Formule", 0, MatFormule, "", 0)

yayaprod
10/02/2012, 22h19
Salut,
Je dis rien à chaque fois et je suis en silence mais là c'est trop : t'es un fou furieux du langage Python : :icon_boss:
Hyper balise et balaise comme mec! chapeau bas.
Yaya. °) Merci pour tout ce que tu fais.

Aurety
10/02/2012, 23h33
Woow Cesar, je suis ébloui par tes compétences et ta curiosité. Ca ouvre de belles perspectives quand je vois tes premiers résultats. Je m'installe au chaud pour suivre ca de plus près :icon_bouncy:

valkaari
10/02/2012, 23h59
Pour les données perso dans les interfaces, (et de manière globale) il faut que tu regardes du coté des fichiers de ressources.
(dialog ressources)

Passer par les fichiers ressources ça facilite les mises à jour et les portage multi-langues.

Une piste à suivre (j'ai recrée l'arbo de ton plugin). Mais la fonction pour récupérer la valeur de la donnée n'est clairement pas à la bonne place, elle crée des refresh ce qui ralenti complètement le processus :p

en gros, il faut créer dans le répertoire description les interfaces pour les outils, les shaders, les objets. Pour les fenêtres d'interface tu vas mettre ton fichier dans le répertoire dialogs. (idem pour le répertoire string_fr)

Lorsque tu enregistres ton plugin, tu peux mettre un nom de ressource. Il doit correspondre au nom du fichier sans le .res
Tu as deux fichiers, le .h pour la déclaration des ID et le .res pour l'interface elle même.

Tu peux créer ces fichiers assez facilement avec resEdit (dispo chez maxon).
Sinon faut ouvrir les fichiers déjà existant dans le répertoire ressources de c4d et regarder ^^
Dans la doc c++ faut regarder à dialog Ressources, y a pas mal d'info.


edit : le coup classique d'oublier de lier le fichier.
4480

César Vonc
11/02/2012, 00h32
Oh, merci Val, je regarderai attentivement tout ça demain au petit matin. Je maîtrise encore mal la structure des modules.


Pendant ce temps j'étais en train de longuement faire joujou étudier les propriétés des formules !



http://img838.imageshack.us/img838/4267/matformule0001m.jpg (http://img252.imageshack.us/img252/7374/matformule0001.jpg)

diego1968
11/02/2012, 09h11
Wouahou !:icon_eek::icon_bave: Ton image est superbe ! cette matière est vraiment incroyable…et bravo pour tes recherches sur python :icon_clap:

Sir Gong
11/02/2012, 10h37
Ça ressemble aux shaders de StrataVision en 1847. :icon_mrgreen:

Je suis quand même épaté par tes recherches tous azimuts et tes capacités à développer, chapeau bas ! :icon_prie:

oli_d
11/02/2012, 11h10
ça y'est, on vient de basculer dans l'ère où c'est moi qui vais te demander des conseils en programmation.

Il me semble que tu as vraiment attrapé le virus, en tout cas bravo c'est vraiment du beau boulot

César Vonc
11/02/2012, 14h15
Merci. Je ne suis pas prêt de te détrôner, Oli_d !
J'ai encore beaucoup de mal pour l'interface, j'ai mes trois fichiers :

matformule.h :

#ifndef _matformule_H_
#define _matformule_H_

enum
{
MATFORMULE_SOURCE = 1000,
MATFORMULE_COUL = 1001
};

#endifmatformule.res :

CONTAINER matformule
{
INCLUDE Mpreview;
INCLUDE Xbase;

GROUP ID_SHADERPROPERTIES
{
LONG MATFORMULE_SOURCE { MIN -100000; MAX 100000; }
COLORFIELD MATFORMULE_COUL { }
}
}
matformule.str :

STRINGTABLE matformule
{
MATFORMULE_SOURCE "Source";
MATFORMULE_COUL "Couleur";
}Mais j'ai inévitablement une erreur dans matformule.res à la ligne 9, à cause de mon COLORFIELD ; pourtant c'est ce qu'ils font dans la doc, je pige pas (tout baigne si je remplace COLORFIELD par REAL, sinon).

Les
INCLUDE Mpreview;
INCLUDE Xbase;
inluent quoi, exactement ? Peut-être qu'il m'en manque un pour mon champ couleur.



Édition : Petite mise à jour de l'interface avec l'ajout du contraste et de l'aperçu :

http://img862.imageshack.us/img862/4128/matforminterface.png

valkaari
12/02/2012, 18h17
dans le fichier oLight.res (l'interface d'une lumière de base) pour la couleur ils ont utilisé COLOR LIGHT_COLOR { OPEN; PARENTCOLLAPSE; }

C'est peut être ça qu'il faut prendre, le colorfield étant peut être réservé à une boite de dialogue.

Pour les includes,ça correspond aux informations déjà crée et commune à tous les objets ou textures par exemple.

INCLUDE Obase;

vas rajouter dans ton interface l'onglet "base" d'un objet, avec tous les champs qu'il contient habituellement.

Pour une texture, Xbase et Mpreview, ça doit rajouter l'onglet base d'une texture et la préview matière.

Une fois de plus, j'ai pas spécialement trouvé beaucoup d'info à ce sujet, j'ai tendance à aller voir dans les fichier .res de c4d pour voir comment ils ont fait ^^

César Vonc
12/02/2012, 23h28
En effet, COLOR marche parfaitement, merci !

J'ai regardé d'autres .res et ai découvert

STRING MATFORMULE_CODE
{
CUSTOMGUI MULTISTRING;
PYTHON;
SCALE_V;
}Pour implémenter une zone de texte Python, que je récupère, compile() puis exécute avec exec().

Tout semble bien fonctionner, encore quelques petits réglages et le module sera bientôt prêt. Voici à quoi il ressemble actuellement :

http://img718.imageshack.us/img718/4128/matforminterface.png

Je créerai un sujet bien propre et fournirai quelques codes d'exemple, je pense que les matheux pourront s'en donner à cœur joie !

valkaari
12/02/2012, 23h52
et t'as fais comment pour activer le preview du shader ? que j'évites de chercher ^^'

non ben j'ai rien dit ça marche maintenant -_-'

César Vonc
12/02/2012, 23h59
En fait c'est la même sortie que pour l'affichage 3d, sauf que objet de l'aperçu n'a pas de paramètre vd (VolumeData), donc on récupère les coordonnées des points UVW au lieu de XYZ :



def Output(self, sh, cd):
if cd.vd: # vue 3d
# Points XYZ rendus de l'objet : cd.vd.p
return c4d.Vector(0, 0, 0)

else: # vue 2d et aperçu
# Points UVW rendus de la texture de l'objet : cd.p
return c4d.Vector(0, 0, 0)

Le retour étant la couleur RVB pour chaque pixel rendu.

Ceci dit l'aperçu peut afficher un objet 3d au lieu d'un plan (clic droit dessus).



Je posterai bientôt le code en entier !

tarlack
13/02/2012, 14h43
si tu aimes les textures procédurales, je te recommande ce bouquin (http://www.amazon.com/Texturing-Modeling-Second-Procedural-Approach/dp/0122287304) :) En tout cas, c'est super !

César Vonc
13/02/2012, 18h34
Ah dommage que ce livre ne soit pas en français, tarlack, il a pourtant l'air intéressant.


Voici donc la première version bêta, avec un fichier d'exemple.

Le dossier matformule est à placer dans le dossier plugin de c4d.


J'ai remarqué que vous étiez plus attentifs avec des images. ^^

http://img830.imageshack.us/img830/2458/matformule0002m.jpg (http://img717.imageshack.us/img717/6163/matformule0002.jpg)

http://img263.imageshack.us/img263/381/matformule0003m.jpg (http://img839.imageshack.us/img839/2457/matformule0003.jpg)

http://img29.imageshack.us/img29/350/matformule0004m.jpg (http://img513.imageshack.us/img513/9263/matformule0004.jpg)



import os
import math
import c4d
from c4d import plugins, Vector
from c4d.utils.noise import Noise
from math import *

MODULE_ID = 1028230

class MatFormule(plugins.ShaderData):
tps = 0
ech = 0.1
echxyz = Vector(1, 1, 1)
contra = 0
lumi = 0
cola = Vector(0, 0, 0)
colb = Vector(1, 1, 1)
colc = Vector(1, 0, 0)
codetxt = 'n = Noise(Vector(x, y, z), (t+cos(x)+cos(y)+cos(z))*10)\nr = v = b = n'
code = compile(codetxt, '<string>', 'exec')
mode = 1

def Init(self, node):
donnees = node.GetDataInstance()
donnees.SetReal(1000, self.tps)
donnees.SetReal(1001, self.ech)
donnees.SetVector(1003, self.echxyz)
donnees.SetReal(1002, self.contra)
donnees.SetReal(1006, self.lumi)
donnees.SetVector(1004, self.cola)
donnees.SetVector(1005, self.colb)
donnees.SetString(1007, self.codetxt)
donnees.SetVector(1008, self.colc)
donnees.SetLong(1010, self.mode)
return True

def recup(self, sh):
donnees = sh.GetDataInstance()
self.tps = donnees.GetReal(1000)
self.ech = donnees.GetReal(1001)
self.echxyz = donnees.GetVector(1003)
self.contra = donnees.GetReal(1002)
self.lumi = donnees.GetReal(1006)
self.cola = donnees.GetVector(1004)
self.colb = donnees.GetVector(1005)
txt = donnees.GetString(1007)
self.colc = donnees.GetVector(1008)
self.SetExceptionColor(self.colc)
self.codetxt = txt
self.code = compile(txt, '<string>', 'exec')
self.mode = donnees.GetLong(1010)

def InitRender(self, sh, irs):
self.recup(sh)
return 0

def Output(self, sh, cd):
if cd.vd and self.mode is 1: # 3d
vec = cd.vd.p * self.ech
else: # 2d et aperçu
if self.mode is 0:
vec = (cd.p) * 100 * self.ech # Coordonnées UVW
else:
vec = (cd.p-0.5) * 100 * self.ech # Coordonnées UVW

x = vec.x * self.echxyz.x
y = vec.y * self.echxyz.y
z = vec.z * self.echxyz.z
tu = cd.p.x
tv = cd.p.y
tw = cd.p.z
t = self.tps
r = v = b = 0

exec self.code

vec = Vector(r, v, b)
dif = self.colb - self.cola
vec.x = dif.x * vec.x + self.cola.x
vec.y = dif.y * vec.y + self.cola.y
vec.z = dif.z * vec.z + self.cola.z
vec = ((vec-0.5) * (self.contra + 1)) + 0.5 + self.lumi
return vec

def FreeRender(self, sh): # Libère la mémoire
return

if __name__=='__main__':
plugins.RegisterShaderPlugin(MODULE_ID, "Formule", 0, MatFormule, "matformule", 0)
Le code perso s'ajoute automatiquement là où se trouve exec self.code, au sein même de la fonction Output(), donc toutes les variables de cette fonction sont utilisables dans votre code (si vous utiliser cd.vd (http://chicagoc4d.com/C4DPythonSDK/modules/c4d.modules/render/BaseVolumeData/index.html#c4d.modules.render.BaseVolumeData) , vérifiez impérativement qu'il existe).

Aurety
13/02/2012, 19h00
pfiou c'est juste épique comme thread ! Merci César, tes procédurales sont à tomber !:icon_clap:

oli_d
13/02/2012, 19h06
respect :icon_prie:

En plus de ton plugin et de ton code, la matière procédurale pour le ciel est à tomber, merci pour le partage.

César Vonc
13/02/2012, 19h17
Je pense qu'il y a quand même moyen de faire plus simple, pour le ciel. N'oubliez pas de renommer les matériaux, hein ! :-P exemple mis à jour, ni vu ni connu.

valkaari
14/02/2012, 14h00
Bravo, tu progresses super vite ^^


T'as le droit aux codes correspondant aux caractères latin.


é è ç à ê ë
\u00E9 \u00E8 \u00E7 \u00E0 \u00EA \u00EB


Ce qui donne "Luminosit\u00E8" dans le fichier .str

César Vonc
15/02/2012, 14h53
Ah d'accord, je me disais aussi, le fichier str ne marche qu'en ANSI et non en unicode.


J'ai ajouté deux petites cases à cocher pour limiter ou non la valeur minimale maximale de la couleur. Car j'ai remarqué qu'un noir avec une valeur négative pouvait illuminer du noir dans le canal luminescence !

De la même manière, un blanc avec une valeur supérieure à 1 placée dans le canal couleur équivaut à sa couleur -1 dans le canal luminescence.


http://img705.imageshack.us/img705/6418/image2tzc.png
De cette manière, on évite d'avoir des surprises.


Je bloque en revanche pour récupérer les coordonnées de l'objet en cours de rendu, pour pouvoir proposer d'autres espaces que Monde et UV, car en Monde, les valeurs x y z sont absolues, or j'aimerais récupérer les relatives.

Quelque chose me dit que c'est dans c4d.modules.render.BaseVolumeData (http://chicagoc4d.com/C4DPythonSDK/modules/c4d.modules/render/BaseVolumeData/index.html#c4d.modules.render.BaseVolumeData), mais je n'arrive pas à trouver où.

Capt_Chester
15/02/2012, 16h04
Trés intéressant tes recherches sur les procedurals césar, bravo bravo :thumbup1:
Oops, je m'installe si cela ne te dérange pas.
Bien à toi

istef
16/02/2012, 16h31
ça y'est, on vient de basculer dans l'ère où c'est moi qui vais te demander des conseils en programmation.

C'est dans quel épisode déjà ou y'a un passage du genre :

"c'est ainsi que le jeune apprenti Jedi, utilisant la force à ses dépends, terrassa son vieux maître..." :icon_mrgreen:

Terrible ce thread, superbes les textures et les moyens employés pour les générer >> Big up' :icon_clap:

César Vonc
19/02/2012, 17h41
Merci bien, je garderai ce sujet pour le développement. La première version est disponible !

http://frenchcinema4d.fr/showthread.php?74119-Mati%E8re-Formule

Loriel
20/02/2012, 04h01
Terrible tous ça :icon_eek::icon_eek:
Merci !:thumbup1: