PDA

Voir la version complète : Objet UVW



César Vonc
26/12/2011, 18h18
Bonjour,

Voici mon script COFFEE permettant de transformer des coordonnées UVW en un objet polygonal et vice versa.

Pour ceux qui n'aiment pas beaucoup l'interface de bodypaint et qui ont besoin de déplacer les points UV avec précision avec les outils de modélisation de base de c4d, je pense que ce script leur sera utile.


Sélectionnez votre objet, exécutez le script et les coordonnées UVW devrait apparaître sous forme d'un nouvel objet. Sélectionnez-le et relancez le script pour mettre le dépliage UVW de l'objet de base à jour.


Voici le code source, le script est en pièce jointe. Si vous avez des remarques, suggestions, ou trouvé des bogues... n'hésitez pas !



// Objet UVW par César Vonc (www.cesar.vonc.fr)
//v1.1

alerte(message) {
var erreur = new(array, 5);
erreur[0] = "Erreur.";
erreur[1] = "Veuillez sélectionner un objet éditable.";
erreur[2] = "Propriété UVW introuvable.";
erreur[3] = "Objet de base introuvable.";
erreur[4] = "L'objet de base ne correspond pas avec l'objet UVW.";
TextDialog(erreur[message], GEMB_OK);
}

modCoor(v) {
var vz = v.z;
var vy = v.y;
v.z = 1 - vy;
v.y = vz;
v *= 1000;
return v;
}

demodCoor(v) {
var vz = v.z;
var vy = v.y;
v.z = vy;
v.y = 1000 - vz;
v *= 0.001;
return v;
}

objVuvw(doc, op, texte) {
var obj = doc->FindObject(texte + " UVW");
if (obj) {
obj#ID_BASELIST_NAME += "_Ans";
obj#ID_BASEOBJECT_VISIBILITY_EDITOR = 1;
obj#ID_BASEOBJECT_VISIBILITY_RENDER = 1;
}

var uvw;
var tex;
var prop;
for(prop = op->GetFirstTag() ; prop ; prop = prop->GetNext()) {
if (instanceof(prop, UVWTag)) { uvw = prop; continue; }
if (instanceof(prop, TextureTag)) { tex = prop; continue; }
}
if(!instanceof(uvw, UVWTag)) return 2;
//if(!instanceof(tex, textureTag)) return;
var uvwObj = AllocObject(Opolygon);
var texProp = AllocTag(Ttexture);


var uvwTab = uvw->GetData();
var nbPolys = op->GetPolygonCount(); // Nombre de polygones
var nbPts = nbPolys*4; // Nombre de points
var posPts = uvw->GetData(); // Coordonnées des points
var maillage = new(array, nbPts); // Connexion des polygones
var i;
var n = 0; // Nombre réel de points
var tmp = new(array, nbPts);
for (i = 0 ; i < nbPolys ; i++) {
var poly = op->GetPolygon(i);
maillage[i*4] = n;
tmp[n] = i*4;
n++;
maillage[i*4+1] = n;
tmp[n] = i*4+1;
n++;
maillage[i*4+2] = n;
tmp[n] = i*4+2;
n++;
if (poly->c != poly->d) {
maillage[i*4+3] = n;
tmp[n] = i*4+3;
n++;
}
else {
maillage[i*4+3] = n-1;
tmp[n] = i*4+2;
}

posPts[i*4] = modCoor(posPts[i*4]);
posPts[i*4+1] = modCoor(posPts[i*4+1]);
posPts[i*4+2] = modCoor(posPts[i*4+2]);
posPts[i*4+3] = modCoor(posPts[i*4+3]);
}
var posPn = new(array, n);
for (i = 0 ; i < n ; i++) {
posPn[i] = posPts[tmp[i]];
}

var vc = new(VariableChanged); if (!vc) return 0;
vc->Init(0, n);
uvwObj->MultiMessage(MSG_POINTS_CHANGED, vc);
uvwObj->SetPoints(posPn);

var vc2 = new(VariableChanged); if (!vc2) return 0;
vc2->Init(0, nbPolys);
uvwObj->MultiMessage(MSG_POLYGONS_CHANGED, vc2);
uvwObj->SetPolygons(maillage);

doc->AddUndo(UNDO_OBJECT_NEW, uvwObj);
uvwObj#ID_BASELIST_NAME = op#ID_BASELIST_NAME + " UVW";
if(tex) {
texProp#TEXTURETAG_MATERIAL = tex#TEXTURETAG_MATERIAL;
texProp#TEXTURETAG_SIZE = texProp#TEXTURETAG_SIZE * 5;
texProp#TEXTURETAG_POSITION = vector(500, 0, 500);
texProp#TEXTURETAG_ROTATION:VECTOR_Y = 3*pi/2;
texProp#TEXTURETAG_PROJECTION = 2;
uvwObj->InsertTag(texProp, NULL);
}
doc->InsertObject(uvwObj, NULL, NULL);
doc->SetActiveObject(uvwObj);
uvwObj->Message(MSG_UPDATE);
// CallCommand(14023); // Aligner les normales
}

uvwVobj(doc, op, texte) {
var obj = doc->FindObject(texte);
if (!obj) return 3;

var uvw;
var prop;
for(prop = obj->GetFirstTag() ; prop ; prop = prop->GetNext()) {
if (instanceof(prop, UVWTag)) { uvw = prop; break; }
}
if(!instanceof(uvw, UVWTag)) return 2;

var nbPolys = op->GetPolygonCount();
var nbPolysObj = obj->GetPolygonCount();
if (nbPolys != nbPolysObj) { return 4; }

var i;
var uvwPos = new(array, nbPolys*4);
for (i = 0 ; i < nbPolys ; i++) {
var poly = op->GetPolygon(i);
uvwPos[i*4] = demodCoor(op->GetPoint(poly->a));
uvwPos[i*4 + 1] = demodCoor(op->GetPoint(poly->b));
uvwPos[i*4 + 2] = demodCoor(op->GetPoint(poly->c));
if (poly->c != poly->d)
uvwPos[i*4 + 3] = demodCoor(op->GetPoint(poly->d));
else
uvwPos[i*4 + 3] = demodCoor(op->GetPoint(poly->c));
}

doc->AddUndo(UNDO_OBJECT_BASEDATA, uvw);
uvw->SetData(uvwPos);
obj->Message(MSG_UPDATE);
uvw->Message(MSG_UPDATE);
}

main(doc, op)
{
if (!op || instanceof(op, Polygon)) { alerte(1); return; }

var texte = op#ID_BASELIST_NAME;
var posUVW = strstr(texte, " UVW");
var etat;

if (posUVW > 0) {
texte = strmid(texte, 0, posUVW);
etat = uvwVobj(doc, op, texte);
}
else {
etat = objVuvw(doc, op, texte);
}

if (etat) alerte(etat);
}


http://code.vonc.fr/details/s5-00.png

Maj du 28/12/11 : Correction d'un petit bogue.

clemz
26/12/2011, 21h54
waouw merci César :) . j'apprends plein de trucs avec tes pitis tutos ! j'ai jamais vraiment exploré cette partie de créa de polygones etc , en Coffee .

shtl
27/12/2011, 21h36
Ah gééééénial! Merci beaucoup César ! :icon_bouncy:


PS:
Me suis permis de coller un lien sur la page FB de c4d.
Et je pense que ça mérriterai un petit poste sur CGTalk aussi, non?

César Vonc
28/12/2011, 13h18
Ça me fait plaisir, clemz. ^^


C'est quoi la page FB de c4d, shtl ?

Je ne pense pas me créer de compte sur CGTalk, j'aimerais cependant être certain que le script fonctionne parfaitement.


J'ai mis à jour le script, il y avait une petite coquille et je viens d'en trouver une autre :

C4d rame et les objets clignotent lorsqu'on exécute le script sur un objet ayant l'UV maximum, c'est à dire quand tous les polygones UV se superposent.
Je ne vois pas comment régler ce problème, à moins que je ne change les coordonnées de l'axe W pour les polygones UV qui se superposent ; ils se retrouveront ainsi espacés verticalement, comme des sortes de calques.

Cela risque de bien compliquer le script, de devoir détecter si deux polygones se superposent.