PDA

Voir la version complète : Coordonnées UV en Coffee



César Vonc
13/05/2010, 00h58
Bonjour,

Je souhaiterais savoir s'il est possible de récupérer les coordonnées UV d'une texture, ou les actions menées dans BP UV Edit.

L'historique de script n'affiche pas certaines fonctions utilisées dans BP, comme le type de projection appliqué ou les transformations.


J'aimerais utiliser le Coffee pour modifier automatiquement la position de mes points dans la vue UV, et par la suite scripter un réducteur de polys qui ne charcute pas le texturage, ou réaliser d'autres modèles de projection automatique.

oli_d
13/05/2010, 11h11
Bon alors là c'est pas du tout ma spécialité, je suis une bille en BP.

Mais pour les uvw, regarde dans la doc du côté de la classe VariableTag ...mais là aussi je ne pourrai pas beaucoup t'aider

César Vonc
20/05/2010, 00h16
J'ai bien trouvé quelque chose dans la doc du côté de UVWStruct, mais c'est en C++, je ne pige pas comment m'en servir pour le Coffee.

J'ai également trouvé ce sujet (http://www.plugincafe.com/forum/printer_friendly_posts.asp?TID=4067), mais toujours en C++.

Quelqu'un sait-il comment l'utiliser ?

oli_d
20/05/2010, 13h58
Je ne crois pas que le SDK du C++ soit très utile pour le COFFEE.

Voilà un bout de code COFFEE qui te permet de lire les coordonnées uvw contenues dans le tag UVW, chaque niveau du tableau correspond au numéro de polygone (i dans mon code):


var doc = GetActiveDocument();
var op =doc->GetActiveObject();
if(!op)return;

var tg;
for(tg=op->GetFirstTag();tg;tg=tg->GetNext()) //Boucle pour parcourir tous les tags de l'objet
{
if(instanceof(tg,UVWTag))//Si on tombe sur un tag uvw on va lire les données
{
var i;
var arr = tg->GetData();//renvoie un tableau avec toutes les coordonnées uvw
for(i=0;i<tg->GetDataCount();i++)//parcours du tableau
{
println(arr[i]); //affichage de la coordonnée uvw
}
}
}

après si tu veux changer les coord uvw, tu changes dans le tableau et tu renvoies au tag via tg->SetData(arr)

voir VariableTag dans la doc COFFEE

César Vonc
21/05/2010, 01h19
Toujours aussi efficace, Oli_D !

Le but ici serait de récupérer l'ID des Points UV à partir d'une sélection de Points.

Alors pour récupérer l'ID d'un point, j'ai trouvé ça :


var sel = op->GetPointSelection();
var totpoints = sel->GetCount();
var ptsID = new(array,totpoints); // Tableau
var i;
var id = 0;
for(i=0; i<op->GetPointCount(); i++) // Je parcours tous les points de l'objet...
{
if(sel->IsSelected(i)) // À la recherche d'un point sélectionné.
{
ptsID[id] = i;
id++;
}
}

Donc l'ID de mes points est ptsID[id] où id serait mon point sélectionné (pour deux points sélectionnés : le premier, id=0 ; le second, id=1, par exemple).

Mais l'ID d'un Point n'est pas la même que celle d'un Point UV (logique), or la fonction GetUVPointSel() ne semble pas marcher en Coffee. :?

oli_d
21/05/2010, 09h56
Petite rectification du code ci-dessus qui est incomplet,

En fait on a pour chaque polygone 4 coordonnées UVW (une par point, si on a un triangle le 3ème point est répété), donc pour lire toutes les données il faut rajouter une boucle interne qui lit les 4 vecteurs :


var doc = GetActiveDocument();
var op =doc->GetActiveObject();
if(!op)return;

var tg;
for(tg=op->GetFirstTag();tg;tg=tg->GetNext()) //Boucle pour parcourir tous les tags de l'objet
{
if(instanceof(tg,UVWTag))//Si on tombe sur un tag uvw on va lire les données
{
var i;
var n;
var cnt = 0;
var arr = tg->GetData();//renvoie un tableau avec toutes les coordonnées uvw
for(i=0;i<tg->GetDataCount();i++)//parcours du tableau
{
println("polygone n° ",i);
for (n=0;n<4;n++) //pour chaque polygone on lit les 4 coordonnées uvw
{
println(" ",arr[cnt]); //affichage de la coordonnée uvw
cnt++;
}
}
}
}

Pour ton problème de points, c'est un peu plus compliqué, car un point peut être rattaché à plusieurs polygones. Donc il faudrait récupérer tous les polygones qui contiennent ce point et retrouver les coordonnées uvw correspondantes à ce point ...

Dans le code normalement la variable i correspond également au numéro de polygone, qui lui-même contient l'identifiant des 4 points ...

Si j'ai le temps j'essaierai, mais pas aujourd'hui, mais essaie c'est un très bon exercice ....

César Vonc
21/05/2010, 13h54
D'accord, donc il faut récupérer l'ID du point, déduire l'ID du polygone rattaché, puis l'ID du Point UV en fonction de celui du polygone.

Pour récupérer l'ID du polygone à partir de celui du point, j'ai fait en comparant les coordonnées des points de tous les polygones avec celui du point sélectionné, ça marche plutôt bien mais je me demande si ce n'est pas un peu lourd :


var doc = GetActiveDocument();
var op = doc->GetActiveObject();
if(!op) return;

var tg;
for(tg=op->GetFirstTag(); tg; tg=tg->GetNext()) // Boucle pour parcourir tous les tags de l'objet
{
if(instanceof(tg, UVWTag)) // Si on tombe sur un tag uvw on va lire les données.
{
var i;
var n;
var cnt = 0;
var arr = tg->GetData(); // Renvoie un tableau avec toutes les coordonnées UVW.
for(i=0; i<tg->GetDataCount(); i++) // Parcours du tableau
{
println("Polygone n° ", i);
for (n=0; n<4; n++) // Pour chaque polygone on lit les 4 coordonnées UVW.
{
println(" ", arr[cnt]); // Affichage de la coordonnée UVW.
cnt++;
}
}
}
}

// Récupération de l'ID des points sélectionnés.
var sel = op->GetPointSelection();
var totpoints = sel->GetCount();
var totpolys = op->GetPolygonCount();
println("Nombre de polygones : ", totpolys);
println("Nombre de points sélectionnés : ", totpoints);
var ptsID = new(array, totpoints); // Tableau
var iden;
var id = 0;
for(iden=0; iden<op->GetPointCount(); iden++) // Je parcours tous les points de l'objet...
{
if(sel->IsSelected(iden)) // À la recherche d'un point sélectionné.
{
ptsID[id] = iden;
println("Sélection n° ", id);
println(" ID du point : ", ptsID[id]);

var coorptsel = op->GetPoint(iden); // Je récupère les coordonées du point sélectionné.
// println(coorptsel);

var pol; // À la recherche des polygones correspondants.
for (pol=0; pol<totpolys; pol++) // Je parcours tous les polygones de l'objet.
{
var poly = op->GetPolygon(pol); // Je récupère le polygone d'incide pol.
var va = op->GetPoint(poly->a); // Puis les coordonnées de chacun de ses points.
var vb = op->GetPoint(poly->b);
var vc = op->GetPoint(poly->c);
var vd = op->GetPoint(poly->d);

if ( (va==coorptsel) || (vb==coorptsel) || (vc==coorptsel) || (vd==coorptsel) ) // Si une de ces coordonnées est égale à celle de mon point sélectionné...
println(" Rattaché au poly d'ID : ", pol); // Récupérer l'ID du polygone.
}
id++;
}
}

J'attaque la suite. :)

César Vonc
22/05/2010, 12h14
J'ai pu récupérer l'ID des points UV à partir de l'ID des polygones, ou plus précisément à partir du point A, B, C ou D de mon polygone.

Si les coordonnées de mon point sélectionné est égal à celle du point A d'un polygone, alors l'indice du point UV de celui-ci est l'ID du polygone × 4 + 0 (+ 1 si c'est le point B, 2 pour le point C et 3 pour le point D).

J'espère que c'est correct, voici le code entier :


var doc = GetActiveDocument();
var op = doc->GetActiveObject();
if(!op) return;

var tg;
// Récupération de l'ID des points sélectionnés.
var sel = op->GetPointSelection();
var totpoints = sel->GetCount();
var totpolys = op->GetPolygonCount();
println("Nombre de polygones : ", totpolys);
println("Nombre de points sélectionnés : ", totpoints);
var ptsID = new(array, totpoints); // Tableau
var iden;
var id = 0;
for(iden=0; iden<op->GetPointCount(); iden++) // Je parcours tous les points de l'objet...
{
if(sel->IsSelected(iden)) // À la recherche d'un point sélectionné.
{
ptsID[id] = iden;
println("Sélection n° ", id);
println(" ID du point : ", ptsID[id]);

var coorptsel = op->GetPoint(iden); // Je récupère les coordonées du point sélectionné.
// println(coorptsel);

var pol; // À la recherche des polygones correspondants.
for (pol=0; pol<totpolys; pol++) // Je parcours tous les polygones de l'objet.
{
var poly = op->GetPolygon(pol); // Je récupère le polygone d'incide pol.
var va = op->GetPoint(poly->a); // Puis les coordonnées de chacun de ses points.
var vb = op->GetPoint(poly->b);
var vc = op->GetPoint(poly->c);
var vd = op->GetPoint(poly->d);

if ( (va==coorptsel) || (vb==coorptsel) || (vc==coorptsel) || (vd==coorptsel) ) // Si une de ces coordonnées est égale à celle de mon point sélectionné...
println(" Rattaché au poly d'ID : ", pol); // Récupérer l'ID du polygone.

for(tg=op->GetFirstTag(); tg; tg=tg->GetNext()) // Boucle pour parcourir toutes les propriétés de l'objet.
{
if(instanceof(tg, UVWTag)) // Si on tombe sur une propriété UVW on va lire les données.
{
var idpuva = (pol*4)+0; // ID du point UV à partir de l'ID du polygone.
var idpuvb = (pol*4)+1;
var idpuvc = (pol*4)+2;
var idpuvd = (pol*4)+3;

if (va==coorptsel) {
println(" ID du point UV : ", idpuva);
var arr = tg->GetData();
println(" ", arr[idpuva]);}

if (vb==coorptsel) {
println(" ID du point UV : ", idpuvb);
var arr = tg->GetData();
println(" ", arr[idpuvb]);}

if (vc==coorptsel) {
println(" ID du point UV : ", idpuvc);
var arr = tg->GetData();
println(" ", arr[idpuvc]);}

if (vd==coorptsel) {
println(" ID du point UV : ", idpuvd);
var arr = tg->GetData();
println(" ", arr[idpuvd]);}
}
}
}
id++;
}
}

Là où je bloque maintenant, c'est pour définir une nouvelle coordonnée à ces points UV comme étant la moyenne de ces coordonnées.
Mais vu qu'il y a un nombre variable de points sélectionnés, de polygones rattachés et de points UV (il peut y en avoir deux pour un seul polygone et pour un seul point sélectionné, si ce polygone est un triangle), j'ai vraiment du mal.

César Vonc
22/05/2010, 15h26
Désolé pour le triple message, je préviens juste que j'ai finalement réussi. :)

Je voulais faire une sorte d'outil Soudure pour l'UVW sans passer par BodyPaint, et ainsi gagner du temps lorsqu'on veut réduire le nombre de polygones d'un objet sans devoir le re-texturer.

L'outil est encore un peu rigide, il n'offre pas d'option concernant la position du point soudé (c'est une bête moyenne des points), mais j'y travaille !

http://img88.imageshack.us/img88/7320/soudureuv.png
2 clics !

Le script est encore un peu brouillon, je le publierai lorsqu'il sera bien propre.

César Vonc
25/05/2010, 16h09
Peut-on récupérer la taille d'un objet ?

J'ai essayé monobjet->GetSize(); , mais ça n'a pas l'air d'être ça.

Pour ceux que ça intéresse, voici le script entier, commenté, avec pas mal d'infos qui sortent dans la console, est-ce que ça peut ralentir le script ?



var doc = GetActiveDocument();
var op = doc->GetActiveObject();
if(!op) return;

var tg;
println("-------------------------------------------------------- Début - Soudure UVW");

// Récupération de l'ID des points sélectionnés.

for(tg=op->GetFirstTag(); tg; tg=tg->GetNext()) // Boucle pour parcourir toutes les propriétés de l'objet.
{
if(instanceof(tg, UVWTag)) // Si on tombe sur une propriété UVW on va lire les données.
{
var sel = op->GetPointSelection(); // Je récupère ma sélection de points.
var totpoints = sel->GetCount(); // Puis son nombre de points.
println("Nombre de points sélectionnés : ", totpoints);

if (totpoints != 0) // S'il y a des points sélectionnés.
{
var totpolys = op->GetPolygonCount();
println("Nombre de polygones : ", totpolys);
println("// Calcul des coordonnées :");

var coef = 0;
var coeff = 1;
var addidpuv = vector(0,0,0);
var moyidpuv = vector(0,0,0);
var addidpuvp = vector(0,0,0);
var moyidpuvp = vector(0,0,0);
var addidpuvpp = vector(0,0,0);
var moyidpuvpp = vector(0,0,0);
var coefp = 0;

var ptsIDUV = new(array, totpolys*4); // Tableau pour l'ID des points UV.
var addpuv = 0;

var ptsID = new(array, totpoints); // Tableau pour l'ID des points.
var iden;
var id = 0;
for(iden=0; iden<op->GetPointCount(); iden++) // Je parcours tous les points de l'objet...
{
if(sel->IsSelected(iden)) // À la recherche d'un point sélectionné.
{
ptsID[id] = iden;
println("Sélection n° ", id);
println(" ID du point : ", ptsID[id]);

var coorptsel = op->GetPoint(iden); // Je récupère les coordonées du point sélectionné.
// println(coorptsel);

var pol; // À la recherche des polygones correspondants.
for (pol=0; pol<totpolys; pol++) // Je parcours tous les polygones de l'objet.
{
var poly = op->GetPolygon(pol); // Je récupère le polygone d'incide pol.
var va = op->GetPoint(poly->a); // Puis les coordonnées de chacun de ses points.
var vb = op->GetPoint(poly->b);
var vc = op->GetPoint(poly->c);
var vd = op->GetPoint(poly->d);

if ( (va==coorptsel) || (vb==coorptsel) || (vc==coorptsel) || (vd==coorptsel) ) // Si une de ces coordonnées est égale à celle de mon point sélectionné...
{
println(" - Rattaché au poly d'ID : ", pol); // Récupérer l'ID du polygone.

var idpuva = (pol*4)+0; // ID du point UV à partir de l'ID du polygone.
var idpuvb = (pol*4)+1;
var idpuvc = (pol*4)+2;
var idpuvd = (pol*4)+3;
coef = 0;
coeff = 1;
addidpuv = vector(0,0,0);
var arr = tg->GetData();

if (va==coorptsel)
{ // Si les coordonées du point du polygone = celles du point sélectionné.
coef = coef + coeff;
addpuv = addpuv + coeff;
ptsIDUV[addpuv] = idpuva; // Je complète le tableau de l'ID des points UV.
println(" Point UV ; a : ", arr[idpuva], " ID : ", idpuva);
addidpuv = addidpuv + arr[idpuva];
}

if (vb==coorptsel)
{
coef = coef + coeff;
addpuv = addpuv + coeff;
ptsIDUV[addpuv] = idpuvb;
println(" Point UV ; b : ", arr[idpuvb], " ID : ", idpuvb);
addidpuv = addidpuv + arr[idpuvb];
}

if (vc==coorptsel)
{
coef = coef + coeff;
addpuv = addpuv + coeff;
ptsIDUV[addpuv] = idpuvc;
println(" Point UV ; c : ", arr[idpuvc], " ID : ", idpuvc);
addidpuv = addidpuv + arr[idpuvc];
}

if (vd==coorptsel)
{
coef = coef + coeff;
addpuv = addpuv + coeff;
ptsIDUV[addpuv] = idpuvd;
println(" Point UV : d : ", arr[idpuvd], " ID : ", idpuvd);
addidpuv = addidpuv + arr[idpuvd];
}

moyidpuv = addidpuv;
if (coef==2) moyidpuv = arr[idpuvc]; // En cas de triangle.
// moyidpuv = vector(addidpuv.x/coef, addidpuv.y/coef, addidpuv.z/coef); // Moyenne des points UV.
println(" Total : ", coef, " Moyenne : ", moyidpuv);
addidpuvp = addidpuvp + moyidpuv;
coefp = coefp + coeff;
}
}
moyidpuvp = vector(addidpuvp.x/coefp, addidpuvp.y/coefp, addidpuvp.z/coefp); // Moyenne des points UV de chaque poylgone.
println(" ");
println(" Total polys rattachés : ", coefp, " ; Moyenne : ", moyidpuvp);

coefp = 0;
addidpuvp = vector(0,0,0);
addidpuvpp = addidpuvpp + moyidpuvp;
println(" Tot sélection : ", totpoints, " ; Cumul sélection : ", addidpuvpp);
println("--");
id++;
}
}
moyidpuvpp = vector(addidpuvpp.x/totpoints, addidpuvpp.y/totpoints, addidpuvpp.z/totpoints); // Moyenne des points UV de chaque sélection.
println("Moyenne sélection : ", moyidpuvpp);
println("--");
println("// Modification des coordonnées :");

// Modification des points UV.

println("Total de points UV : ", addpuv);
var k;

var arr = tg->GetData(); // Je récupère les coordonénes UVW actuelles.
for (k = 1 ; k < addpuv+1 ; k++) // Boucle pour chaque point UV.
{
arr[ptsIDUV[k]] = moyidpuvpp; // J'attribue la nouvelle coordonnée à chacun de ces points.
tg->SetData(arr);
println("ID du point UV n°",k, " : ", ptsIDUV[k]);
}

}
}
}
println("-------------------------------------------------------- Fin - Soudure UVW");
op->Message(MSG_UPDATE);

xs_yann
25/05/2010, 16h55
Pour ceux que ça intéresse, voici le script entier, commenté, avec pas mal d'infos qui sortent dans la console, est-ce que ça peut ralentir le script ?


Oui, beaucoup. Compare par exemple la sortie de :


main(doc,op)
{
var t = time();
var i;
for (i = 0; i < 10000; i++)
{
println("text");
}
println(time() - t);
}


avec :



main(doc,op)
{
var t = time();
var i;
for (i = 0; i < 10000; i++)
{
//println("text");
}
println(time() - t);
}

César Vonc
26/05/2010, 12h19
En effet, on passe de 13 secondes à 1 milliseconde.

(Il semble manquer un ; dans ton premier code).



Une idée pour récupérer la taille d'un objet ?

xs_yann
26/05/2010, 13h16
(Il semble manquer un ; dans ton premier code).


Corrigé merci. :wink:

Pour la taille d'un objet, j'ai fait un script pour calculer la position, la taille et la rotation de la bounding box d'un objet, je te l'envoie par mp.

En gros la taille est la difference du point min et du point max.